Commit 03149702 authored by Hanadi's avatar Hanadi
Browse files

Initial Commit

parents
# Created by https://www.gitignore.io
### Intellij ###
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm
*.iml
## Directory-based project format:
.idea/
# if you remove the above rule, at least ignore the following:
# User-specific stuff:
# .idea/workspace.xml
# .idea/tasks.xml
# .idea/dictionaries
# Sensitive or high-churn files:
# .idea/dataSources.ids
# .idea/dataSources.xml
# .idea/sqlDataSources.xml
# .idea/dynamic.xml
# .idea/uiDesigner.xml
# Gradle:
# .idea/gradle.xml
# .idea/libraries
# Mongo Explorer plugin:
# .idea/mongoSettings.xml
## File-based project format:
*.ipr
*.iws
## Plugin-specific files:
# IntelliJ
/out/
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
### Node ###
# Logs
logs
*.log
# Runtime data
pids
*.pid
*.seed
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# node-waf configuration
.lock-wscript
# Compiled binary addons (http://nodejs.org/api/addons.html)
build/Release
# Dependency directory
# https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git
node_modules
# Traffic History Job
## Requirements
* `node: ^14.8.0`
* `npm: ^6.14.8`
## Configuration
1. Run FROST Server making sure that it uses String Ids, see [`docker-compose.example.yaml`](docker-compose.example.yaml).
2. Export Here API Key `HERE_API_KEY` and FROST server url `FROST_URL` (with version postfix) as environment variables, e.g.
```shell
export HERE_API_KEY=yYTMvf0L2oXCvETw6FLzNnr-GjfEd_TO6Fv_YG-v7ps
export FROST_URL=http://localhost:8080/FROST-Server/v1.1
```
3. Install dependencies:
```shell
npm install
```
3. For development, run `npm start` to start a `ts-node` server.
4. For production:
```shell
npm run build
node build/index.js
```
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const express_1 = __importDefault(require("express"));
const node_cron_1 = __importDefault(require("node-cron"));
const HereClient_1 = require("./src/here/HereClient");
const FrostClient_1 = require("./src/frost/FrostClient");
const logger_1 = require("./src/logger/logger");
const app = express_1.default();
const PORT = 8089;
const geoProximity = {
latitude: 48.791348,
longitude: 9.190342,
distance: 3000
};
if (!process.env.HERE_API_KEY) {
throw new Error("HERE_API_KEY environment variable should be present!");
}
if (!process.env.FROST_URL) {
throw new Error("FROST_URL environment variable should be present!");
}
const hereClient = new HereClient_1.HereClient(process.env.HERE_API_KEY);
const frostClient = new FrostClient_1.FrostClient(process.env.FROST_URL);
function triggerJob(forceUpdateLocations = false) {
return __awaiter(this, void 0, void 0, function* () {
const now = new Date().getTime();
return hereClient.flow(geoProximity)
.then(flowResponse => frostClient.mapAndInsertHereFlowResponse(flowResponse, forceUpdateLocations))
.then(insertedObservations => ({
status: 200,
success: true,
millis: new Date().getTime() - now,
insertedObservations
}))
.catch((err) => {
logger_1.error(err.message, err);
return Object.assign(Object.assign({}, err), { insertedObservations: "Unknown", status: 500, success: false, message: err.message, name: err.name, stack: err.stack, millis: new Date().getTime() - now });
});
});
}
// Routes
app.get("/", (req, res) => res.send("Healthy!"));
app.get("/here", (req, res) => {
hereClient.flow(geoProximity)
.then(body => res.send(body))
.catch(err => console.error(err));
});
app.get("/trigger-job", (req, res) => {
logger_1.info("Received trigger-job request");
const forceUpdateLocations = !!req.query.forceUpdateLocations;
triggerJob(forceUpdateLocations).then(result => {
res.status(result.status).send(result);
logger_1.info(`trigger-job request completed after ${result.millis} ms with status ${result.status}.`);
});
});
node_cron_1.default.schedule("*/5 * * * *", () => {
logger_1.info("Triggering job");
triggerJob().then(result => {
if (result.success)
logger_1.info(`Job executed after ${result.millis} ms. Inserted observations: ${result.insertedObservations}.`);
else
logger_1.info(`Job execution failed after ${result.millis} ms.`);
});
});
// Start Application
app.listen(PORT, () => {
logger_1.info(`⚡️[server]: Server is running at http://localhost:${PORT}`);
});
//# sourceMappingURL=index.js.map
\ No newline at end of file
{"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"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"}
\ No newline at end of file
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
//# sourceMappingURL=DataTypes.js.map
\ No newline at end of file
{"version":3,"file":"DataTypes.js","sourceRoot":"","sources":["../../../src/frost/DataTypes.ts"],"names":[],"mappings":""}
\ No newline at end of file
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.FrostClient = void 0;
const node_fetch_1 = __importDefault(require("node-fetch"));
const logger_1 = require("../logger/logger");
const THINGS_PATH = "Things";
const LOCATIONS_PATH = "Locations";
const FEATURES_OF_INTEREST_PATH = "FeaturesOfInterest";
const DATASTREAMS_PATH = "Datastreams";
const OBSERVATIONS_PATH = "Observations";
const SENSORS_PATH = "Sensors";
const OBSERVED_PROPERTIES_PATH = "ObservedProperties";
const getPathFromType = (type) => {
switch (type) {
case "thing":
return THINGS_PATH;
case "location":
return LOCATIONS_PATH;
case "featureOfInterest":
return FEATURES_OF_INTEREST_PATH;
case "datastream":
return DATASTREAMS_PATH;
case "observation":
return OBSERVATIONS_PATH;
case "sensor":
return SENSORS_PATH;
case "observedProperty":
return OBSERVED_PROPERTIES_PATH;
}
throw new Error(`Unknown type ${type}!`);
};
const DEFAULT_PROJECTION = ["@iot.id"];
class FrostClient {
constructor(baseUrl) {
this.baseUrl = baseUrl;
// Initialize Here sensor and Speed observed property if they are not already inserted
this.insertItemIfNotExists("sensor", {
"@iot.id": "here",
name: "Here",
description: "Here - Traffic Flow API",
encodingType: "text/html",
metadata: "https://developer.here.com/documentation/traffic/dev_guide/topics_v6.1/example-flow.html"
})
.then(inserted => {
if (inserted)
console.log("Here sensor was inserted.");
})
.catch(err => console.error(err));
this.insertItemIfNotExists("observedProperty", {
"@iot.id": "speed",
name: "Speed",
definition: "http://www.qudt.org/qudt/owl/1.0.0/quantity/Instances.html#Speed",
description: "The Speed."
})
.then(inserted => {
if (inserted)
console.log("Speed observed property was inserted.");
})
.catch(err => console.error(err));
}
/**
* Returns the first thing with the specified id, or null if not found.
* @param id
* @param projection
*/
getSingleThingById(id, projection) {
return __awaiter(this, void 0, void 0, function* () {
return this.getSingleItemById("thing", id, projection);
});
}
/**
* Returns the first location with the specified id, or null if not found.
* @param id
* @param projection
*/
getSingleLocationById(id, projection) {
return __awaiter(this, void 0, void 0, function* () {
return this.getSingleItemById("location", id, projection);
});
}
/**
* Returns the first feature of interest with the specified id, or null if not found.
* @param id
* @param projection
*/
getSingleFeatureOfInterestById(id, projection) {
return __awaiter(this, void 0, void 0, function* () {
return this.getSingleItemById("featureOfInterest", id, projection);
});
}
getSingleDatastreamById(id, projection) {
return __awaiter(this, void 0, void 0, function* () {
return this.getSingleItemById("datastream", id, projection);
});
}
/**
* Returns the number of inserted observations
* @param hereFlow
* @param forceUpdateLocations
*/
mapAndInsertHereFlowResponse(hereFlow, forceUpdateLocations = false) {
return __awaiter(this, void 0, void 0, function* () {
const data = hereFlow.RWS
.flatMap(rws => rws.RW)
.flatMap(rw => {
const timeStamp = rw.PBT;
const locationsAndResults = rw.FIS
.flatMap(fis => fis.FI)
.map(fi => {
var _a, _b, _c;
const thingId = `${rw.LI}-${fi.TMC.DE}-${fi.TMC.PC}`;
const thingDescription = `${rw.DE} direction to ${fi.TMC.DE}`;
const thing = {
"@iot.id": thingId,
name: thingId,
description: thingDescription
};
const location = {
"@iot.id": thingId,
name: thingId,
description: thingDescription,
encodingType: "application/vnd.geo+json",
location: {
type: "MultiLineString",
coordinates: fi.SHP
.map(v => v.value.toString())
.map(str => str
.trim()
.split(" ")
.map(coord => coord.split(",").reverse().map(x => +x)))
},
properties: {
length: fi.TMC.LE //In Kilometers
},
Things: [{
"@iot.id": thingId
}],
};
const featureOfInterest = {
"@iot.id": location["@iot.id"],
name: location.name,
description: location.description,
encodingType: location.encodingType,
feature: location.location,
properties: location.properties,
};
const speed = (_a = fi.CF[0]) === null || _a === void 0 ? void 0 : _a.SP;
const confidence = (_b = fi.CF[0]) === null || _b === void 0 ? void 0 : _b.CN;
const jamFactor = (_c = fi.CF[0]) === null || _c === void 0 ? void 0 : _c.JF;
return { thing, location, featureOfInterest, timeStamp, speed, confidence, jamFactor };
})
.filter(data => !!data.speed); // if failed to obtain speed data, don't consider it
/***** Log if ID repetitions Found *****/
Object.entries(locationsAndResults.map(data => data.featureOfInterest["@iot.id"])
.reduce(function (prev, cur) {
prev[cur] = (prev[cur] || 0) + 1;
return prev;
}, {}))
.forEach(([foiId, repetitions]) => {
if (repetitions > 1) {
console.error(`FeaturesOfInterest: ${foiId} is repeated ${repetitions} times`);
}
});
/***** *************************** *****/
return locationsAndResults;
});
return Promise.all(data.map(roadwayData => {
const datastreamId = `here-${roadwayData.thing["@iot.id"]}`;
return this.insertItemIfNotExists("thing", roadwayData.thing)
.then(() => {
const datastream = {
"@iot.id": datastreamId,
name: datastreamId,
description: `Speed readings from Here for roadway ${roadwayData.thing.description}`,
observationType: "http://www.opengis.net/def/observationType/OGC-OM/2.0/OM_Measurement",
unitOfMeasurement: {
name: "Kilometers per hour",
symbol: "km/h",
definition: "http://www.qudt.org/qudt/owl/1.0.0/unit/Instances.html#KilometerPerHour"
},
ObservedProperty: {
"@iot.id": "speed"
},
Sensor: {
"@iot.id": "here"
},
Thing: {
"@iot.id": roadwayData.thing["@iot.id"]
},
};
return this.insertItemIfNotExists("datastream", datastream);
})
.then(() => this.insertItemIfNotExists("location", roadwayData.location, forceUpdateLocations))
.then(() => this.insertItemIfNotExists("featureOfInterest", roadwayData.featureOfInterest, forceUpdateLocations))
.then(() => {
const observation = {
phenomenonTime: roadwayData.timeStamp,
result: roadwayData.speed,
resultQuality: roadwayData.confidence,
resultTime: roadwayData.timeStamp,
FeatureOfInterest: {
"@iot.id": roadwayData.featureOfInterest["@iot.id"]
},
Datastream: {
"@iot.id": datastreamId
},
parameters: {
jamFactor: roadwayData.jamFactor
}
};
return this.insertItem("observation", observation);
})
.then(() => 1);
})).then(length => length.reduce((a, b) => a + b, 0));
});
}
insertItemIfNotExists(type, frostItemWithId, forceUpdate = false) {
return __awaiter(this, void 0, void 0, function* () {
const existingThing = yield this.getSingleItemById(type, frostItemWithId["@iot.id"]);
if (existingThing && forceUpdate) {
logger_1.info(`Force updating item ${frostItemWithId["@iot.id"]} with type ${type}`);
return this.updateItem(type, frostItemWithId);
}
if (existingThing)
return false;
return this.insertItem(type, frostItemWithId);
});
}
insertItem(type, frostItem) {
return __awaiter(this, void 0, void 0, function* () {
// if (type == "location")
// console.debug(`inserting item with type ${type}`);
const path = getPathFromType(type);
let url = `${this.baseUrl}/${path}`;
return node_fetch_1.default(url, {
method: "POST",
body: JSON.stringify(frostItem)
})
.then(res => {
if (!res.ok) {
console.error(`Error inserting item ${JSON.stringify(frostItem)} with type ${type}`);
res.text().then(text => console.error(text));
const err = new Error(`Error inserting item ${JSON.stringify(frostItem)} with type ${type}`);
err.name = "COULD_NOT_INSERT_ITEM";
throw err;
}
return res.ok;
});
});
}
updateItem(type, frostItem) {
var _a;
return __awaiter(this, void 0, void 0, function* () {
// if (type == "location")
// console.debug(`inserting item with type ${type}`);
const path = getPathFromType(type);
const encodedId = (_a = frostItem["@iot.id"]) === null || _a === void 0 ? void 0 : _a.split("/").map(x => encodeURIComponent(x)).join("/");
let url = `${this.baseUrl}/${path}('${encodedId}')`;
return node_fetch_1.default(url, {
method: "PATCH",
body: JSON.stringify(frostItem)
})
.then(res => {
if (!res.ok) {
console.error(`Error updating item ${JSON.stringify(frostItem)} with type ${type}`);
res.text().then(text => console.error(text));
const err = new Error(`Error inserting item ${JSON.stringify(frostItem)} with type ${type}`);
err.name = "COULD_NOT_INSERT_ITEM";
throw err;
}
return res.ok;
});
});
}
getSingleItemById(type, id, projection = DEFAULT_PROJECTION) {
return __awaiter(this, void 0, void 0, function* () {
const path = getPathFromType(type);
const params = Object.assign({ "$filter": `id eq '${id}'`, "$top": 1 }, (projection ? { "$select": projection === null || projection === void 0 ? void 0 : projection.join(",") } : {}));
return this.get(path, params).then(res => res.value[0]);
});
}
get(urlPath, params) {
return __awaiter(this, void 0, void 0, function* () {
let url = `${this.baseUrl}/${urlPath}`;
if (!params)
params = {};
if (Object.keys(params)) {
url += "?";
url += Object.entries(params)
.map(([key, value]) => [key, encodeURIComponent(value)])
.map(([key, value]) => `${key}=${value}`)
.join("&");
}
return node_fetch_1.default(url)
.then(res => res.json())
.then(json => {
// console.debug(`Getting url "${url}"`);
// console.debug(json);
return json;
});
});
}
}
exports.FrostClient = FrostClient;
//# sourceMappingURL=FrostClient.js.map
\ No newline at end of file
{"version":3,"file":"FrostClient.js","sourceRoot":"","sources":["../../../src/frost/FrostClient.ts"],"names":[],"mappings":"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"}
\ No newline at end of file
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
//# sourceMappingURL=DataTypes.js.map
\ No newline at end of file
{"version":3,"file":"DataTypes.js","sourceRoot":"","sources":["../../../src/here/DataTypes.ts"],"names":[],"mappings":""}
\ No newline at end of file
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.HereClient = void 0;
const node_fetch_1 = __importDefault(require("node-fetch"));
const BASE_URL = "https://traffic.ls.hereapi.com";
const TRAFFIC_PATH = "traffic/6.1";
class HereClient {
constructor(apiKey) {
this.apiKey = apiKey;
}
flow(position, units = "metric") {
return __awaiter(this, void 0, void 0, function* () {
const prox = `${position.latitude},${position.longitude},${position.distance}`;
const urlPath = `${TRAFFIC_PATH}/flow.json`;
return this.get(urlPath, { prox, units });
});
}
get(urlPath, params) {
return __awaiter(this, void 0, void 0, function* () {
let url = `${BASE_URL}/${urlPath}`;
if (!params)
params = {};
params.apiKey = this.apiKey;
params.responseattributes = "shape";
url += "?";
url += Object.entries(params)
.map(([key, value]) => `${key}=${value}`)
.join("&");
return node_fetch_1.default(url).then(res => res.json());
});
}
}
exports.HereClient = HereClient;
//# sourceMappingURL=HereClient.js.map
\ No newline at end of file
{"version":3,"file":"HereClient.js","sourceRoot":"","sources":["../../../src/here/HereClient.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,4DAA+B;AAG/B,MAAM,QAAQ,GAAG,gCAAgC,CAAC;AAClD,MAAM,YAAY,GAAG,aAAa,CAAC;AAEnC,MAAa,UAAU;IACnB,YACY,MAAc;QAAd,WAAM,GAAN,MAAM,CAAQ;IACvB,CAAC;IAEE,IAAI,CAAC,QAAsB,EAAE,QAAmB,QAAQ;;YAC1D,MAAM,IAAI,GAAG,GAAG,QAAQ,CAAC,QAAQ,IAAI,QAAQ,CAAC,SAAS,IAAI,QAAQ,CAAC,QAAQ,EAAE,CAAC;YAC/E,MAAM,OAAO,GAAG,GAAG,YAAY,YAAY,CAAC;YAC5C,OAAO,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,EAAC,IAAI,EAAE,KAAK,EAAC,CAAC,CAAC;QAC5C,CAAC;KAAA;IAEa,GAAG,CAAC,OAAe,EAAE,MAAiC;;YAChE,IAAI,GAAG,GAAG,GAAG,QAAQ,IAAI,OAAO,EAAE,CAAC;YACnC,IAAI,CAAC,MAAM;gBACP,MAAM,GAAG,EAAE,CAAC;YAChB,MAAM,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;YAC5B,MAAM,CAAC,kBAAkB,GAAG,OAAO,CAAC;YACpC,GAAG,IAAI,GAAG,CAAC;YACX,GAAG,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC;iBACxB,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,IAAI,KAAK,EAAE,CAAC;iBACxC,IAAI,CAAC,GAAG,CAAC,CAAC;YACf,OAAO,oBAAK,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC;QAC9C,CAAC;KAAA;CACJ;AAvBD,gCAuBC"}
\ No newline at end of file
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.debug = exports.error = exports.info = void 0;
const log = (text, logType) => {
const time = new Date().toISOString();
console.log(`${time} ${logType} ${text}`);
};
const info = (text) => log(text, "INFO");
exports.info = info;
const error = (text, err) => {
log(text, "ERROR");
if (err)
console.error(err);
};
exports.error = error;
const debug = (text) => log(text, "DEBUG");
exports.debug = debug;
//# sourceMappingURL=logger.js.map
\ No newline at end of file
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../../src/logger/logger.ts"],"names":[],"mappings":";;;AAAA,MAAM,GAAG,GAAG,CAAC,IAAY,EAAE,OAAmC,EAAE,EAAE;IAC9D,MAAM,IAAI,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IACtC,OAAO,CAAC,GAAG,CAAC,GAAG,IAAI,IAAI,OAAO,IAAI,IAAI,EAAE,CAAC,CAAC;AAC9C,CAAC,CAAC;AACK,MAAM,IAAI,GAAG,CAAC,IAAY,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;AAA3C,QAAA,IAAI,QAAuC;AACjD,MAAM,KAAK,GAAG,CAAC,IAAY,EAAE,GAAW,EAAE,EAAE;IAC/C,GAAG,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IACnB,IAAI,GAAG;QACH,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;AAC3B,CAAC,CAAC;AAJW,QAAA,KAAK,SAIhB;AACK,MAAM,KAAK,GAAG,CAAC,IAAY,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;AAA7C,QAAA,KAAK,SAAwC"}
\ No newline at end of file
version: '3.1'
services:
web:
image: fraunhoferiosb/frost-server:latest
environment:
- serviceRootUrl=http://localhost:8080/FROST-Server
- http_cors_enable=true
- http_cors_allowed.origins=*
- mqtt.WebsocketPort=9876
- persistence_db_driver=org.postgresql.Driver
- persistence_db_url=jdbc:postgresql://database:5432/sensorThing
- persistence_db_username=sensorThing
- persistence_db_password=sensorThing
- persistence_autoUpdateDatabase=true
- plugins.openApi.enable=true
- persistence.idGenerationMode=ServerAndClientGenerated
- persistence.persistenceManagerImplementationClass=de.fraunhofer.iosb.ilt.frostserver.persistence.pgjooq.imp.PostgresPersistenceManagerString
ports:
- 8080:8080
- 1883:1883
- 9876:9876
depends_on:
- database_setup
database:
image: postgis/postgis:11-2.5-alpine
ports:
- 5432:5432
environment:
- POSTGRES_DB=sensorThing
- POSTGRES_USER=sensorThing
- POSTGRES_PASSWORD=sensorThing
volumes:
- postgis_volume:/var/lib/postgresql/data
database_setup:
image: postgis/postgis:11-2.5-alpine
environment:
- PGPASSWORD=sensorThing
command:
- /bin/bash
- -c
- |
sleep 5
echo 'CREATE EXTENSION "uuid-ossp";' | psql -h database -p 5432 -U sensorThing
links:
- database
volumes:
postgis_volume:
import express from "express";
import cron from "node-cron";
import {HereClient} from "./src/here/HereClient";
import {FrostClient} from "./src/frost/FrostClient";
import {GeoProximity} from "./src/here/DataTypes";
import {error, info} from "./src/logger/logger";
const app = express();
const PORT = 8089;
const geoProximity: GeoProximity = {
latitude: 48.791348,
longitude: 9.190342,
distance: 3000
};
if (!process.env.HERE_API_KEY) {
throw new Error("HERE_API_KEY environment variable should be present!");
}
if (!process.env.FROST_URL) {
throw new Error("FROST_URL environment variable should be present!");
}
const hereClient = new HereClient(process.env.HERE_API_KEY);
const frostClient = new FrostClient(process.env.FROST_URL);
async function triggerJob(forceUpdateLocations: boolean = false) {
const now = new Date().getTime();
return hereClient.flow(geoProximity)
.then(flowResponse => frostClient.mapAndInsertHereFlowResponse(flowResponse, forceUpdateLocations))
.then(insertedObservations => ({
status: 200,
success: true,
millis: new Date().getTime() - now,
insertedObservations
}))
.catch((err: Error) => {
error(err.message, err);
return {
...err,
insertedObservations: "Unknown",
status: 500,
success: false,
message: err.message,
name: err.name,
stack: err.stack,
millis: new Date().getTime() - now
};
});
}
// Routes
app.get("/", (req, res) => res.send("Healthy!"));
app.get("/here", (req, res) => {
hereClient.flow(geoProximity)
.then(body => res.send(body))
.catch(err => console.error(err));
});
app.get("/trigger-job", (req, res) => {
info("Received trigger-job request");
const forceUpdateLocations = !!req.query.forceUpdateLocations
triggerJob(forceUpdateLocations).then(result => {
res.status(result.status).send(result);
info(`trigger-job request completed after ${result.millis} ms with status ${result.status}.`);
});
});
cron.schedule("*/5 * * * *", () => {
info("Triggering job");
triggerJob().then(result => {
if (result.success)
info(`Job executed after ${result.millis} ms. Inserted observations: ${result.insertedObservations}.`);
else
info(`Job execution failed after ${result.millis} ms.`);
});
});
// Start Application
app.listen(PORT, () => {
info(`⚡️[server]: Server is running at http://localhost:${PORT}`);
});
{
"name": "traffic-history-job",
"version": "1.0.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
"@sindresorhus/is": {
"version": "0.14.0",
"resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz",
"integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==",
"dev": true
},
"@szmarczak/http-timer": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz",
"integrity": "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==",
"dev": true,
"requires": {
"defer-to-connect": "^1.0.1"
}
},
"@types/body-parser": {
"version": "1.19.0",
"resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.0.tgz",
"integrity": "sha512-W98JrE0j2K78swW4ukqMleo8R7h/pFETjM2DQ90MF6XK2i4LO4W3gQ71Lt4w3bfm2EvVSyWHplECvB5sK22yFQ==",
"dev": true,
"requires": {
"@types/connect": "*",
"@types/node": "*"
}
},
"@types/connect": {
"version": "3.4.34",
"resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.34.tgz",
"integrity": "sha512-ePPA/JuI+X0vb+gSWlPKOY0NdNAie/rPUqX2GUPpbZwiKTkSPhjXWuee47E4MtE54QVzGCQMQkAL6JhV2E1+cQ==",
"dev": true,
"requires": {
"@types/node": "*"
}
},
"@types/express": {
"version": "4.17.9",
"resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.9.tgz",
"integrity": "sha512-SDzEIZInC4sivGIFY4Sz1GG6J9UObPwCInYJjko2jzOf/Imx/dlpume6Xxwj1ORL82tBbmN4cPDIDkLbWHk9hw==",
"dev": true,
"requires": {
"@types/body-parser": "*",
"@types/express-serve-static-core": "*",
"@types/qs": "*",
"@types/serve-static": "*"
}
},
"@types/express-serve-static-core": {
"version": "4.17.17",
"resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.17.tgz",
"integrity": "sha512-YYlVaCni5dnHc+bLZfY908IG1+x5xuibKZMGv8srKkvtul3wUuanYvpIj9GXXoWkQbaAdR+kgX46IETKUALWNQ==",
"dev": true,
"requires": {
"@types/node": "*",
"@types/qs": "*",
"@types/range-parser": "*"
}
},
"@types/mime": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/@types/mime/-/mime-2.0.3.tgz",
"integrity": "sha512-Jus9s4CDbqwocc5pOAnh8ShfrnMcPHuJYzVcSUU7lrh8Ni5HuIqX3oilL86p3dlTrk0LzHRCgA/GQ7uNCw6l2Q==",
"dev": true
},
"@types/node": {
"version": "14.14.16",
"resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.16.tgz",
"integrity": "sha512-naXYePhweTi+BMv11TgioE2/FXU4fSl29HAH1ffxVciNsH3rYXjNP2yM8wqmSm7jS20gM8TIklKiTen+1iVncw==",
"dev": true
},
"@types/node-cron": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/@types/node-cron/-/node-cron-2.0.3.tgz",
"integrity": "sha512-gwBBGeY2XeYBLE0R01K9Sm2hvNcPGmoloL6aqthA3QmBB1GYXTHIJ42AGZL7bdXBRiwbRV8b6NB5iKpl20R3gw==",
"dev": true,
"requires": {
"@types/tz-offset": "*"
}
},
"@types/node-fetch": {
"version": "2.5.7",
"resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.5.7.tgz",
"integrity": "sha512-o2WVNf5UhWRkxlf6eq+jMZDu7kjgpgJfl4xVNlvryc95O/6F2ld8ztKX+qu+Rjyet93WAWm5LjeX9H5FGkODvw==",
"dev": true,
"requires": {
"@types/node": "*",
"form-data": "^3.0.0"
}
},
"@types/qs": {
"version": "6.9.5",
"resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.5.tgz",
"integrity": "sha512-/JHkVHtx/REVG0VVToGRGH2+23hsYLHdyG+GrvoUGlGAd0ErauXDyvHtRI/7H7mzLm+tBCKA7pfcpkQ1lf58iQ==",
"dev": true
},
"@types/range-parser": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.3.tgz",
"integrity": "sha512-ewFXqrQHlFsgc09MK5jP5iR7vumV/BYayNC6PgJO2LPe8vrnNFyjQjSppfEngITi0qvfKtzFvgKymGheFM9UOA==",
"dev": true
},
"@types/serve-static": {
"version": "1.13.8",
"resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.8.tgz",
"integrity": "sha512-MoJhSQreaVoL+/hurAZzIm8wafFR6ajiTM1m4A0kv6AGeVBl4r4pOV8bGFrjjq1sGxDTnCoF8i22o0/aE5XCyA==",
"dev": true,
"requires": {
"@types/mime": "*",
"@types/node": "*"
}
},
"@types/tz-offset": {
"version": "0.0.0",
"resolved": "https://registry.npmjs.org/@types/tz-offset/-/tz-offset-0.0.0.tgz",
"integrity": "sha512-XLD/llTSB6EBe3thkN+/I0L+yCTB6sjrcVovQdx2Cnl6N6bTzHmwe/J8mWnsXFgxLrj/emzdv8IR4evKYG2qxQ==",
"dev": true
},
"abbrev": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
"integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==",
"dev": true
},
"accepts": {
"version": "1.3.7",
"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz",
"integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==",
"requires": {
"mime-types": "~2.1.24",
"negotiator": "0.6.2"
}
},
"ansi-align": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.0.tgz",
"integrity": "sha512-ZpClVKqXN3RGBmKibdfWzqCY4lnjEuoNzU5T0oEFpfd/z5qJHVarukridD4juLO2FXMiwUQxr9WqQtaYa8XRYw==",
"dev": true,
"requires": {
"string-width": "^3.0.0"
},
"dependencies": {
"string-width": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
"integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
"dev": true,
"requires": {
"emoji-regex": "^7.0.1",
"is-fullwidth-code-point": "^2.0.0",
"strip-ansi": "^5.1.0"
}
}
}
},
"ansi-regex": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
"integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
"dev": true
},
"ansi-styles": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
"dev": true,
"requires": {
"color-convert": "^2.0.1"
}
},
"anymatch": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz",
"integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==",
"dev": true,
"requires": {
"normalize-path": "^3.0.0",
"picomatch": "^2.0.4"
}
},
"arg": {
"version": "4.1.3",
"resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz",
"integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==",
"dev": true
},
"array-flatten": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
"integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI="
},
"asynckit": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
"integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=",
"dev": true
},
"balanced-match": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
"dev": true
},
"binary-extensions": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.1.0.tgz",
"integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==",
"dev": true
},
"body-parser": {
"version": "1.19.0",
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz",
"integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==",
"requires": {
"bytes": "3.1.0",
"content-type": "~1.0.4",
"debug": "2.6.9",
"depd": "~1.1.2",
"http-errors": "1.7.2",
"iconv-lite": "0.4.24",
"on-finished": "~2.3.0",
"qs": "6.7.0",
"raw-body": "2.4.0",
"type-is": "~1.6.17"
}
},
"boxen": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/boxen/-/boxen-4.2.0.tgz",
"integrity": "sha512-eB4uT9RGzg2odpER62bBwSLvUeGC+WbRjjyyFhGsKnc8wp/m0+hQsMUvUe3H2V0D5vw0nBdO1hCJoZo5mKeuIQ==",
"dev": true,
"requires": {
"ansi-align": "^3.0.0",
"camelcase": "^5.3.1",
"chalk": "^3.0.0",
"cli-boxes": "^2.2.0",
"string-width": "^4.1.0",
"term-size": "^2.1.0",
"type-fest": "^0.8.1",
"widest-line": "^3.1.0"
}
},
"brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
"dev": true,
"requires": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
}
},
"braces": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
"dev": true,
"requires": {
"fill-range": "^7.0.1"
}
},
"buffer-from": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz",
"integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==",
"dev": true
},
"bytes": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz",
"integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg=="
},
"cacheable-request": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz",
"integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==",
"dev": true,
"requires": {
"clone-response": "^1.0.2",
"get-stream": "^5.1.0",
"http-cache-semantics": "^4.0.0",
"keyv": "^3.0.0",
"lowercase-keys": "^2.0.0",
"normalize-url": "^4.1.0",
"responselike": "^1.0.2"
},
"dependencies": {
"get-stream": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz",
"integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==",
"dev": true,
"requires": {
"pump": "^3.0.0"
}
},
"lowercase-keys": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz",
"integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==",
"dev": true
}
}
},
"camelcase": {
"version": "5.3.1",
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
"integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
"dev": true
},
"chalk": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz",
"integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==",
"dev": true,
"requires": {
"ansi-styles": "^4.1.0",
"supports-color": "^7.1.0"
},
"dependencies": {
"has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
"dev": true
},
"supports-color": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
"dev": true,
"requires": {
"has-flag": "^4.0.0"
}
}
}
},
"chokidar": {
"version": "3.4.3",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.3.tgz",
"integrity": "sha512-DtM3g7juCXQxFVSNPNByEC2+NImtBuxQQvWlHunpJIS5Ocr0lG306cC7FCi7cEA0fzmybPUIl4txBIobk1gGOQ==",
"dev": true,
"requires": {
"anymatch": "~3.1.1",
"braces": "~3.0.2",
"fsevents": "~2.1.2",
"glob-parent": "~5.1.0",
"is-binary-path": "~2.1.0",
"is-glob": "~4.0.1",
"normalize-path": "~3.0.0",
"readdirp": "~3.5.0"
}
},
"ci-info": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz",
"integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==",
"dev": true
},
"cli-boxes": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz",
"integrity": "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==",
"dev": true
},
"clone-response": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz",
"integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=",
"dev": true,
"requires": {
"mimic-response": "^1.0.0"
}
},
"color-convert": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"dev": true,
"requires": {
"color-name": "~1.1.4"
}
},
"color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true
},
"combined-stream": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
"dev": true,
"requires": {
"delayed-stream": "~1.0.0"
}
},
"concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
"dev": true
},
"configstore": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/configstore/-/configstore-5.0.1.tgz",
"integrity": "sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA==",
"dev": true,
"requires": {
"dot-prop": "^5.2.0",
"graceful-fs": "^4.1.2",
"make-dir": "^3.0.0",
"unique-string": "^2.0.0",
"write-file-atomic": "^3.0.0",
"xdg-basedir": "^4.0.0"
}
},
"content-disposition": {
"version": "0.5.3",
"resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz",
"integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==",
"requires": {
"safe-buffer": "5.1.2"
}
},
"content-type": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz",
"integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA=="
},
"cookie": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz",
"integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg=="
},
"cookie-signature": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
"integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw="
},
"create-require": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz",
"integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==",
"dev": true
},
"crypto-random-string": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz",
"integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==",
"dev": true
},
"debug": {
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
"requires": {
"ms": "2.0.0"
}
},
"decompress-response": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz",
"integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=",
"dev": true,
"requires": {
"mimic-response": "^1.0.0"
}
},
"deep-extend": {
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
"integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==",
"dev": true
},
"defer-to-connect": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz",
"integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==",
"dev": true
},
"delayed-stream": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
"integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=",
"dev": true
},
"depd": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
"integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak="
},
"destroy": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz",
"integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA="
},
"diff": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
"integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==",
"dev": true
},
"dot-prop": {
"version": "5.3.0",
"resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz",
"integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==",
"dev": true,
"requires": {
"is-obj": "^2.0.0"
}
},
"duplexer3": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz",
"integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=",
"dev": true
},
"ee-first": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
"integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
},
"emoji-regex": {
"version": "7.0.3",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz",
"integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==",
"dev": true
},
"encodeurl": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
"integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k="
},
"end-of-stream": {
"version": "1.4.4",
"resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
"integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==",
"dev": true,
"requires": {
"once": "^1.4.0"
}
},
"escape-goat": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-2.1.1.tgz",
"integrity": "sha512-8/uIhbG12Csjy2JEW7D9pHbreaVaS/OpN3ycnyvElTdwM5n6GY6W6e2IPemfvGZeUMqZ9A/3GqIZMgKnBhAw/Q==",
"dev": true
},
"escape-html": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
"integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg="
},
"etag": {
"version": "1.8.1",
"resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
"integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc="
},
"express": {
"version": "4.17.1",
"resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz",
"integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==",
"requires": {
"accepts": "~1.3.7",
"array-flatten": "1.1.1",
"body-parser": "1.19.0",
"content-disposition": "0.5.3",
"content-type": "~1.0.4",
"cookie": "0.4.0",
"cookie-signature": "1.0.6",
"debug": "2.6.9",
"depd": "~1.1.2",
"encodeurl": "~1.0.2",
"escape-html": "~1.0.3",
"etag": "~1.8.1",
"finalhandler": "~1.1.2",
"fresh": "0.5.2",
"merge-descriptors": "1.0.1",
"methods": "~1.1.2",
"on-finished": "~2.3.0",
"parseurl": "~1.3.3",
"path-to-regexp": "0.1.7",
"proxy-addr": "~2.0.5",
"qs": "6.7.0",
"range-parser": "~1.2.1",
"safe-buffer": "5.1.2",
"send": "0.17.1",
"serve-static": "1.14.1",
"setprototypeof": "1.1.1",
"statuses": "~1.5.0",
"type-is": "~1.6.18",
"utils-merge": "1.0.1",
"vary": "~1.1.2"
}
},
"fill-range": {
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
"integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
"dev": true,
"requires": {
"to-regex-range": "^5.0.1"
}
},
"finalhandler": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz",
"integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==",
"requires": {
"debug": "2.6.9",
"encodeurl": "~1.0.2",
"escape-html": "~1.0.3",
"on-finished": "~2.3.0",
"parseurl": "~1.3.3",
"statuses": "~1.5.0",
"unpipe": "~1.0.0"
}
},
"form-data": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.0.tgz",
"integrity": "sha512-CKMFDglpbMi6PyN+brwB9Q/GOw0eAnsrEZDgcsH5Krhz5Od/haKHAX0NmQfha2zPPz0JpWzA7GJHGSnvCRLWsg==",
"dev": true,
"requires": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.8",
"mime-types": "^2.1.12"
}
},
"forwarded": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz",
"integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ="
},
"fresh": {
"version": "0.5.2",
"resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
"integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac="
},
"fsevents": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz",
"integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==",
"dev": true,
"optional": true
},
"get-stream": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz",
"integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==",
"dev": true,
"requires": {
"pump": "^3.0.0"
}
},
"glob-parent": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz",
"integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==",
"dev": true,
"requires": {
"is-glob": "^4.0.1"
}
},
"global-dirs": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-2.1.0.tgz",
"integrity": "sha512-MG6kdOUh/xBnyo9cJFeIKkLEc1AyFq42QTU4XiX51i2NEdxLxLWXIjEjmqKeSuKR7pAZjTqUVoT2b2huxVLgYQ==",
"dev": true,
"requires": {
"ini": "1.3.7"
}
},
"got": {
"version": "9.6.0",
"resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz",
"integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==",
"dev": true,
"requires": {
"@sindresorhus/is": "^0.14.0",
"@szmarczak/http-timer": "^1.1.2",
"cacheable-request": "^6.0.0",
"decompress-response": "^3.3.0",
"duplexer3": "^0.1.4",
"get-stream": "^4.1.0",
"lowercase-keys": "^1.0.1",
"mimic-response": "^1.0.1",
"p-cancelable": "^1.0.0",
"to-readable-stream": "^1.0.0",
"url-parse-lax": "^3.0.0"
}
},
"graceful-fs": {
"version": "4.2.4",
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz",
"integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==",
"dev": true
},
"has-flag": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
"integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
"dev": true
},
"has-yarn": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/has-yarn/-/has-yarn-2.1.0.tgz",
"integrity": "sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw==",
"dev": true
},
"http-cache-semantics": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz",
"integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==",
"dev": true
},
"http-errors": {
"version": "1.7.2",
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz",
"integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==",
"requires": {
"depd": "~1.1.2",
"inherits": "2.0.3",
"setprototypeof": "1.1.1",
"statuses": ">= 1.5.0 < 2",
"toidentifier": "1.0.0"
}
},
"iconv-lite": {
"version": "0.4.24",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
"integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
"requires": {
"safer-buffer": ">= 2.1.2 < 3"
}
},
"ignore-by-default": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz",
"integrity": "sha1-SMptcvbGo68Aqa1K5odr44ieKwk=",
"dev": true
},
"import-lazy": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz",
"integrity": "sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM=",
"dev": true
},
"imurmurhash": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
"integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=",
"dev": true
},
"inherits": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
},
"ini": {
"version": "1.3.7",
"resolved": "https://registry.npmjs.org/ini/-/ini-1.3.7.tgz",
"integrity": "sha512-iKpRpXP+CrP2jyrxvg1kMUpXDyRUFDWurxbnVT1vQPx+Wz9uCYsMIqYuSBLV+PAaZG/d7kRLKRFc9oDMsH+mFQ==",
"dev": true
},
"ipaddr.js": {
"version": "1.9.1",
"resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
"integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g=="
},
"is-binary-path": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
"integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
"dev": true,
"requires": {
"binary-extensions": "^2.0.0"
}
},
"is-ci": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz",
"integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==",
"dev": true,
"requires": {
"ci-info": "^2.0.0"
}
},
"is-extglob": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
"integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=",
"dev": true
},
"is-fullwidth-code-point": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
"integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=",
"dev": true
},
"is-glob": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz",
"integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==",
"dev": true,
"requires": {
"is-extglob": "^2.1.1"
}
},
"is-installed-globally": {
"version": "0.3.2",
"resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.3.2.tgz",
"integrity": "sha512-wZ8x1js7Ia0kecP/CHM/3ABkAmujX7WPvQk6uu3Fly/Mk44pySulQpnHG46OMjHGXApINnV4QhY3SWnECO2z5g==",
"dev": true,
"requires": {
"global-dirs": "^2.0.1",
"is-path-inside": "^3.0.1"
}
},
"is-npm": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/is-npm/-/is-npm-4.0.0.tgz",
"integrity": "sha512-96ECIfh9xtDDlPylNPXhzjsykHsMJZ18ASpaWzQyBr4YRTcVjUvzaHayDAES2oU/3KpljhHUjtSRNiDwi0F0ig==",
"dev": true
},
"is-number": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
"dev": true
},
"is-obj": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz",
"integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==",
"dev": true
},
"is-path-inside": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.2.tgz",
"integrity": "sha512-/2UGPSgmtqwo1ktx8NDHjuPwZWmHhO+gj0f93EkhLB5RgW9RZevWYYlIkS6zePc6U2WpOdQYIwHe9YC4DWEBVg==",
"dev": true
},
"is-typedarray": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
"integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=",
"dev": true
},
"is-yarn-global": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/is-yarn-global/-/is-yarn-global-0.3.0.tgz",
"integrity": "sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw==",
"dev": true
},
"json-buffer": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz",
"integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=",
"dev": true
},
"keyv": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz",
"integrity": "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==",
"dev": true,
"requires": {
"json-buffer": "3.0.0"
}
},
"latest-version": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/latest-version/-/latest-version-5.1.0.tgz",
"integrity": "sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA==",
"dev": true,
"requires": {
"package-json": "^6.3.0"
}
},
"lowercase-keys": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz",
"integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==",
"dev": true
},
"make-dir": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
"integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==",
"dev": true,
"requires": {
"semver": "^6.0.0"
},
"dependencies": {
"semver": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
"dev": true
}
}
},
"make-error": {
"version": "1.3.6",
"resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz",
"integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==",
"dev": true
},
"media-typer": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
"integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g="
},
"merge-descriptors": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
"integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E="
},
"methods": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
"integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4="
},
"mime": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
"integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg=="
},
"mime-db": {
"version": "1.44.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz",
"integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg=="
},
"mime-types": {
"version": "2.1.27",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz",
"integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==",
"requires": {
"mime-db": "1.44.0"
}
},
"mimic-response": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz",
"integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==",
"dev": true
},
"minimatch": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
"dev": true,
"requires": {
"brace-expansion": "^1.1.7"
}
},
"minimist": {
"version": "1.2.5",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
"integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==",
"dev": true
},
"ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
},
"negotiator": {
"version": "0.6.2",
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz",
"integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw=="
},
"node-cron": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/node-cron/-/node-cron-2.0.3.tgz",
"integrity": "sha512-eJI+QitXlwcgiZwNNSRbqsjeZMp5shyajMR81RZCqeW0ZDEj4zU9tpd4nTh/1JsBiKbF8d08FCewiipDmVIYjg==",
"requires": {
"opencollective-postinstall": "^2.0.0",
"tz-offset": "0.0.1"
}
},
"node-fetch": {
"version": "2.6.1",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz",
"integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw=="
},
"nodemon": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.6.tgz",
"integrity": "sha512-4I3YDSKXg6ltYpcnZeHompqac4E6JeAMpGm8tJnB9Y3T0ehasLa4139dJOcCrB93HHrUMsCrKtoAlXTqT5n4AQ==",
"dev": true,
"requires": {
"chokidar": "^3.2.2",
"debug": "^3.2.6",
"ignore-by-default": "^1.0.1",
"minimatch": "^3.0.4",
"pstree.remy": "^1.1.7",
"semver": "^5.7.1",
"supports-color": "^5.5.0",
"touch": "^3.1.0",
"undefsafe": "^2.0.3",
"update-notifier": "^4.1.0"
},
"dependencies": {
"debug": {
"version": "3.2.7",
"resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
"integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
"dev": true,
"requires": {
"ms": "^2.1.1"
}
},
"ms": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
"dev": true
}
}
},
"nopt": {
"version": "1.0.10",
"resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz",
"integrity": "sha1-bd0hvSoxQXuScn3Vhfim83YI6+4=",
"dev": true,
"requires": {
"abbrev": "1"
}
},
"normalize-path": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
"integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
"dev": true
},
"normalize-url": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.0.tgz",
"integrity": "sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ==",
"dev": true
},
"on-finished": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
"integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=",
"requires": {
"ee-first": "1.1.1"
}
},
"once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
"dev": true,
"requires": {
"wrappy": "1"
}
},
"opencollective-postinstall": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/opencollective-postinstall/-/opencollective-postinstall-2.0.3.tgz",
"integrity": "sha512-8AV/sCtuzUeTo8gQK5qDZzARrulB3egtLzFgteqB2tcT4Mw7B8Kt7JcDHmltjz6FOAHsvTevk70gZEbhM4ZS9Q=="
},
"p-cancelable": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz",
"integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==",
"dev": true
},
"package-json": {
"version": "6.5.0",
"resolved": "https://registry.npmjs.org/package-json/-/package-json-6.5.0.tgz",
"integrity": "sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ==",
"dev": true,
"requires": {
"got": "^9.6.0",
"registry-auth-token": "^4.0.0",
"registry-url": "^5.0.0",
"semver": "^6.2.0"
},
"dependencies": {
"semver": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
"dev": true
}
}
},
"parseurl": {
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
"integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ=="
},
"path-to-regexp": {
"version": "0.1.7",
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
"integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w="
},
"picomatch": {
"version": "2.2.2",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz",
"integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==",
"dev": true
},
"prepend-http": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz",
"integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=",
"dev": true
},
"proxy-addr": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz",
"integrity": "sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw==",
"requires": {
"forwarded": "~0.1.2",
"ipaddr.js": "1.9.1"
}
},
"pstree.remy": {
"version": "1.1.8",
"resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz",
"integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==",
"dev": true
},
"pump": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
"integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
"dev": true,
"requires": {
"end-of-stream": "^1.1.0",
"once": "^1.3.1"
}
},
"pupa": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/pupa/-/pupa-2.1.1.tgz",
"integrity": "sha512-l1jNAspIBSFqbT+y+5FosojNpVpF94nlI+wDUpqP9enwOTfHx9f0gh5nB96vl+6yTpsJsypeNrwfzPrKuHB41A==",
"dev": true,
"requires": {
"escape-goat": "^2.0.0"
}
},
"qs": {
"version": "6.7.0",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz",
"integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ=="
},
"range-parser": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
"integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg=="
},
"raw-body": {
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz",
"integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==",
"requires": {
"bytes": "3.1.0",
"http-errors": "1.7.2",
"iconv-lite": "0.4.24",
"unpipe": "1.0.0"
}
},
"rc": {
"version": "1.2.8",
"resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz",
"integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==",
"dev": true,
"requires": {
"deep-extend": "^0.6.0",
"ini": "~1.3.0",
"minimist": "^1.2.0",
"strip-json-comments": "~2.0.1"
}
},
"readdirp": {
"version": "3.5.0",
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz",
"integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==",
"dev": true,
"requires": {
"picomatch": "^2.2.1"
}
},
"registry-auth-token": {
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.2.1.tgz",
"integrity": "sha512-6gkSb4U6aWJB4SF2ZvLb76yCBjcvufXBqvvEx1HbmKPkutswjW1xNVRY0+daljIYRbogN7O0etYSlbiaEQyMyw==",
"dev": true,
"requires": {
"rc": "^1.2.8"
}
},
"registry-url": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/registry-url/-/registry-url-5.1.0.tgz",
"integrity": "sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw==",
"dev": true,
"requires": {
"rc": "^1.2.8"
}
},
"responselike": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz",
"integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=",
"dev": true,
"requires": {
"lowercase-keys": "^1.0.0"
}
},
"safe-buffer": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
},
"safer-buffer": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
},
"semver": {
"version": "5.7.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
"dev": true
},
"semver-diff": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-3.1.1.tgz",
"integrity": "sha512-GX0Ix/CJcHyB8c4ykpHGIAvLyOwOobtM/8d+TQkAd81/bEjgPHrfba41Vpesr7jX/t8Uh+R3EX9eAS5be+jQYg==",
"dev": true,
"requires": {
"semver": "^6.3.0"
},
"dependencies": {
"semver": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
"dev": true
}
}
},
"send": {
"version": "0.17.1",
"resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz",
"integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==",
"requires": {
"debug": "2.6.9",
"depd": "~1.1.2",
"destroy": "~1.0.4",
"encodeurl": "~1.0.2",
"escape-html": "~1.0.3",
"etag": "~1.8.1",
"fresh": "0.5.2",
"http-errors": "~1.7.2",
"mime": "1.6.0",
"ms": "2.1.1",
"on-finished": "~2.3.0",
"range-parser": "~1.2.1",
"statuses": "~1.5.0"
},
"dependencies": {
"ms": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
"integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg=="
}
}
},
"serve-static": {
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz",
"integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==",
"requires": {
"encodeurl": "~1.0.2",
"escape-html": "~1.0.3",
"parseurl": "~1.3.3",
"send": "0.17.1"
}
},
"setprototypeof": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz",
"integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw=="
},
"signal-exit": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz",
"integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==",
"dev": true
},
"source-map": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
"dev": true
},
"source-map-support": {
"version": "0.5.19",
"resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz",
"integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==",
"dev": true,
"requires": {
"buffer-from": "^1.0.0",
"source-map": "^0.6.0"
}
},
"statuses": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
"integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow="
},
"string-width": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz",
"integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==",
"dev": true,
"requires": {
"emoji-regex": "^8.0.0",
"is-fullwidth-code-point": "^3.0.0",
"strip-ansi": "^6.0.0"
},
"dependencies": {
"ansi-regex": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz",
"integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==",
"dev": true
},
"emoji-regex": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
"dev": true
},
"is-fullwidth-code-point": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
"dev": true
},
"strip-ansi": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz",
"integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==",
"dev": true,
"requires": {
"ansi-regex": "^5.0.0"
}
}
}
},
"strip-ansi": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
"integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
"dev": true,
"requires": {
"ansi-regex": "^4.1.0"
}
},
"strip-json-comments": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
"integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=",
"dev": true
},
"supports-color": {
"version": "5.5.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
"dev": true,
"requires": {
"has-flag": "^3.0.0"
}
},
"term-size": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/term-size/-/term-size-2.2.1.tgz",
"integrity": "sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg==",
"dev": true
},
"to-readable-stream": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz",
"integrity": "sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==",
"dev": true
},
"to-regex-range": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
"dev": true,
"requires": {
"is-number": "^7.0.0"
}
},
"toidentifier": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz",
"integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw=="
},
"touch": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz",
"integrity": "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==",
"dev": true,
"requires": {
"nopt": "~1.0.10"
}
},
"ts-node": {
"version": "9.1.1",
"resolved": "https://registry.npmjs.org/ts-node/-/ts-node-9.1.1.tgz",
"integrity": "sha512-hPlt7ZACERQGf03M253ytLY3dHbGNGrAq9qIHWUY9XHYl1z7wYngSr3OQ5xmui8o2AaxsONxIzjafLUiWBo1Fg==",
"dev": true,
"requires": {
"arg": "^4.1.0",
"create-require": "^1.1.0",
"diff": "^4.0.1",
"make-error": "^1.1.1",
"source-map-support": "^0.5.17",
"yn": "3.1.1"
}
},
"type-fest": {
"version": "0.8.1",
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz",
"integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==",
"dev": true
},
"type-is": {
"version": "1.6.18",
"resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
"integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
"requires": {
"media-typer": "0.3.0",
"mime-types": "~2.1.24"
}
},
"typedarray-to-buffer": {
"version": "3.1.5",
"resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz",
"integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==",
"dev": true,
"requires": {
"is-typedarray": "^1.0.0"
}
},
"typescript": {
"version": "4.1.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.1.3.tgz",
"integrity": "sha512-B3ZIOf1IKeH2ixgHhj6la6xdwR9QrLC5d1VKeCSY4tvkqhF2eqd9O7txNlS0PO3GrBAFIdr3L1ndNwteUbZLYg==",
"dev": true
},
"tz-offset": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/tz-offset/-/tz-offset-0.0.1.tgz",
"integrity": "sha512-kMBmblijHJXyOpKzgDhKx9INYU4u4E1RPMB0HqmKSgWG8vEcf3exEfLh4FFfzd3xdQOw9EuIy/cP0akY6rHopQ=="
},
"undefsafe": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.3.tgz",
"integrity": "sha512-nrXZwwXrD/T/JXeygJqdCO6NZZ1L66HrxM/Z7mIq2oPanoN0F1nLx3lwJMu6AwJY69hdixaFQOuoYsMjE5/C2A==",
"dev": true,
"requires": {
"debug": "^2.2.0"
}
},
"unique-string": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz",
"integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==",
"dev": true,
"requires": {
"crypto-random-string": "^2.0.0"
}
},
"unpipe": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
"integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw="
},
"update-notifier": {
"version": "4.1.3",
"resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-4.1.3.tgz",
"integrity": "sha512-Yld6Z0RyCYGB6ckIjffGOSOmHXj1gMeE7aROz4MG+XMkmixBX4jUngrGXNYz7wPKBmtoD4MnBa2Anu7RSKht/A==",
"dev": true,
"requires": {
"boxen": "^4.2.0",
"chalk": "^3.0.0",
"configstore": "^5.0.1",
"has-yarn": "^2.1.0",
"import-lazy": "^2.1.0",
"is-ci": "^2.0.0",
"is-installed-globally": "^0.3.1",
"is-npm": "^4.0.0",
"is-yarn-global": "^0.3.0",
"latest-version": "^5.0.0",
"pupa": "^2.0.1",
"semver-diff": "^3.1.1",
"xdg-basedir": "^4.0.0"
}
},
"url-parse-lax": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz",
"integrity": "sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=",
"dev": true,
"requires": {
"prepend-http": "^2.0.0"
}
},
"utils-merge": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
"integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM="
},
"vary": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
"integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw="
},
"widest-line": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz",
"integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==",
"dev": true,
"requires": {
"string-width": "^4.0.0"
}
},
"wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
"dev": true
},
"write-file-atomic": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz",
"integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==",
"dev": true,
"requires": {
"imurmurhash": "^0.1.4",
"is-typedarray": "^1.0.0",
"signal-exit": "^3.0.2",
"typedarray-to-buffer": "^3.1.5"
}
},
"xdg-basedir": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz",
"integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==",
"dev": true
},
"yn": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz",
"integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==",
"dev": true
}
}
}
{
"name": "traffic-history-job",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "nodemon index.ts",
"build": "tsc --project ./",
"test": "echo \"Error: no test specified\" && exit 1"
},
"repository": {
"type": "git",
"url": "git+https://gitlab.com/hanadiEbrahim/traffic-history-job.git"
},
"author": "Hanadi Ebrahim",
"license": "ISC",
"bugs": {
"url": "https://gitlab.com/hanadiEbrahim/traffic-history-job/issues"
},
"homepage": "https://gitlab.com/hanadiEbrahim/traffic-history-job#readme",
"dependencies": {
"express": "^4.17.1",
"node-cron": "^2.0.3",
"node-fetch": "^2.6.1"
},
"devDependencies": {
"@types/node-cron": "^2.0.3",
"@types/node-fetch": "^2.5.7",
"@types/express": "^4.17.9",
"@types/node": "^14.14.14",
"nodemon": "^2.0.6",
"ts-node": "^9.1.1",
"typescript": "^4.1.3"
}
}
export type FrostProjection = string[];
export type FrostBaseEntity = {
"@iot.id"?: string;
[key: string]: any;
}
export type FrostThing = FrostBaseEntity & {
name?: string;
description?: string;
properties?: any;
}
export type GeoLocation = any;
export type FrostLocation = FrostBaseEntity & {
name?: string;
description?: string;
encodingType?: string;
location?: GeoLocation;
properties?: any;
}
export type FrostFeatureOfInterest = FrostBaseEntity & {
name?: string;
description?: string;
encodingType?: string;
feature?: GeoLocation;
properties?: any;
}
export type FrostDatastreamInput = FrostBaseEntity & {
name: string;
description: string;
observationType: string;
unitOfMeasurement: {
name: string;
symbol: string;
definition: string;
};
ObservedProperty: FrostBaseEntity;
Sensor: FrostBaseEntity;
Thing: FrostBaseEntity;
}
export type FrostObservationInput = FrostBaseEntity & {
phenomenonTime: string;
result: number;
resultQuality: number;
resultTime: string;
FeatureOfInterest: FrostBaseEntity;
parameters?: any;
Datastream: FrostBaseEntity;
}
import {
FrostBaseEntity,
FrostDatastreamInput,
FrostFeatureOfInterest,
FrostLocation,
FrostObservationInput,
FrostProjection,
FrostThing
} from "./DataTypes";
import fetch from "node-fetch";
import {FlowResponse} from "../here/DataTypes";
import {info} from "../logger/logger";
const THINGS_PATH = "Things";
const LOCATIONS_PATH = "Locations";
const FEATURES_OF_INTEREST_PATH = "FeaturesOfInterest";
const DATASTREAMS_PATH = "Datastreams";
const OBSERVATIONS_PATH = "Observations";
const SENSORS_PATH = "Sensors";
const OBSERVED_PROPERTIES_PATH = "ObservedProperties";
type ItemType = "location" | "thing" | "featureOfInterest" | "datastream" | "observation" | "sensor" | "observedProperty";
const getPathFromType = (type: ItemType) => {
switch (type) {
case "thing":
return THINGS_PATH;
case "location":
return LOCATIONS_PATH;
case "featureOfInterest":
return FEATURES_OF_INTEREST_PATH;
case "datastream":
return DATASTREAMS_PATH;
case "observation":
return OBSERVATIONS_PATH;
case "sensor":
return SENSORS_PATH;
case "observedProperty":
return OBSERVED_PROPERTIES_PATH;
}
throw new Error(`Unknown type ${type}!`);
};
const DEFAULT_PROJECTION: FrostProjection = ["@iot.id"];
export class FrostClient {
constructor(
private baseUrl: string
) {
// Initialize Here sensor and Speed observed property if they are not already inserted
this.insertItemIfNotExists("sensor", {
"@iot.id": "here",
name: "Here",
description: "Here - Traffic Flow API",
encodingType: "text/html",
metadata: "https://developer.here.com/documentation/traffic/dev_guide/topics_v6.1/example-flow.html"
})
.then(inserted => {
if (inserted) console.log("Here sensor was inserted.");
})
.catch(err => console.error(err));
this.insertItemIfNotExists("observedProperty", {
"@iot.id": "speed",
name: "Speed",
definition: "http://www.qudt.org/qudt/owl/1.0.0/quantity/Instances.html#Speed",
description: "The Speed."
})
.then(inserted => {
if (inserted) console.log("Speed observed property was inserted.");
})
.catch(err => console.error(err));
}
/**
* Returns the first thing with the specified id, or null if not found.
* @param id
* @param projection
*/
async getSingleThingById(id: string, projection?: FrostProjection): Promise<FrostThing> {
return this.getSingleItemById("thing", id, projection);
}
/**
* Returns the first location with the specified id, or null if not found.
* @param id
* @param projection
*/
async getSingleLocationById(id: string, projection?: FrostProjection): Promise<FrostLocation> {
return this.getSingleItemById("location", id, projection);
}
/**
* Returns the first feature of interest with the specified id, or null if not found.
* @param id
* @param projection
*/
async getSingleFeatureOfInterestById(id: string, projection?: FrostProjection): Promise<FrostFeatureOfInterest> {
return this.getSingleItemById("featureOfInterest", id, projection);
}
async getSingleDatastreamById(id: string, projection?: FrostProjection): Promise<any> {
return this.getSingleItemById("datastream", id, projection);
}
/**
* Returns the number of inserted observations
* @param hereFlow
* @param forceUpdateLocations
*/
async mapAndInsertHereFlowResponse(hereFlow: FlowResponse, forceUpdateLocations: boolean = false): Promise<number> {
const data = hereFlow.RWS
.flatMap(rws => rws.RW)
.flatMap(rw => {
const timeStamp = rw.PBT;
const locationsAndResults =
rw.FIS
.flatMap(fis => fis.FI)
.map(fi => {
const thingId = `${rw.LI}-${fi.TMC.DE}-${fi.TMC.PC}`;
const thingDescription = `${rw.DE} direction to ${fi.TMC.DE}`;
const thing: FrostThing = {
"@iot.id": thingId,
name: thingId,
description: thingDescription
};
const location: FrostLocation = {
"@iot.id": thingId,
name: thingId,
description: thingDescription,
encodingType: "application/vnd.geo+json",
location: {
type: "MultiLineString",
coordinates: fi.SHP!
.map(v => v.value.toString())
.map(
str =>
str
.trim()
.split(" ")
.map(coord => coord.split(",").reverse().map(x => +x))
)
},
properties: {
length: fi.TMC.LE //In Kilometers
},
Things: [{
"@iot.id": thingId
}],
};
const featureOfInterest: FrostFeatureOfInterest = {
"@iot.id": location["@iot.id"],
name: location.name,
description: location.description,
encodingType: location.encodingType,
feature: location.location,
properties: location.properties,
};
const speed = fi.CF[0]?.SP;
const confidence = fi.CF[0]?.CN;
const jamFactor = fi.CF[0]?.JF;
return {thing, location, featureOfInterest, timeStamp, speed, confidence, jamFactor};
})
.filter(data => !!data.speed); // if failed to obtain speed data, don't consider it
/***** Log if ID repetitions Found *****/
Object.entries(locationsAndResults.map(data => data.featureOfInterest["@iot.id"]!)
.reduce(function (prev: { [key: string]: number }, cur: string) {
prev[cur] = (prev[cur] || 0) + 1;
return prev;
}, {}))
.forEach(([foiId, repetitions]) => {
if (repetitions > 1) {
console.error(`FeaturesOfInterest: ${foiId} is repeated ${repetitions} times`);
}
});
/***** *************************** *****/
return locationsAndResults;
});
return Promise.all(data.map(roadwayData => {
const datastreamId = `here-${roadwayData.thing["@iot.id"]}`;
return this.insertItemIfNotExists("thing", roadwayData.thing)
.then(() => {
const datastream: FrostDatastreamInput = {
"@iot.id": datastreamId,
name: datastreamId,
description: `Speed readings from Here for roadway ${roadwayData.thing.description}`,
observationType: "http://www.opengis.net/def/observationType/OGC-OM/2.0/OM_Measurement",
unitOfMeasurement: {
name: "Kilometers per hour",
symbol: "km/h",
definition: "http://www.qudt.org/qudt/owl/1.0.0/unit/Instances.html#KilometerPerHour"
},
ObservedProperty: {
"@iot.id": "speed"
},
Sensor: {
"@iot.id": "here"
},
Thing: {
"@iot.id": roadwayData.thing["@iot.id"]
},
};
return this.insertItemIfNotExists("datastream", datastream);
})
.then(() => this.insertItemIfNotExists("location", roadwayData.location, forceUpdateLocations))
.then(() => this.insertItemIfNotExists("featureOfInterest", roadwayData.featureOfInterest, forceUpdateLocations))
.then(() => {
const observation: FrostObservationInput = {
phenomenonTime: roadwayData.timeStamp,
result: roadwayData.speed,
resultQuality: roadwayData.confidence,
resultTime: roadwayData.timeStamp,
FeatureOfInterest: {
"@iot.id": roadwayData.featureOfInterest["@iot.id"]
},
Datastream: {
"@iot.id": datastreamId
},
parameters: {
jamFactor: roadwayData.jamFactor
}
};
return this.insertItem("observation", observation);
})
.then(() => 1);
})).then(length => length.reduce((a, b) => a + b, 0));
}
private async insertItemIfNotExists(
type: ItemType,
frostItemWithId: FrostBaseEntity,
forceUpdate: boolean = false
): Promise<boolean> {
const existingThing = await this.getSingleItemById(type, frostItemWithId["@iot.id"]!);
if (existingThing && forceUpdate) {
info(`Force updating item ${frostItemWithId["@iot.id"]} with type ${type}`);
return this.updateItem(type, frostItemWithId);
}
if (existingThing)
return false;
return this.insertItem(type, frostItemWithId);
}
private async insertItem(
type: ItemType,
frostItem: FrostBaseEntity
): Promise<boolean> {
// if (type == "location")
// console.debug(`inserting item with type ${type}`);
const path = getPathFromType(type);
let url = `${this.baseUrl}/${path}`;
return fetch(url, {
method: "POST",
body: JSON.stringify(frostItem)
})
.then(res => {
if (!res.ok) {
console.error(`Error inserting item ${JSON.stringify(frostItem)} with type ${type}`);
res.text().then(text => console.error(text));
const err = new Error(`Error inserting item ${JSON.stringify(frostItem)} with type ${type}`);
err.name = "COULD_NOT_INSERT_ITEM";
throw err;
}
return res.ok;
});
}
private async updateItem(
type: ItemType,
frostItem: FrostBaseEntity
): Promise<boolean> {
// if (type == "location")
// console.debug(`inserting item with type ${type}`);
const path = getPathFromType(type);
const encodedId = frostItem["@iot.id"]?.split("/").map(x => encodeURIComponent(x)).join("/");
let url = `${this.baseUrl}/${path}('${encodedId}')`;
return fetch(url, {
method: "PATCH",
body: JSON.stringify(frostItem)
})
.then(res => {
if (!res.ok) {
console.error(`Error updating item ${JSON.stringify(frostItem)} with type ${type}`);
res.text().then(text => console.error(text));
const err = new Error(`Error inserting item ${JSON.stringify(frostItem)} with type ${type}`);
err.name = "COULD_NOT_INSERT_ITEM";
throw err;
}
return res.ok;
});
}
private async getSingleItemById(
type: ItemType,
id: string,
projection: FrostProjection = DEFAULT_PROJECTION
): Promise<FrostBaseEntity> {
const path = getPathFromType(type);
const params = {
"$filter": `id eq '${id}'`,
"$top": 1,
...(projection ? {"$select": projection?.join(",")} : {})
};
return this.get(path, params).then(res => res.value[0]);
}
private async get(urlPath: string, params?: { [key: string]: string | number }): Promise<any> {
let url = `${this.baseUrl}/${urlPath}`;
if (!params)
params = {};
if (Object.keys(params)) {
url += "?";
url += Object.entries(params)
.map(([key, value]) => [key, encodeURIComponent(value)])
.map(([key, value]) => `${key}=${value}`)
.join("&");
}
return fetch(url)
.then(res => res.json())
.then(json => {
// console.debug(`Getting url "${url}"`);
// console.debug(json);
return json;
});
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment