From 7028300e6e727a4b25f9c1314176a0370ef6d6d7 Mon Sep 17 00:00:00 2001 From: Jason Fox Date: Sat, 30 Nov 2019 12:31:29 +0100 Subject: [PATCH 01/27] Integrate EsLint + Prettier --- .eslintrc.json | 11 + .gitignore | 1 + .jshintrc | 31 - .prettierrc.json | 9 + README.md | 14 +- bin/agentConsole.js | 137 +- bin/iotAgentTester.js | 33 +- config-blank.js | 3 +- config.js | 2 +- doc/echo.js | 21 +- doc/finalResult.js | 34 +- doc/usermanual.md | 12 +- ghpages/javascripts/scale.fix.js | 20 +- index.js | 2 +- lib/command/commandLine.js | 333 +- lib/command/migration.js | 152 +- lib/commonConfig.js | 162 +- lib/constants.js | 2 - lib/errors.js | 235 +- lib/fiware-iotagent-lib.js | 149 +- lib/model/Command.js | 7 +- lib/model/Device.js | 7 +- lib/model/Group.js | 7 +- lib/model/dbConn.js | 83 +- lib/plugins/addEvent.js | 9 +- lib/plugins/attributeAlias.js | 28 +- lib/plugins/bidirectionalData.js | 110 +- lib/plugins/compressTimestamp.js | 20 +- lib/plugins/expressionParser.js | 168 +- lib/plugins/expressionPlugin.js | 44 +- lib/plugins/multiEntity.js | 169 +- lib/plugins/pluginUtils.js | 55 +- lib/plugins/timestampProcessPlugin.js | 48 +- .../commands/commandRegistryMemory.js | 101 +- .../commands/commandRegistryMongoDB.js | 87 +- lib/services/commands/commandService.js | 71 +- lib/services/common/alarmManagement.js | 23 +- lib/services/common/domain.js | 33 +- lib/services/common/genericMiddleware.js | 30 +- lib/services/common/iotManagerService.js | 76 +- .../common/securityServiceKeystone.js | 43 +- lib/services/common/securityServiceOAuth2.js | 85 +- lib/services/devices/deviceRegistryMemory.js | 56 +- lib/services/devices/deviceRegistryMongoDB.js | 115 +- lib/services/devices/deviceService.js | 590 +- lib/services/devices/registrationUtils.js | 130 +- lib/services/groups/groupRegistryMemory.js | 111 +- lib/services/groups/groupRegistryMongoDB.js | 149 +- lib/services/groups/groupService.js | 101 +- lib/services/ngsi/ngsiParser.js | 18 +- lib/services/ngsi/ngsiService.js | 711 +-- lib/services/ngsi/subscriptionService.js | 241 +- lib/services/northBound/contextServer.js | 639 +- .../deviceGroupAdministrationServer.js | 208 +- .../northBound/deviceProvisioningServer.js | 253 +- lib/services/northBound/northboundServer.js | 50 +- lib/services/northBound/restUtils.js | 71 +- lib/services/stats/statsRegistry.js | 37 +- package-lock.json | 5117 +++++++++++++++++ package.json | 22 +- test/.jshintrc | 35 - test/tools/utils.js | 9 +- test/unit/expressions/expression-test.js | 82 +- .../expressionBasedTransformations-test.js | 263 +- test/unit/general/alarmManagement-test.js | 53 +- test/unit/general/config-multi-core-test.js | 268 +- ...ontextBrokerKeystoneSecurityAccess-test.js | 327 +- .../contextBrokerOAuthSecurityAccess-test.js | 929 +-- test/unit/general/deviceService-test.js | 347 +- test/unit/general/https-support-test.js | 266 +- .../general/iotam-autoregistration-test.js | 365 +- test/unit/general/loglevel-api_test.js | 117 +- test/unit/general/migration-test.js | 254 +- test/unit/general/startup-test.js | 79 +- .../general/statistics-persistence_test.js | 98 +- test/unit/general/statistics-service_test.js | 88 +- .../active-devices-attribute-update-test.js | 103 +- test/unit/lazyAndCommands/command-test.js | 265 +- .../lazyAndCommands/commandRegistry_test.js | 107 +- .../unit/lazyAndCommands/lazy-devices-test.js | 967 ++-- .../lazyAndCommands/polling-commands-test.js | 274 +- .../deviceRegistryMemory_test.js | 138 +- test/unit/mongodb/mongoDBUtils.js | 58 +- .../mongodb/mongodb-group-registry-test.js | 462 +- test/unit/mongodb/mongodb-registry-test.js | 609 +- test/unit/ngsiService/active-devices-test.js | 348 +- .../queryDeviceInformationInCb-test.js | 235 +- .../unit/ngsiService/staticAttributes-test.js | 153 +- test/unit/ngsiService/subscriptions-test.js | 193 +- .../expressionBasedTransformations-test.js | 569 +- .../contextBrokerOAuthSecurityAccess-test.js | 889 +-- .../unit/ngsiv2/general/deviceService-test.js | 321 +- .../unit/ngsiv2/general/https-support-test.js | 233 +- .../general/iotam-autoregistration-test.js | 365 +- test/unit/ngsiv2/general/startup-test.js | 76 +- .../active-devices-attribute-update-test.js | 91 +- .../ngsiv2/lazyAndCommands/command-test.js | 232 +- .../lazyAndCommands/lazy-devices-test.js | 835 +-- .../lazyAndCommands/polling-commands-test.js | 231 +- .../ngsiv2/ngsiService/active-devices-test.js | 344 +- test/unit/ngsiv2/ngsiService/autocast-test.js | 206 +- .../ngsiService/staticAttributes-test.js | 149 +- .../ngsiv2/ngsiService/subscriptions-test.js | 170 +- test/unit/ngsiv2/plugins/alias-plugin_test.js | 293 +- .../plugins/bidirectional-plugin_test.js | 325 +- .../plugins/compress-timestamp-plugin_test.js | 221 +- test/unit/ngsiv2/plugins/event-plugin_test.js | 80 +- .../ngsiv2/plugins/multientity-plugin_test.js | 656 ++- .../timestamp-processing-plugin_test.js | 88 +- .../device-provisioning-api_test.js | 282 +- .../provisioning/device-registration_test.js | 226 +- .../device-update-registration_test.js | 256 +- .../listProvisionedDevices-test.js | 165 +- .../provisionDeviceMultientity-test.js | 74 +- .../removeProvisionedDevice-test.js | 147 +- .../singleConfigurationMode-test.js | 176 +- .../updateProvisionedDevices-test.js | 283 +- test/unit/plugins/alias-plugin_test.js | 119 +- .../unit/plugins/bidirectional-plugin_test.js | 452 +- .../capture-configuration-inPlugins_test.js | 153 +- .../capture-provision-inPlugins_test.js | 117 +- .../plugins/compress-timestamp-plugin_test.js | 234 +- test/unit/plugins/event-plugin_test.js | 86 +- test/unit/plugins/multientity-plugin_test.js | 205 +- .../timestamp-processing-plugin_test.js | 92 +- .../plugins/translation-inPlugins_test.js | 219 +- .../provisioning/device-group-api-test.js | 604 +- .../provisioning/device-group-utils_test.js | 121 +- .../device-provisioning-api_test.js | 325 +- .../provisioning/device-registration_test.js | 333 +- .../device-update-registration_test.js | 302 +- .../listProvisionedDevices-test.js | 220 +- .../provisionDeviceMultientity-test.js | 86 +- .../removeProvisionedDevice-test.js | 199 +- .../singleConfigurationMode-test.js | 235 +- .../updateProvisionedDevices-test.js | 355 +- 136 files changed, 18865 insertions(+), 12353 deletions(-) create mode 100644 .eslintrc.json delete mode 100644 .jshintrc create mode 100644 .prettierrc.json create mode 100644 package-lock.json delete mode 100644 test/.jshintrc diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 000000000..407e21b28 --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,11 @@ +{ + "extends": "tamia", + "parserOptions": { + "sourceType": "module" + }, + "plugins": ["prettier"], + "rules": { + "prettier/prettier": "error", + "valid-jsdoc": 0 + } +} \ No newline at end of file diff --git a/.gitignore b/.gitignore index dc4f12297..90e14c023 100644 --- a/.gitignore +++ b/.gitignore @@ -12,4 +12,5 @@ .project .metadata npm-debug.log +.eslintcache diff --git a/.jshintrc b/.jshintrc deleted file mode 100644 index 517729321..000000000 --- a/.jshintrc +++ /dev/null @@ -1,31 +0,0 @@ -{ - "curly": true, - "eqeqeq": true, - "immed": true, - "latedef": true, - "newcap": true, - "noarg": true, - "noempty": true, - "quotmark": "single", - "undef": true, - "unused": true, - "trailing": true, - "maxparams": 8, - "maxdepth": 4, - "camelcase": true, - "maxlen": 120, - "node": true, - "expr": true, - "unused": "vars", - "esversion": 6, - "globals": { - "describe":true, - "it": true, - "expect": true, - "before": true, - "after": true, - "beforeEach": true, - "afterEach": true, - "mock": true - } -} \ No newline at end of file diff --git a/.prettierrc.json b/.prettierrc.json new file mode 100644 index 000000000..8238852e0 --- /dev/null +++ b/.prettierrc.json @@ -0,0 +1,9 @@ +{ + "arrowParens": "always", + "bracketSpacing": true, + "singleQuote": true, + "parser": "flow", + "printWidth": 120, + "trailingComma": "none", + "tabWidth": 4 +} \ No newline at end of file diff --git a/README.md b/README.md index e12accb18..ce686dda4 100644 --- a/README.md +++ b/README.md @@ -459,8 +459,8 @@ in the database model. | entity_name | name | Name of the entity representing the device in the Context Broker | ParkLamplight12 | | entity_type | type | Type of the entity in the Context Broker | Lamplights | | timezone | timezone | Time zone of the sensor if it has any | America/Santiago | -| timestamp | timestamp | Optional flag about add or not the TimeInstant attribute to devide entity created, as well as a TimeInstant metadata to each attribute, with the current timestamp | true | -| apikey | apikey | Optional Apikey key string to use instead of group apikey +| timestamp. | timestamp | Optional flag about add or not the TimeInstant attribute to devide entity created, as well as a TimeInstant metadata to each attribute, with the current timestamp | true | +| apikey | apikey | Optional Apikey key string to use instead of group apikey | 9n4hb1vpwbjozzmw9f0flf9c2 | | endpoint | endpoint | Endpoint where the device is going to receive commands, if any. | http://theDeviceUrl:1234/commands | | protocol | protocol | Name of the device protocol, for its use with an IoT Manager. | IoTA-UL | @@ -1477,17 +1477,17 @@ version 3](./LICENSE). ### Are there any legal issues with AGPL 3.0? Is it safe for me to use? -There is absolutely no problem in using a product licensed under AGPL 3.0. Issues with GPL -(or AGPL) licenses are mostly related with the fact that different people assign different +There is absolutely no problem in using a product licensed under AGPL 3.0. Issues with GPL +(or AGPL) licenses are mostly related with the fact that different people assign different interpretations on the meaning of the term “derivate work” used in these licenses. Due to this, some people believe that there is a risk in just _using_ software under GPL or AGPL licenses (even without _modifying_ it). -For the avoidance of doubt, the owners of this software licensed under an AGPL-3.0 license +For the avoidance of doubt, the owners of this software licensed under an AGPL-3.0 license wish to make a clarifying public statement as follows: > Please note that software derived as a result of modifying the source code of this -> software in order to fix a bug or incorporate enhancements is considered a derivative -> work of the product. Software that merely uses or aggregates (i.e. links to) an otherwise +> software in order to fix a bug or incorporate enhancements is considered a derivative +> work of the product. Software that merely uses or aggregates (i.e. links to) an otherwise > unmodified version of existing software is not considered a derivative work, and therefore > it does not need to be released as under the same license, or even released as open source. diff --git a/bin/agentConsole.js b/bin/agentConsole.js index 9ddfa4cab..d7139117b 100755 --- a/bin/agentConsole.js +++ b/bin/agentConsole.js @@ -23,53 +23,58 @@ * please contact with::[contacto@tid.es] */ -var readline = require('readline'), - iotAgentLib = require('../lib/fiware-iotagent-lib'), - commandUtils = require('command-shell-lib'), - config = require('../config'), - logger = require('logops'), - async = require('async'), - separator = '\n\n\t'; - -var commands = { - 'start': { +/* eslint-disable no-unused-vars */ +/* eslint-disable no-console */ + +const readline = require('readline'); +const iotAgentLib = require('../lib/fiware-iotagent-lib'); +const commandUtils = require('command-shell-lib'); +let config = require('../config'); +const logger = require('logops'); +const async = require('async'); +const separator = '\n\n\t'; + +const commands = { + start: { parameters: [], description: '\tStart the IoT Agent', handler: startApp }, - 'stop': { + stop: { parameters: [], description: '\tStop the IoT Agent', handler: stopApp }, - 'register': { + register: { parameters: ['id', 'type'], - description: '\tRegister a new device in the IoT Agent. The attributes to register will be extracted from the\n' + + description: + '\tRegister a new device in the IoT Agent. The attributes to register will be extracted from the\n' + '\ttype configuration', handler: registerDevice }, - 'unregister': { + unregister: { parameters: ['id', 'type'], description: '\tUnregister the selected device', handler: unregisterDevice }, - 'showConfig': { + showConfig: { parameters: [], description: '\tShow the current configuration file', handler: showConfig }, - 'config': { + config: { parameters: ['newConfig'], description: '\tChange the configuration file to a new one', handler: changeConfig }, - 'updatevalue': { + updatevalue: { parameters: ['deviceId', 'deviceType', 'attributes'], - description: '\tUpdate a device value in the Context Broker. The attributes should be triads with the following\n' + + description: + '\tUpdate a device value in the Context Broker. The attributes should be triads with the following\n' + '\tformat: "name/type/value" sepparated by commas.', handler: updateDeviceValue }, - 'listdevices': { + listdevices: { parameters: [], description: '\tList all the devices that have been registered in this IoT Agent session\n', handler: listDevices @@ -77,11 +82,11 @@ var commands = { }; function handleError(message) { - return function (error) { + return function(error) { if (error) { - console.log('\n\033[31mERROR:\033[0m %s', error.message); + console.log('\n\\033[31mERROR:\\033[0m %s', error.message); } else { - console.log(message) + console.log(message); } commandUtils.prompt(); @@ -89,13 +94,13 @@ function handleError(message) { } function listDevices() { - iotAgentLib.listDevices(config.service, config.subservice, function (error, devices) { + iotAgentLib.listDevices(config.service, config.subservice, function(error, devices) { if (error) { - console.log('\n\033[31mERROR:\033[0m %s', error.message); + console.log('\n\\033[31mERROR:\\033[0m %s', error.message); } else { - var keys = Object.keys(devices); + const keys = Object.keys(devices); - for (var i = 0; i < keys.length; i++) { + for (let i = 0; i < keys.length; i++) { console.log('\n\n%s\n', JSON.stringify(devices[keys[i]], null, 4)); } @@ -105,16 +110,15 @@ function listDevices() { } function extractAttributes(attributeString, callback) { - var attributes = attributeString.split(','), - attributesResult = []; - - for (var i = 0; i < attributes.length; i++) { - var fields = attributes[i].split('/'), - attribute = { - name: fields[0], - type: fields[1] - }; + const attributes = attributeString.split(','); + const attributesResult = []; + for (let i = 0; i < attributes.length; i++) { + const fields = attributes[i].split('/'); + const attribute = { + name: fields[0], + type: fields[1] + }; if (fields[2]) { attribute.value = fields[2]; @@ -135,24 +139,32 @@ function changeConfig(command) { } function writeHandler(id, type, attributes, callback) { - console.log('\n\nFake WRITE handler for update in entity [%s] with type [%s]\n%s\n', - id, type, JSON.stringify(attributes, null, 4)); + console.log( + '\n\nFake WRITE handler for update in entity [%s] with type [%s]\n%s\n', + id, + type, + JSON.stringify(attributes, null, 4) + ); callback(null, { - id: id, - type: type, - attributes: attributes + id, + type, + attributes }); } function readHandler(id, type, attributes, callback) { - console.log('\n\nFake READ handler for update in entity [%s] with type [%s]\n%s\n' - , id, type, JSON.stringify(attributes, null, 4)); - - var sensorData = { - id: id, + console.log( + '\n\nFake READ handler for update in entity [%s] with type [%s]\n%s\n', + id, + type, + JSON.stringify(attributes, null, 4) + ); + + const sensorData = { + id, isPattern: false, - type: type, + type, attributes: [ { name: 'luminance', @@ -181,7 +193,7 @@ function exitAgent(command) { } function registerDevice(command) { - var device = { + const device = { id: command[0], type: command[1] }; @@ -199,14 +211,23 @@ function updateDeviceValue(command) { iotAgentLib.getDevice(command[0], function(error, device) { if (device) { extractAttributes(command[2], function(error, attributes) { - iotAgentLib.update(device.name, device.type, '', attributes, device, - handleError('Device value updated')); + iotAgentLib.update( + device.name, + device.type, + '', + attributes, + device, + handleError('Device value updated') + ); }); } else { - async.waterfall([ - async.apply(extractAttributes, command[2]), - async.apply(iotAgentLib.update, command[0], command[1], '') - ], handleError('Device value updated')); + async.waterfall( + [ + async.apply(extractAttributes, command[2]), + async.apply(iotAgentLib.update, command[0], command[1], '') + ], + handleError('Device value updated') + ); } }); } @@ -215,20 +236,20 @@ function queryHandler(id, type, attributes, callback) { console.log('Handling query for [%s] of type [%s]:\n%s', JSON.stringify(attributes)); callback(null, { - type: type, + type, isPattern: false, - id: id, + id, attributes: [] }); } function updateHandler(id, type, attributes, callback) { - console.log("Update message received for device with id [%s] and type [%s]", id, type); + console.log('Update message received for device with id [%s] and type [%s]', id, type); callback(null, { - type: type, + type, isPattern: false, - id: id, + id, attributes: [] }); } diff --git a/bin/iotAgentTester.js b/bin/iotAgentTester.js index 73b9a2a2e..5eb1b4c82 100755 --- a/bin/iotAgentTester.js +++ b/bin/iotAgentTester.js @@ -22,24 +22,23 @@ * For those usages not covered by the GNU Affero General Public License * please contact with::[contacto@tid.es] */ -'use strict'; -var commandLine = require('../lib/command/commandLine'), - clUtils = require('command-shell-lib'), - configCb = { - host: 'localhost', - port: 1026, - service: 'tester', - subservice: '/test' - }, - configIot = { - host: 'localhost', - port: 4041, - name: 'default', - service: 'tester', - subservice: '/test' - }; +const commandLine = require('../lib/command/commandLine'); +const clUtils = require('command-shell-lib'); +const configCb = { + host: 'localhost', + port: 1026, + service: 'tester', + subservice: '/test' +}; +const configIot = { + host: 'localhost', + port: 4041, + name: 'default', + service: 'tester', + subservice: '/test' +}; commandLine.init(configCb, configIot); -clUtils.initialize(commandLine.commands, 'IoT Agent tester> '); \ No newline at end of file +clUtils.initialize(commandLine.commands, 'IoT Agent tester> '); diff --git a/config-blank.js b/config-blank.js index f57209bc6..4a76214ee 100644 --- a/config-blank.js +++ b/config-blank.js @@ -33,8 +33,7 @@ var config = { deviceRegistry: { type: 'memory' }, - types: { - }, + types: {}, service: 'tester', subservice: '/test', providerUrl: 'http://192.168.56.1:4041', diff --git a/config.js b/config.js index cb6c8d3b6..7cfde892d 100644 --- a/config.js +++ b/config.js @@ -44,7 +44,7 @@ var config = { type: 'memory' }, types: { - 'Light': { + Light: { url: '/', apikey: '', type: 'Light', diff --git a/doc/echo.js b/doc/echo.js index 1e66f213d..5bafbc043 100644 --- a/doc/echo.js +++ b/doc/echo.js @@ -2,16 +2,16 @@ var http = require('http'), express = require('express'); function dummyResponse(req, res) { - console.log('Processing response to [%s] [%s] [%j]', req.method, req.path, req.query); + console.log('Processing response to [%s] [%s] [%j]', req.method, req.path, req.query); res.status(200).send('89'); } function initEcho(callback) { - echoServer = { + echoServer = { server: null, app: express(), router: express.Router() - }; + }; echoServer.app.set('port', 9999); echoServer.app.set('host', '0.0.0.0'); @@ -22,11 +22,10 @@ function initEcho(callback) { echoServer.server.listen(echoServer.app.get('port'), echoServer.app.get('host'), callback); } -initEcho(function (error) { - if (error) { - console.log('Could not initialize echo server: %s', error); - } else { - console.log('Echo server started successfully'); - } - }); - +initEcho(function(error) { + if (error) { + console.log('Could not initialize echo server: %s', error); + } else { + console.log('Echo server started successfully'); + } +}); diff --git a/doc/finalResult.js b/doc/finalResult.js index 4ac8571cf..4256d8384 100644 --- a/doc/finalResult.js +++ b/doc/finalResult.js @@ -6,7 +6,7 @@ var iotAgentLib = require('iotagent-node-lib'), function parseUl(data, device) { function findType(name) { - for (var i=0; i < device.active.length; i++) { + for (var i = 0; i < device.active.length; i++) { if (device.active[i].name === name) { return device.active[i].type; } @@ -22,11 +22,11 @@ function parseUl(data, device) { value: pair[1], type: findType(pair[0]) }; - + return attribute; } - - return data.split("#").map(createAttribute); + + return data.split('#').map(createAttribute); } function manageULRequest(req, res, next) { @@ -35,7 +35,7 @@ function manageULRequest(req, res, next) { iotAgentLib.getDevice(req.query.i, function(error, device) { if (error) { res.status(404).send({ - message: 'Couldn\'t find the device: ' + JSON.stringify(error) + message: "Couldn't find the device: " + JSON.stringify(error) }); } else { values = parseUl(req.query.d, device); @@ -43,15 +43,15 @@ function manageULRequest(req, res, next) { if (error) { res.status(500).send({ message: 'Error updating the device' - }); + }); } else { res.status(200).send({ message: 'Device successfully updated' }); - } + } }); } - }); + }); } function initSouthbound(callback) { @@ -77,9 +77,9 @@ function createResponse(id, type, attributes, body) { for (var i = 0; i < attributes.length; i++) { responses.push({ - name: attributes[i], - type: "string", - value: values[i] + name: attributes[i], + type: 'string', + value: values[i] }); } @@ -99,7 +99,7 @@ function queryContextHandler(id, type, attributes, callback) { } }; - request(options, function (error, response, body) { + request(options, function(error, response, body) { if (error) { callback(error); } else { @@ -109,12 +109,12 @@ function queryContextHandler(id, type, attributes, callback) { } function createQueryFromAttributes(attributes) { - var query = ""; + var query = ''; for (var i in attributes) { query += attributes[i].name + '|' + attributes[i].value; - if (i != attributes.length -1) { + if (i != attributes.length - 1) { query += ','; } } @@ -131,7 +131,7 @@ function updateContextHandler(id, type, attributes, callback) { } }; - request(options, function (error, response, body) { + request(options, function(error, response, body) { if (error) { callback(error); } else { @@ -167,7 +167,7 @@ iotAgentLib.activate(config, function(error) { iotAgentLib.setConfigurationHandler(configurationHandler); iotAgentLib.setProvisioningHandler(provisioningHandler); - initSouthbound(function (error) { + initSouthbound(function(error) { if (error) { console.log('Could not initialize South bound API due to the following error: %s', error); } else { @@ -176,5 +176,3 @@ iotAgentLib.activate(config, function(error) { }); } }); - - diff --git a/doc/usermanual.md b/doc/usermanual.md index 4cf7ae67a..20fef4199 100644 --- a/doc/usermanual.md +++ b/doc/usermanual.md @@ -15,6 +15,7 @@ + [Continuous testing](#continuous-testing) + [Code Coverage](#code-coverage) + [Clean](#clean) + + [Prettify Code](#prettify-code) ## Usage @@ -749,9 +750,18 @@ npm run test:coverage ### Clean -Removes `node_modules` and `coverage` folders, and `package-lock.json` file so that a fresh copy of the project is restored. +Removes `node_modules` and `coverage` folders, and `package-lock.json` file so that a fresh copy of the project is restored. ```bash # Use git-bash on Windows npm run clean ``` + +### Prettify Code + +Runs the [prettier](https://prettier.io) code formatter to ensure consistent code style (whitespacing, parameter placement and breakup of long lines etc.) within the codebase. + +```bash +# Use git-bash on Windows +npm run prettier +``` diff --git a/ghpages/javascripts/scale.fix.js b/ghpages/javascripts/scale.fix.js index 87a40ca71..39cdc7663 100644 --- a/ghpages/javascripts/scale.fix.js +++ b/ghpages/javascripts/scale.fix.js @@ -1,17 +1,17 @@ var metas = document.getElementsByTagName('meta'); var i; if (navigator.userAgent.match(/iPhone/i)) { - for (i=0; i 0) { - db.db().collection(collection).insertMany(docs, function(error, inserts) { - innerCb(error); - }); + db.db() + .collection(collection) + /* eslint-disable-next-line no-unused-vars */ + .insertMany(docs, function(error, inserts) { + innerCb(error); + }); } else { innerCb(); } @@ -120,7 +125,7 @@ function migrate(dbConfig, originDb, targetDb, service, subservice, callback) { } function getCollection(db, name, service, subservice, innerCb) { - var query = {}; + const query = {}; if (service) { query.service = service; @@ -130,42 +135,49 @@ function migrate(dbConfig, originDb, targetDb, service, subservice, callback) { query.service_path = subservice; } - db.db().collection(name).find(query).toArray(innerCb); + db.db() + .collection(name) + .find(query) + .toArray(innerCb); } function closeDb(db, innerCb) { + /* eslint-disable-next-line no-unused-vars */ db.close(function(error) { innerCb(); }); } function startMigration(dbResults, innerCb) { - var originDb = dbResults[0], - targetDb = dbResults[1]; - - async.waterfall([ - apply(getCollection, originDb, 'SERVICE', service, subservice), - generateCollectionTranslator(serviceTranslation), - apply(saveToTargetDb, targetDb, 'groups'), - apply(getCollection, originDb, 'DEVICE', service, subservice), - generateCollectionTranslator(deviceTranslation), - applyDefaultName, - applyProtocolTranslations, - apply(saveToTargetDb, targetDb, 'devices'), - apply(closeDb, originDb), - apply(closeDb, targetDb) - ], function(error) { - innerCb(error); - }); + const originDb = dbResults[0]; + const targetDb = dbResults[1]; + + async.waterfall( + [ + apply(getCollection, originDb, 'SERVICE', service, subservice), + generateCollectionTranslator(serviceTranslation), + apply(saveToTargetDb, targetDb, 'groups'), + apply(getCollection, originDb, 'DEVICE', service, subservice), + generateCollectionTranslator(deviceTranslation), + applyDefaultName, + applyProtocolTranslations, + apply(saveToTargetDb, targetDb, 'devices'), + apply(closeDb, originDb), + apply(closeDb, targetDb) + ], + function(error) { + innerCb(error); + } + ); } - async.waterfall([ - apply(async.series, [ - apply(connectToDb, dbConfig, originDb), - apply(connectToDb, dbConfig, targetDb) - ]), - startMigration - ], callback); + async.waterfall( + [ + apply(async.series, [apply(connectToDb, dbConfig, originDb), apply(connectToDb, dbConfig, targetDb)]), + startMigration + ], + callback + ); } exports.migrate = migrate; diff --git a/lib/commonConfig.js b/lib/commonConfig.js index 13309ef09..84b75a4a4 100644 --- a/lib/commonConfig.js +++ b/lib/commonConfig.js @@ -25,20 +25,18 @@ * Modified by: Fernando López - FIWARE Foundation */ -'use strict'; - -var config = {}, - logger = require('logops'), - registry, - groupRegistry, - commandRegistry, - securityService, - context = { - op: 'IoTAgentNGSI.CommonConfig' - }; +let config = {}; +const logger = require('logops'); +let registry; +let groupRegistry; +let commandRegistry; +let securityService; +const context = { + op: 'IoTAgentNGSI.CommonConfig' +}; function anyIsSet(variableSet) { - for (var i = 0; i < variableSet.length; i++) { + for (let i = 0; i < variableSet.length; i++) { if (process.env[variableSet[i]]) { return true; } @@ -51,70 +49,74 @@ function anyIsSet(variableSet) { * Looks for environment variables that could override configuration values. */ function processEnvironmentVariables() { - var environmentVariables = [ - 'IOTA_CB_URL', - 'IOTA_CB_HOST', - 'IOTA_CB_PORT', - 'IOTA_CB_NGSI_VERSION', - 'IOTA_NORTH_HOST', - 'IOTA_NORTH_PORT', - 'IOTA_PROVIDER_URL', - 'IOTA_AUTH_ENABLED', - 'IOTA_AUTH_TYPE', - 'IOTA_AUTH_HEADER', - 'IOTA_AUTH_URL', - 'IOTA_AUTH_HOST', - 'IOTA_AUTH_PORT', - 'IOTA_AUTH_USER', - 'IOTA_AUTH_PASSWORD', - 'IOTA_AUTH_CLIENT_ID', - 'IOTA_AUTH_CLIENT_SECRET', - 'IOTA_AUTH_TOKEN_PATH', - 'IOTA_AUTH_PERMANENT_TOKEN', - 'IOTA_REGISTRY_TYPE', - 'IOTA_LOG_LEVEL', - 'IOTA_TIMESTAMP', - 'IOTA_IOTAM_HOST', - 'IOTA_IOTAM_PORT', - 'IOTA_IOTAM_PATH', - 'IOTA_IOTAM_PROTOCOL', - 'IOTA_IOTAM_DESCRIPTION', - 'IOTA_DEFAULT_RESOURCE', - 'IOTA_MONGO_HOST', - 'IOTA_MONGO_PORT', - 'IOTA_MONGO_DB', - 'IOTA_MONGO_REPLICASET', - 'IOTA_AUTOCAST', - 'IOTA_MONGO_RETRIES', - 'IOTA_MONGO_RETRY_TIME', - 'IOTA_SINGLE_MODE', - 'IOTA_APPEND_MODE', - 'IOTA_POLLING_EXPIRATION', - 'IOTA_POLLING_DAEMON_FREQ', - 'IOTA_MULTI_CORE' - ], - iotamVariables = [ - 'IOTA_IOTAM_URL', - 'IOTA_IOTAM_HOST', - 'IOTA_IOTAM_PORT', - 'IOTA_IOTAM_PATH', - 'IOTA_IOTAM_PROTOCOL', - 'IOTA_IOTAM_DESCRIPTION', - 'IOTA_IOTAM_AGENTPATH' - ], - mongoVariables = [ - 'IOTA_MONGO_HOST', - 'IOTA_MONGO_PORT', - 'IOTA_MONGO_DB', - 'IOTA_MONGO_REPLICASET', - 'IOTA_MONGO_RETRIES', - 'IOTA_MONGO_RETRY_TIME' - ]; - - for (var i = 0; i < environmentVariables.length; i++) { + const environmentVariables = [ + 'IOTA_CB_URL', + 'IOTA_CB_HOST', + 'IOTA_CB_PORT', + 'IOTA_CB_NGSI_VERSION', + 'IOTA_NORTH_HOST', + 'IOTA_NORTH_PORT', + 'IOTA_PROVIDER_URL', + 'IOTA_AUTH_ENABLED', + 'IOTA_AUTH_TYPE', + 'IOTA_AUTH_HEADER', + 'IOTA_AUTH_URL', + 'IOTA_AUTH_HOST', + 'IOTA_AUTH_PORT', + 'IOTA_AUTH_USER', + 'IOTA_AUTH_PASSWORD', + 'IOTA_AUTH_CLIENT_ID', + 'IOTA_AUTH_CLIENT_SECRET', + 'IOTA_AUTH_TOKEN_PATH', + 'IOTA_AUTH_PERMANENT_TOKEN', + 'IOTA_REGISTRY_TYPE', + 'IOTA_LOG_LEVEL', + 'IOTA_TIMESTAMP', + 'IOTA_IOTAM_HOST', + 'IOTA_IOTAM_PORT', + 'IOTA_IOTAM_PATH', + 'IOTA_IOTAM_PROTOCOL', + 'IOTA_IOTAM_DESCRIPTION', + 'IOTA_DEFAULT_RESOURCE', + 'IOTA_MONGO_HOST', + 'IOTA_MONGO_PORT', + 'IOTA_MONGO_DB', + 'IOTA_MONGO_REPLICASET', + 'IOTA_AUTOCAST', + 'IOTA_MONGO_RETRIES', + 'IOTA_MONGO_RETRY_TIME', + 'IOTA_SINGLE_MODE', + 'IOTA_APPEND_MODE', + 'IOTA_POLLING_EXPIRATION', + 'IOTA_POLLING_DAEMON_FREQ', + 'IOTA_MULTI_CORE' + ]; + const iotamVariables = [ + 'IOTA_IOTAM_URL', + 'IOTA_IOTAM_HOST', + 'IOTA_IOTAM_PORT', + 'IOTA_IOTAM_PATH', + 'IOTA_IOTAM_PROTOCOL', + 'IOTA_IOTAM_DESCRIPTION', + 'IOTA_IOTAM_AGENTPATH' + ]; + const mongoVariables = [ + 'IOTA_MONGO_HOST', + 'IOTA_MONGO_PORT', + 'IOTA_MONGO_DB', + 'IOTA_MONGO_REPLICASET', + 'IOTA_MONGO_RETRIES', + 'IOTA_MONGO_RETRY_TIME' + ]; + + for (let i = 0; i < environmentVariables.length; i++) { if (process.env[environmentVariables[i]]) { - logger.info(context, 'Setting %s to environment value: %s', - environmentVariables[i], process.env[environmentVariables[i]]); + logger.info( + context, + 'Setting %s to environment value: %s', + environmentVariables[i], + process.env[environmentVariables[i]] + ); } } @@ -122,7 +124,7 @@ function processEnvironmentVariables() { if (config.contextBroker === undefined) { config.contextBroker = {}; } - + if (process.env.IOTA_CB_URL) { config.contextBroker.url = process.env.IOTA_CB_URL; // Not sure if config.contextBroker.host and config.contextBroker.port are used @@ -142,7 +144,7 @@ function processEnvironmentVariables() { config.contextBroker.url += ':' + config.contextBroker.port; } } - + if (process.env.IOTA_CB_NGSI_VERSION) { config.contextBroker.ngsiVersion = process.env.IOTA_CB_NGSI_VERSION; } @@ -151,7 +153,7 @@ function processEnvironmentVariables() { if (config.server === undefined) { config.server = {}; } - + if (process.env.IOTA_NORTH_HOST) { config.server.host = process.env.IOTA_NORTH_HOST; } @@ -368,9 +370,7 @@ function getCommandRegistry() { * @return {boolean} Result of the checking */ function checkNgsi2() { - if (config.contextBroker && - config.contextBroker.ngsiVersion && - config.contextBroker.ngsiVersion === 'v2') { + if (config.contextBroker && config.contextBroker.ngsiVersion && config.contextBroker.ngsiVersion === 'v2') { return true; } diff --git a/lib/constants.js b/lib/constants.js index 44c9b4d9f..9d81fd1c7 100644 --- a/lib/constants.js +++ b/lib/constants.js @@ -23,8 +23,6 @@ * Modified by: Daniel Calvo - ATOS Research & Innovation */ -'use strict'; - module.exports = { TIMESTAMP_ATTRIBUTE: 'TimeInstant', TIMESTAMP_TYPE: 'ISO8601', diff --git a/lib/errors.js b/lib/errors.js index 5d35e24f4..23dddb341 100644 --- a/lib/errors.js +++ b/lib/errors.js @@ -6,7 +6,8 @@ * fiware-iotagent-lib is free software: you can redistribute it and/or * modify it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the License, - * or (at your option) any later version. + * or { + constructor(at your option) any later version. * * fiware-iotagent-lib is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -22,154 +23,250 @@ * * Modified by: Daniel Calvo - ATOS Research & Innovation */ - -'use strict'; - -module.exports = { - RegistrationError: function(id, type) { +class RegistrationError { + constructor(id, type) { this.name = 'REGISTRATION_ERROR'; this.message = 'Error registering context provider for device: ' + id + ' of type: ' + type; - }, - UnregistrationError: function(id, type) { + } +} +class UnregistrationError { + constructor(id, type) { this.name = 'UNREGISTRATION_ERROR'; this.message = 'Error unregistering context provider for device: ' + id + ' of type: ' + type; - }, - EntityGenericError: function(id, type, details, code) { + } +} +class EntityGenericError { + constructor(id, type, details, code) { this.name = 'ENTITY_GENERIC_ERROR'; this.message = 'Error accesing entity data for device: ' + id + ' of type: ' + type; this.details = details || {}; this.code = code || 200; - }, - EntityNotFound: function(id) { + } +} +class EntityNotFound { + constructor(id) { this.name = 'ENTITY_NOT_FOUND'; this.message = 'The entity with the requested id [' + id + '] was not found.'; this.code = 404; - }, - RegistryNotAvailable: function() { + } +} +class RegistryNotAvailable { + constructor() { this.name = 'REGISTRY_NOT_AVAILABLE'; this.message = 'No device registry is available.'; - }, - InternalDbError: function(msg) { + } +} +class InternalDbError { + constructor(msg) { this.name = 'INTERNAL_DB_ERROR'; this.message = 'An internal DB Error happened: ' + msg; - }, - BadRequest: function(msg) { + } +} +class BadRequest { + constructor(msg) { this.name = 'BAD_REQUEST'; this.message = 'Request error connecting to the Context Broker: ' + msg; this.code = 400; - }, - UnsupportedContentType: function(type) { + } +} +class UnsupportedContentType { + constructor(type) { this.name = 'UNSUPPORTED_CONTENT_TYPE'; this.message = 'Unsuported content type in the context request: ' + type; this.code = 400; - }, - TypeNotFound: function(id, type) { + } +} +class TypeNotFound { + constructor(id, type) { this.name = 'TYPE_NOT_FOUND'; this.message = 'Type : ' + type + ' not found for device with id: ' + id; this.code = 500; - }, - MissingAttributes: function(msg) { + } +} +class MissingAttributes { + constructor(msg) { this.name = 'MISSING_ATTRIBUTES'; this.message = 'The request was not well formed:' + msg; - }, - DeviceNotFound: function(id) { + } +} +class DeviceNotFound { + constructor(id) { this.name = 'DEVICE_NOT_FOUND'; this.message = 'No device was found with id:' + id; this.code = 404; - }, - DuplicateDeviceId: function(id) { + } +} +class DuplicateDeviceId { + constructor(id) { this.name = 'DUPLICATE_DEVICE_ID'; this.message = 'A device with the same pair (Service, DeviceId) was found:' + id; this.code = 409; - }, - DuplicateGroup: function(res, key) { + } +} +class DuplicateGroup { + constructor(res, key) { this.name = 'DUPLICATE_GROUP'; this.message = 'A device configuration already exists for resource ' + res + ' and API Key ' + key; this.code = 409; - }, - SecurityInformationMissing: function(type) { + } +} +class SecurityInformationMissing { + constructor(type) { this.name = 'SECURITY_INFORMATION_MISSING'; this.message = 'Some security information was missing for device type:' + type; - }, - TokenRetrievalError: function(trust, msg) { + } +} +class TokenRetrievalError { + constructor(trust, msg) { this.name = 'TOKEN_RETRIEVAL_ERROR'; this.message = 'An error occurred trying to retrieve a token with trust [' + trust + ']: ' + msg; - }, - AccessForbidden: function(token, service, subservice) { + } +} +class AccessForbidden { + constructor(token, service, subservice) { this.name = 'ACCESS_FORBIDDEN'; - this.message = 'The access to the CB was rejected for service [' + - service + '] subservice [ ' + subservice + ' ] and token [' + token + ']'; - }, - AuthenticationError: function(trust) { + this.message = + 'The access to the CB was rejected for service [' + + service + + '] subservice [ ' + + subservice + + ' ] and token [' + + token + + ']'; + } +} +class AuthenticationError { + constructor(trust) { this.name = 'AUTHENTICATION_ERROR'; this.message = 'The trust configured for the device was rejected: [' + trust + ']'; - }, - BadConfiguration: function(msg) { + } +} +class BadConfiguration { + constructor(msg) { this.name = 'BAD_CONFIGURATION'; this.message = 'The application startup failed due to a bad configuration:' + msg; - }, - MissingHeaders: function(msg) { + } +} +class MissingHeaders { + constructor(msg) { this.name = 'MISSING_HEADERS'; this.message = 'Some headers were missing from the request: ' + msg; this.code = 400; - }, - MismatchedService: function(service, subservice) { + } +} +class MismatchedService { + /* eslint-disable-next-line no-unused-vars */ + constructor(service, subservice) { this.name = 'MISMATCHED_SERVICE'; - this.message = 'The declared service didn\'t match the stored one in the entity'; + + this.message = "The declared service didn't match the stored one in the entity"; this.code = 403; - }, - WrongSyntax: function(msg) { + } +} +class WrongSyntax { + constructor(msg) { this.name = 'WRONG_SYNTAX'; this.message = 'Wrong syntax in request: ' + msg; this.code = 400; - }, - CommandNotFound: function(name) { + } +} +class CommandNotFound { + constructor(name) { this.name = 'COMMAND_NOT_FOUND'; - this.message = 'Couldn\'t update the command because no command with the name [' + name + '] was found.'; + this.message = "Couldn't update the command because no command with the name [" + name + '] was found.'; this.code = 400; - }, - MissingConfigParams: function(missing) { + } +} +class MissingConfigParams { + constructor(missing) { this.name = 'MISSING_CONFIG_PARAMS'; this.message = 'The following mandatory configuration parameters were missing: ' + JSON.stringify(missing); this.code = 400; - }, - NotificationError: function(code) { + } +} +class NotificationError { + constructor(code) { this.name = 'NOTIFICATION_ERROR'; this.message = 'Incoming notification with non-200 status code: ' + code; this.code = 400; - }, - DeviceGroupNotFound: function(fields, values) { + } +} +class DeviceGroupNotFound { + constructor(fields, values) { this.name = 'DEVICE_GROUP_NOT_FOUND'; if (values && fields) { this.message = 'Couldn\t find device group for fields: ' + fields + ' and values: ' + values; } else { - this.message = 'Couldn\t find device group'; + this.message = "Couldn't find device group"; } this.code = 404; - }, - GroupNotFound: function(service, subservice) { + } +} +class GroupNotFound { + constructor(service, subservice) { this.name = 'GROUP_NOT_FOUND'; this.message = 'Group not found for service [' + service + '] and subservice [' + subservice + ']'; this.code = 404; - }, - WrongExpressionType: function(type) { + } +} +class WrongExpressionType { + constructor(type) { this.name = 'WRONG_EXPRESSION_TYPE'; this.message = 'Invalid type evaluating expression [' + type + ']'; this.code = 400; - }, - InvalidExpression: function(expression) { + } +} +class InvalidExpression { + constructor(expression) { this.name = 'INVALID_EXPRESSION'; this.message = 'Invalid expression in evaluation [' + expression + ']'; this.code = 400; - }, - BadAnswer: function(statusCode, operation) { + } +} +class BadAnswer { + constructor(statusCode, operation) { this.name = 'BAD_ANSWER'; this.message = 'Invalid statusCode in operation [' + operation + ']'; this.code = 400; - }, - BadTimestamp: function(payload) { + } +} +class BadTimestamp { + constructor(payload) { this.name = 'BAD_TIMESTAMP'; this.message = 'Invalid ISO8601 timestamp [' + payload + ']'; this.code = 400; } +} + +module.exports = { + RegistrationError, + UnregistrationError, + EntityGenericError, + EntityNotFound, + RegistryNotAvailable, + InternalDbError, + BadRequest, + UnsupportedContentType, + TypeNotFound, + MissingAttributes, + DeviceNotFound, + DuplicateDeviceId, + DuplicateGroup, + SecurityInformationMissing, + TokenRetrievalError, + AccessForbidden, + AuthenticationError, + BadConfiguration, + MissingHeaders, + MismatchedService, + WrongSyntax, + CommandNotFound, + MissingConfigParams, + NotificationError, + DeviceGroupNotFound, + GroupNotFound, + WrongExpressionType, + InvalidExpression, + BadAnswer, + BadTimestamp }; diff --git a/lib/fiware-iotagent-lib.js b/lib/fiware-iotagent-lib.js index c315a8a8b..e7031ec1d 100644 --- a/lib/fiware-iotagent-lib.js +++ b/lib/fiware-iotagent-lib.js @@ -21,41 +21,42 @@ * please contact with::daniel.moranjimenez@telefonica.com */ -'use strict'; - -var async = require('async'), - apply = async.apply, - ngsi = require('./services/ngsi/ngsiService'), - intoTrans = require('./services/common/domain').intoTrans, - middlewares = require('./services/common/genericMiddleware'), - db = require('./model/dbConn'), - subscriptions = require('./services/ngsi/subscriptionService'), - statsRegistry = require('./services/stats/statsRegistry'), - domainUtils = require('./services/common/domain'), - deviceService = require('./services/devices/deviceService'), - groupConfig = require('./services/groups/groupService'), - commands = require('./services/commands/commandService'), - iotManager = require('./services/common/iotManagerService'), - contextServer = require('./services/northBound/northboundServer'), - errors = require('./errors'), - constants = require('./constants'), - logger = require('logops'), - config = require('./commonConfig'), - cluster = require('cluster'), - context = { - op: 'IoTAgentNGSI.Global' - }; +const async = require('async'); +const apply = async.apply; +const ngsi = require('./services/ngsi/ngsiService'); +const intoTrans = require('./services/common/domain').intoTrans; +const middlewares = require('./services/common/genericMiddleware'); +const db = require('./model/dbConn'); +const subscriptions = require('./services/ngsi/subscriptionService'); +const statsRegistry = require('./services/stats/statsRegistry'); +const domainUtils = require('./services/common/domain'); +const deviceService = require('./services/devices/deviceService'); +const groupConfig = require('./services/groups/groupService'); +const commands = require('./services/commands/commandService'); +const iotManager = require('./services/common/iotManagerService'); +const contextServer = require('./services/northBound/northboundServer'); +const errors = require('./errors'); +const constants = require('./constants'); +const logger = require('logops'); +const config = require('./commonConfig'); +const cluster = require('cluster'); +const context = { + op: 'IoTAgentNGSI.Global' +}; function activateStatLogs(newConfig, callback) { if (newConfig.stats && newConfig.stats.interval) { - async.series([ - apply(statsRegistry.globalLoad, { - deviceCreationRequests: 0, - deviceRemovalRequests: 0, - measureRequests: 0 - }), - apply(statsRegistry.addTimerAction, statsRegistry.logStats) - ], callback); + async.series( + [ + apply(statsRegistry.globalLoad, { + deviceCreationRequests: 0, + deviceRemovalRequests: 0, + measureRequests: 0 + }), + apply(statsRegistry.addTimerAction, statsRegistry.logStats) + ], + callback + ); } else { callback(); } @@ -79,36 +80,36 @@ function globalErrorHandler(err) { * @param {Function} callback The callback function. */ function doActivate(newConfig, callback) { - var registry, - groupRegistry, - commandRegistry, - securityService; + let registry; + let groupRegistry; + let commandRegistry; + let securityService; if (newConfig.contextBroker) { - if (! newConfig.contextBroker.url && newConfig.contextBroker.host && newConfig.contextBroker.port) { + if (!newConfig.contextBroker.url && newConfig.contextBroker.host && newConfig.contextBroker.port) { newConfig.contextBroker.url = 'http://' + newConfig.contextBroker.host + ':' + newConfig.contextBroker.port; - } else if (! newConfig.contextBroker.url && newConfig.contextBroker.host && !newConfig.contextBroker.port) { + } else if (!newConfig.contextBroker.url && newConfig.contextBroker.host && !newConfig.contextBroker.port) { newConfig.contextBroker.url = 'http://' + newConfig.contextBroker.host; } } if (newConfig.iotManager) { - if (! newConfig.iotManager.url && newConfig.iotManager.host && newConfig.iotManager.port) { + if (!newConfig.iotManager.url && newConfig.iotManager.host && newConfig.iotManager.port) { newConfig.iotManager.url = 'http://' + newConfig.iotManager.host + ':' + newConfig.iotManager.port; - } else if (! newConfig.iotManager.url && newConfig.iotManager.host && !newConfig.iotManager.port) { + } else if (!newConfig.iotManager.url && newConfig.iotManager.host && !newConfig.iotManager.port) { newConfig.iotManager.url = 'http://' + newConfig.iotManager.host; } } if (newConfig.authentication && newConfig.authentication.enabled) { - if (! newConfig.authentication.header) { + if (!newConfig.authentication.header) { newConfig.authentication.header = constants.AUTH_HEADER; } - if (! newConfig.authentication.url && newConfig.authentication.host && newConfig.authentication.port) { - newConfig.authentication.url = 'http://' + newConfig.authentication.host + ':' + - newConfig.authentication.port; - } else if (! newConfig.authentication.url && newConfig.authentication.host && !newConfig.authentication.port) { + if (!newConfig.authentication.url && newConfig.authentication.host && newConfig.authentication.port) { + newConfig.authentication.url = + 'http://' + newConfig.authentication.host + ':' + newConfig.authentication.port; + } else if (!newConfig.authentication.url && newConfig.authentication.host && !newConfig.authentication.port) { newConfig.authentication.url = 'http://' + newConfig.authentication.host; } } @@ -118,8 +119,7 @@ function doActivate(newConfig, callback) { logger.info(context, 'Activating IOT Agent NGSI Library.'); if (newConfig.authentication && newConfig.authentication.enabled) { - if (newConfig.authentication.type && - newConfig.authentication.type === 'oauth2') { + if (newConfig.authentication.type && newConfig.authentication.type === 'oauth2') { logger.info(context, 'Using OAuth2 as authentication service'); securityService = require('./services/common/securityServiceOAuth2'); @@ -130,9 +130,7 @@ function doActivate(newConfig, callback) { } } - if (newConfig.deviceRegistry && - newConfig.deviceRegistry.type && - newConfig.deviceRegistry.type === 'mongodb') { + if (newConfig.deviceRegistry && newConfig.deviceRegistry.type && newConfig.deviceRegistry.type === 'mongodb') { logger.info(context, 'MongoDB Device registry selected for NGSI Library'); registry = require('./services/devices/deviceRegistryMongoDB'); @@ -147,13 +145,10 @@ function doActivate(newConfig, callback) { } exports.clearAll = function(callback) { - async.series([ - registry.clear, - groupRegistry.clear, - commandRegistry.clear, - ngsi.resetMiddlewares, - contextServer.clear - ], callback); + async.series( + [registry.clear, groupRegistry.clear, commandRegistry.clear, ngsi.resetMiddlewares, contextServer.clear], + callback + ); }; if (!config.getConfig().dieOnUnexpectedError) { @@ -167,18 +162,14 @@ function doActivate(newConfig, callback) { commands.start(); - async.series([ - db.configureDb, - apply(contextServer.start, newConfig), - apply(activateStatLogs, newConfig) - ], callback); + async.series([db.configureDb, apply(contextServer.start, newConfig), apply(activateStatLogs, newConfig)], callback); } function checkConfig(newConfig, callback) { - var mandatory = ['providerUrl', 'types'], - missing = []; + const mandatory = ['providerUrl', 'types']; + const missing = []; - for (var i in mandatory) { + for (const i in mandatory) { if (!newConfig[mandatory[i]]) { missing.push(mandatory[i]); } @@ -186,15 +177,15 @@ function checkConfig(newConfig, callback) { if (newConfig.authentication && newConfig.authentication.enabled) { if (newConfig.authentication.type && newConfig.authentication.type === 'oauth2') { - var mandatoryOauth = ['tokenPath', 'clientId', 'clientSecret']; - for (var j in mandatoryOauth) { + const mandatoryOauth = ['tokenPath', 'clientId', 'clientSecret']; + for (const j in mandatoryOauth) { if (!newConfig.authentication[mandatoryOauth[j]]) { missing.push('authentication.' + mandatoryOauth[j]); } } } else { - var mandatoryKeystone = ['user', 'password']; - for (var k in mandatoryKeystone) { + const mandatoryKeystone = ['user', 'password']; + for (const k in mandatoryKeystone) { if (!newConfig.authentication[mandatoryKeystone[k]]) { missing.push('authentication.' + mandatoryKeystone[k]); } @@ -210,11 +201,7 @@ function checkConfig(newConfig, callback) { } function activate(newConfig, callback) { - async.series([ - apply(checkConfig, newConfig), - apply(doActivate, newConfig), - iotManager.register - ], callback); + async.series([apply(checkConfig, newConfig), apply(doActivate, newConfig), iotManager.register], callback); } /** @@ -243,7 +230,7 @@ function startServer(newConfig, iotAgent, callback) { // get the proper context of the logger logger.getContext = function domainContext() { - var domainObj = require('domain').active || {}; + const domainObj = require('domain').active || {}; return { corr: domainObj.corr, @@ -261,27 +248,26 @@ function startServer(newConfig, iotAgent, callback) { if (cluster.isMaster) { // Code to run if we're in a master node process // Count the machine's CPUs - var cpuCount = require('os').cpus().length; + const cpuCount = require('os').cpus().length; logger.info(context, 'Master cluster setting up ' + cpuCount + ' workers...'); // Create a worker for each CPU in the machine - for (var i = 0; i < cpuCount; i += 1) { + for (let i = 0; i < cpuCount; i += 1) { cluster.fork(); } // Log information about the creation of the workers - cluster.on('online', function (worker) { + cluster.on('online', function(worker) { logger.info(context, 'Worker ' + worker.process.pid + ' is online'); }); // If a worker died, automatically we create a new worker to replace it - cluster.on('exit', function (worker, code, signal) { - var message = 'Worker ' + worker.process.pid + ' died with code: ' + code + ', and signal: ' + signal; + cluster.on('exit', function(worker, code, signal) { + const message = 'Worker ' + worker.process.pid + ' died with code: ' + code + ', and signal: ' + signal; logger.warn(context, message); logger.warn(context, 'Starting a new worker...'); cluster.fork(); }); - } else { // We are in the worker, and they can share any TCP connection logger.info(context, 'Starting a new worker...'); @@ -294,7 +280,6 @@ function startServer(newConfig, iotAgent, callback) { } } - exports.activate = intoTrans(context, activate); exports.deactivate = intoTrans(context, deactivate); exports.register = deviceService.register; diff --git a/lib/model/Command.js b/lib/model/Command.js index 4169c89c2..3706b971a 100644 --- a/lib/model/Command.js +++ b/lib/model/Command.js @@ -20,12 +20,11 @@ * For those usages not covered by the GNU Affero General Public License * please contact with::daniel.moranjimenez@telefonica.com */ -'use strict'; -var mongoose = require('mongoose'), - Schema = mongoose.Schema; +const mongoose = require('mongoose'); +const Schema = mongoose.Schema; -var Command = new Schema({ +const Command = new Schema({ deviceId: String, type: String, name: String, diff --git a/lib/model/Device.js b/lib/model/Device.js index a367126e3..00d800360 100644 --- a/lib/model/Device.js +++ b/lib/model/Device.js @@ -20,12 +20,11 @@ * For those usages not covered by the GNU Affero General Public License * please contact with::daniel.moranjimenez@telefonica.com */ -'use strict'; -var mongoose = require('mongoose'), - Schema = mongoose.Schema; +const mongoose = require('mongoose'); +const Schema = mongoose.Schema; -var Device = new Schema({ +const Device = new Schema({ id: String, type: String, name: String, diff --git a/lib/model/Group.js b/lib/model/Group.js index 447524d4c..56352b853 100644 --- a/lib/model/Group.js +++ b/lib/model/Group.js @@ -20,12 +20,11 @@ * For those usages not covered by the GNU Affero General Public License * please contact with::daniel.moranjimenez@telefonica.com */ -'use strict'; -var mongoose = require('mongoose'), - Schema = mongoose.Schema; +const mongoose = require('mongoose'); +const Schema = mongoose.Schema; -var Group = new Schema({ +const Group = new Schema({ url: String, resource: String, apikey: String, diff --git a/lib/model/dbConn.js b/lib/model/dbConn.js index 2b533a58b..92f2358c9 100644 --- a/lib/model/dbConn.js +++ b/lib/model/dbConn.js @@ -20,25 +20,24 @@ * For those usages not covered by the GNU Affero General Public License * please contact with::daniel.moranjimenez@telefonica.com */ -'use strict'; /** * This module sets up the connection with the mongodb through mongoose. This connection will be used * in mongoose schemas to persist objects. */ -var mongoose = require('mongoose'), - config = require('../commonConfig'), - constants = require('../constants'), - alarms = require('../services/common/alarmManagement'), - logger = require('logops'), - async = require('async'), - errors = require('../errors'), - defaultDb, - DEFAULT_DB_NAME = 'iotagent', - context = { - op: 'IoTAgentNGSI.DbConn' - }; +const mongoose = require('mongoose'); +const config = require('../commonConfig'); +const constants = require('../constants'); +const alarms = require('../services/common/alarmManagement'); +const logger = require('logops'); +const async = require('async'); +const errors = require('../errors'); +let defaultDb; +const DEFAULT_DB_NAME = 'iotagent'; +const context = { + op: 'IoTAgentNGSI.DbConn' +}; function loadModels() { require('./Device').load(defaultDb); @@ -52,14 +51,12 @@ function loadModels() { * @this Reference to the dbConn module itself. */ function init(host, db, port, username, password, options, callback) { - /*jshint camelcase:false, validthis:true */ - var hosts, - url, - credentials = '', - retries = 0, - lastError, - maxRetries = (config.getConfig().mongodb && config.getConfig().mongodb.retries || - constants.DEFAULT_MONGODB_RETRIES); + let url; + let credentials = ''; + let retries = 0; + let lastError; + const maxRetries = + (config.getConfig().mongodb && config.getConfig().mongodb.retries) || constants.DEFAULT_MONGODB_RETRIES; if (username && password) { credentials = username + ':' + password + '@'; @@ -79,7 +76,8 @@ function init(host, db, port, username, password, options, callback) { return previous; } - hosts = host.split(',') + const hosts = host + .split(',') .map(addPort) .reduce(commaConcat, ''); @@ -89,6 +87,7 @@ function init(host, db, port, username, password, options, callback) { url += '?replicaSet=' + options.replicaSet.rs_name; } + /* eslint-disable-next-line no-unused-vars */ function createConnectionHandler(error, results) { if (defaultDb) { logger.info(context, 'Successfully connected to MongoDB.'); @@ -106,12 +105,11 @@ function init(host, db, port, username, password, options, callback) { } function connectionAttempt(url, options, callback) { - var candidateDb; - logger.info(context, 'Attempting to connect to MongoDB instance. Attempt %d', retries); options.useNewUrlParser = true; mongoose.set('useCreateIndex', true); - candidateDb = mongoose.createConnection(url, options, function(error, result) { + /* eslint-disable-next-line no-unused-vars */ + const candidateDb = mongoose.createConnection(url, options, function(error, result) { if (error) { logger.error(context, 'MONGODB-001: Error trying to connect to MongoDB: %s', error); lastError = error; @@ -122,7 +120,7 @@ function init(host, db, port, username, password, options, callback) { logger.error(context, 'Mongo Driver error: %j', error); alarms.raise(constants.MONGO_ALARM, error); }); - defaultDb.on('connecting', function(error) { + defaultDb.on('connecting', function() { logger.debug(context, 'Mongo Driver connecting'); }); defaultDb.on('connected', function() { @@ -154,9 +152,10 @@ function init(host, db, port, username, password, options, callback) { } function tryCreateConnection(callback) { - var attempt = async.apply(connectionAttempt, url, options, callback), - seconds = (config.getConfig().mongodb && config.getConfig().mongodb.retryTime || - constants.DEFAULT_MONGODB_RETRY_TIME); + const attempt = async.apply(connectionAttempt, url, options, callback); + const seconds = + (config.getConfig().mongodb && config.getConfig().mongodb.retryTime) || + constants.DEFAULT_MONGODB_RETRY_TIME; retries++; @@ -174,18 +173,19 @@ function init(host, db, port, username, password, options, callback) { } function configureDb(callback) { - /*jshint camelcase:false, validthis:true */ - var currentConfig = config.getConfig(); + const currentConfig = config.getConfig(); - if ((currentConfig.deviceRegistry && currentConfig.deviceRegistry.type === 'mongodb') || - (currentConfig.stats && currentConfig.stats.persistence === true)) { + if ( + (currentConfig.deviceRegistry && currentConfig.deviceRegistry.type === 'mongodb') || + (currentConfig.stats && currentConfig.stats.persistence === true) + ) { if (!currentConfig.mongodb || !currentConfig.mongodb.host) { logger.fatal(context, 'MONGODB-003: No host found for MongoDB driver.'); callback(new errors.BadConfiguration('No host found for MongoDB driver')); } else { - var dbName = currentConfig.mongodb.db, - port = currentConfig.mongodb.port || 27017, - options = {}; + let dbName = currentConfig.mongodb.db; + const port = currentConfig.mongodb.port || 27017; + const options = {}; if (!currentConfig.mongodb.db) { dbName = DEFAULT_DB_NAME; @@ -195,8 +195,15 @@ function configureDb(callback) { options.replset = { rs_name: currentConfig.mongodb.replicaSet }; } - init(config.getConfig().mongodb.host, dbName, port, - currentConfig.username, currentConfig.password, options, callback); + init( + config.getConfig().mongodb.host, + dbName, + port, + currentConfig.username, + currentConfig.password, + options, + callback + ); } } else { callback(); diff --git a/lib/plugins/addEvent.js b/lib/plugins/addEvent.js index 9548e8994..6a3862648 100644 --- a/lib/plugins/addEvent.js +++ b/lib/plugins/addEvent.js @@ -1,4 +1,3 @@ - /* * Copyright 2016 Telefonica Investigación y Desarrollo, S.A.U * @@ -22,13 +21,11 @@ * please contact with::daniel.moranjimenez@telefonica.com */ -'use strict'; - -var pluginUtils = require('./pluginUtils'), - config = require('../commonConfig'); +const pluginUtils = require('./pluginUtils'); +const config = require('../commonConfig'); function addEvents() { - return (new Date()).toISOString(); + return new Date().toISOString(); } exports.update = pluginUtils.createUpdateFilter(addEvents, config.getConfig().eventType || 'Event'); diff --git a/lib/plugins/attributeAlias.js b/lib/plugins/attributeAlias.js index e868b3e9d..f266409a2 100644 --- a/lib/plugins/attributeAlias.js +++ b/lib/plugins/attributeAlias.js @@ -23,21 +23,18 @@ * Modified by: Daniel Calvo - ATOS Research & Innovation */ -'use strict'; +const config = require('../commonConfig'); +const utils = require('./pluginUtils'); -var config = require('../commonConfig'), - utils = require('./pluginUtils'), - /*jshint unused:false*/ - logger = require('logops'), - /*jshint unused:false*/ - context = { - op: 'IoTAgentNGSI.attributeAlias' - }, - ngsiService = require('../services/ngsi/ngsiService'); +/* eslint-disable-next-line no-unused-vars */ +const logger = require('logops'); +/* eslint-disable-next-line no-unused-vars */ +const context = { + op: 'IoTAgentNGSI.attributeAlias' +}; +const ngsiService = require('../services/ngsi/ngsiService'); function extractSingleMapping(previous, current) { - /* jshint camelcase: false */ - previous.direct[current.object_id] = current.name; previous.types[current.object_id] = current.type; previous.inverse[current.name] = current.object_id; // collision using multientity @@ -51,7 +48,7 @@ function extractSingleMapping(previous, current) { * @return {{direct: {}, inverse: {}}} Object containing the direct and reverse name mappings. */ function extractAllMappings(typeInformation) { - var mappings = { direct: {}, inverse: {}, types: {}}; + let mappings = { direct: {}, inverse: {}, types: {} }; if (typeInformation.active) { mappings = typeInformation.active.reduce(extractSingleMapping, mappings); @@ -78,7 +75,6 @@ function applyAlias(mappings) { return function aliasApplier(attribute) { if (mappings.direct[attribute.name]) { if (config.checkNgsi2()) { - /*jshint camelcase: false */ attribute.object_id = attribute.name; // inverse not usefull due to collision } attribute.type = mappings.types[attribute.name]; @@ -96,9 +92,9 @@ function applyAlias(mappings) { * @param {Object} typeInformation Provisioning information about the device represented by the entity. */ function updateAttribute(entity, typeInformation, callback) { - var mappings = extractAllMappings(typeInformation); + const mappings = extractAllMappings(typeInformation); if (config.checkNgsi2()) { - var attsArray = utils.extractAttributesArrayFromNgsi2Entity(entity); + let attsArray = utils.extractAttributesArrayFromNgsi2Entity(entity); attsArray = attsArray.map(applyAlias(mappings)); entity = utils.createNgsi2Entity(entity.id, entity.type, attsArray, true); ngsiService.castJsonNativeAttributes(entity); diff --git a/lib/plugins/bidirectionalData.js b/lib/plugins/bidirectionalData.js index 9ff44faad..8ab851112 100644 --- a/lib/plugins/bidirectionalData.js +++ b/lib/plugins/bidirectionalData.js @@ -23,19 +23,17 @@ * Modified by: Daniel Calvo - ATOS Research & Innovation */ -'use strict'; - -var async = require('async'), - apply = async.apply, - _ = require('underscore'), - parser = require('./expressionParser'), - logger = require('logops'), - subscriptions = require('../services/ngsi/subscriptionService'), - deviceService = require('../services/devices/deviceService'), - context = { - op: 'IoTAgentNGSI.BidirectionalPlugin' - }, - config = require('../commonConfig'); +const async = require('async'); +const apply = async.apply; +const _ = require('underscore'); +const parser = require('./expressionParser'); +const logger = require('logops'); +const subscriptions = require('../services/ngsi/subscriptionService'); +const deviceService = require('../services/devices/deviceService'); +const context = { + op: 'IoTAgentNGSI.BidirectionalPlugin' +}; +const config = require('../commonConfig'); /** * Extract a list of all the bidirectional attributes (those containing reverse expressions) from a device object. @@ -45,7 +43,7 @@ var async = require('async'), * @param {Object} group Configuration Group data object. */ function extractBidirectionalAttributes(device, group, callback) { - var attributeList; + let attributeList; function isBidirectional(item) { return item.reverse; @@ -73,16 +71,15 @@ function extractBidirectionalAttributes(device, group, callback) { * @return {Array} List of variables in all the collection of reverse expressions. */ function extractVariables(item) { - var variables; + let variables; function extractFromExpression(value) { if (value.expression) { return value.expression.match(/@[a-zA-Z]+/g).map(function(item) { return item.substr(1); }); - } else { - return []; } + return []; } if (item.reverse) { @@ -101,9 +98,8 @@ function extractVariables(item) { * @param {Array} attributeList List of active attributes for subscription. */ function sendSubscriptions(device, attributeList, callback) { - function sendSingleSubscriptionNgsi1(item, innerCb) { - var variables = extractVariables(item); + const variables = extractVariables(item); subscriptions.subscribe(device, [item.name], variables, function handleSubscription(error, subId) { if (error) { @@ -118,7 +114,7 @@ function sendSubscriptions(device, attributeList, callback) { } function sendSingleSubscriptionNgsi2(item, innerCb) { - var variables = extractVariables(item); + const variables = extractVariables(item); subscriptions.subscribe(device, [item.name], variables, function handleSubscription(error, subId) { if (error) { @@ -176,8 +172,8 @@ function handleGroupProvision(newGroup, callback) { * @param {Array} values List of reported attributes (with their name, type and value). */ function getReverseTransformations(list, values, callback) { - var availableData = _.pluck(values, 'name'), - transformations = []; + const availableData = _.pluck(values, 'name'); + let transformations = []; function getVariable(expression) { return expression.match(/@[a-zA-Z]+/g).map(function(item) { @@ -186,10 +182,10 @@ function getReverseTransformations(list, values, callback) { } if (list && list.length > 0) { - for (var i = 0; i < list.length; i++) { + for (let i = 0; i < list.length; i++) { if (list[i].reverse && list[i].reverse.length > 0) { - var expressions = _.pluck(list[i].reverse, 'expression'), - variables = _.uniq(_.flatten(expressions.map(getVariable))); + const expressions = _.pluck(list[i].reverse, 'expression'); + const variables = _.uniq(_.flatten(expressions.map(getVariable))); if (_.difference(variables, availableData).length === 0) { transformations = transformations.concat(list[i].reverse); @@ -210,21 +206,21 @@ function getReverseTransformations(list, values, callback) { * @param {Array} transformations List of transformations to apply (with their name, type and expression). */ function processTransformations(values, transformations, callback) { - /*jshint camelcase:false */ + let cleanedExpression; + const ctx = parser.extractContext(values); + let resultTransformations = []; - var cleanedExpression, - ctx = parser.extractContext(values), - resultTransformations = []; - - for (var j = 0; j < 2; j++) { + for (let j = 0; j < 2; j++) { if (transformations[j]) { resultTransformations = resultTransformations.concat(transformations[j]); } } - for (var i = 0; i < resultTransformations.length; i++) { - cleanedExpression = resultTransformations[i].expression - .substr(2, resultTransformations[i].expression.length - 3); + for (let i = 0; i < resultTransformations.length; i++) { + cleanedExpression = resultTransformations[i].expression.substr( + 2, + resultTransformations[i].expression.length - 3 + ); values.push({ name: resultTransformations[i].object_id, @@ -247,17 +243,17 @@ function handleDeviceProvision(device, callback) { if (error) { callback(error); } else { - async.waterfall([ - apply(extractBidirectionalAttributes, device, group), - apply(sendSubscriptions, device) - ], function(error, subscriptionMaps) { - if (error) { - callback(error); - } else { - device = updateDeviceWithSubscriptionIds(subscriptionMaps, device); - callback(null, device); + async.waterfall( + [apply(extractBidirectionalAttributes, device, group), apply(sendSubscriptions, device)], + function(error, subscriptionMaps) { + if (error) { + callback(error); + } else { + device = updateDeviceWithSubscriptionIds(subscriptionMaps, device); + callback(null, device); + } } - }); + ); } }); } @@ -271,21 +267,24 @@ function handleDeviceProvision(device, callback) { */ function handleNotification(device, values, callback) { deviceService.findConfigurationGroup(device, function(error, group) { - var deviceAttributes = device.active || [], - groupAttributes = group && group.attributes || []; + const deviceAttributes = device.active || []; + const groupAttributes = (group && group.attributes) || []; if (deviceAttributes.length > 0 || groupAttributes.length > 0) { logger.debug(context, 'Processing active attributes notification'); - async.waterfall([ - apply(async.series, [ - apply(getReverseTransformations, deviceAttributes, values), - apply(getReverseTransformations, groupAttributes, values) - ]), - apply(processTransformations, values) - ], function(error, results) { - callback(error, device, results); - }); + async.waterfall( + [ + apply(async.series, [ + apply(getReverseTransformations, deviceAttributes, values), + apply(getReverseTransformations, groupAttributes, values) + ]), + apply(processTransformations, values) + ], + function(error, results) { + callback(error, device, results); + } + ); } else { callback(null, device, values); } @@ -295,4 +294,3 @@ function handleNotification(device, values, callback) { exports.deviceProvision = handleDeviceProvision; exports.groupProvision = handleGroupProvision; exports.notification = handleNotification; - diff --git a/lib/plugins/compressTimestamp.js b/lib/plugins/compressTimestamp.js index 206c022ad..8fdf510eb 100644 --- a/lib/plugins/compressTimestamp.js +++ b/lib/plugins/compressTimestamp.js @@ -1,4 +1,3 @@ - /* * Copyright 2015 Telefonica Investigación y Desarrollo, S.A.U * @@ -24,10 +23,8 @@ * Modified by: Daniel Calvo - ATOS Research & Innovation */ -'use strict'; - -var pluginUtils = require('./pluginUtils'), - constants = require('../constants'); +const pluginUtils = require('./pluginUtils'); +const constants = require('../constants'); /** * Takes a string representation of a date in ISO8601 basic calendar format and transforms it into @@ -37,14 +34,12 @@ var pluginUtils = require('./pluginUtils'), * @return {String} Date in extended format. */ function fromBasicToExtended(date) { - var split = date.match(/(\d{4})(\d{2})(\d{2})T(\d{2})(\d{2})(\d{2})/); + const split = date.match(/(\d{4})(\d{2})(\d{2})T(\d{2})(\d{2})(\d{2})/); if (split) { - return '+00' + split[1] + '-' + split[2] + '-' + split[3] + 'T' + - split[4] + ':' + split[5] + ':' + split[6]; - } else { - return null; + return '+00' + split[1] + '-' + split[2] + '-' + split[3] + 'T' + split[4] + ':' + split[5] + ':' + split[6]; } + return null; } /** @@ -55,13 +50,12 @@ function fromBasicToExtended(date) { * @return {String} Date in basic format. */ function fromExtendedToBasic(date) { - var split = date.match(/\+00(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})/); + const split = date.match(/\+00(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})/); if (split) { return split[1] + split[2] + split[3] + 'T' + split[4] + split[5] + split[6]; - } else { - return null; } + return null; } exports.update = pluginUtils.createUpdateFilter(fromBasicToExtended, constants.TIMESTAMP_TYPE); diff --git a/lib/plugins/expressionParser.js b/lib/plugins/expressionParser.js index c509f154c..a8bd53852 100644 --- a/lib/plugins/expressionParser.js +++ b/lib/plugins/expressionParser.js @@ -23,72 +23,69 @@ * Modified by: Daniel Calvo - ATOS Research & Innovation */ -'use strict'; - -var Parser = require('jison').Parser, - errors = require('../errors'), - config = require('../commonConfig'), - _ = require('underscore'), - grammar = { - lex: { - rules: [ - ['\\s+', '/* skip whitespace */'], - ['@[a-zA-Z0-9]+\\b', 'return "VARIABLE";'], - ['[0-9]+(?:\\.[0-9]+)?\\b', 'return "NUMBER";'], - ['\\*', 'return "*";'], - ['\\/', 'return "/";'], - ['-', 'return "-";'], - ['\\+', 'return "+";'], - ['\\^', 'return "^";'], - ['\\(', 'return "(";'], - ['\\)', 'return ")";'], - [',', 'return ",";'], - ['#', 'return "#";'], - ['indexOf', 'return "INDEX";'], - ['length', 'return "LENGTH";'], - ['substr', 'return "SUBSTR";'], - ['trim', 'return "TRIM";'], - ['"[a-zA-Z0-9\\s,]+"', 'return "STRING";'], - ['\'[a-zA-Z0-9\\s,]+\'', 'return "STRING";'], - ['$', 'return "EOF";'] - ] - }, - - operators: [ - ['left', '#', '+', '-'], - ['left', '*', '/'], - ['left', '^'], - ['left', 'UMINUS'] - ], - - bnf: { - expressions: [['e EOF', 'return $1;']], - - e: [ - ['e + e', '$$ = Number($1) + Number($3);'], - ['e - e', '$$ = $1 - $3;'], - ['e * e', '$$ = $1 * $3;'], - ['e / e', '$$ = $1 / $3;'], - ['e ^ e', '$$ = Math.pow($1, $3);'], - ['e # e', '$$ = String($1) + String($3);'], - ['- e', '$$ = -$2;', {'prec': 'UMINUS'}], - ['INDEX ( e , e )', '$$ = String($3).indexOf($5)'], - ['SUBSTR ( e , e , e )', '$$ = String($3).substr($5, $7)'], - ['LENGTH ( e )', '$$ = String($3).length'], - ['TRIM ( e )', '$$ = String($3).trim()'], - ['( e )', '$$ = $2;'], - ['NUMBER', '$$ = Number(yytext);'], - ['VARIABLE', '$$ = yy[yytext.substr(1)];'], - ['STRING', '$$ = yytext.substr(1, yytext.length -2);'], - ['E', '$$ = Math.E;'], - ['PI', '$$ = Math.PI;']] - } +/* eslint-disable consistent-return */ + +const Parser = require('jison').Parser; +const errors = require('../errors'); +const config = require('../commonConfig'); +const _ = require('underscore'); +const grammar = { + lex: { + rules: [ + ['\\s+', '/* skip whitespace */'], + ['@[a-zA-Z0-9]+\\b', 'return "VARIABLE";'], + ['[0-9]+(?:\\.[0-9]+)?\\b', 'return "NUMBER";'], + ['\\*', 'return "*";'], + ['\\/', 'return "/";'], + ['-', 'return "-";'], + ['\\+', 'return "+";'], + ['\\^', 'return "^";'], + ['\\(', 'return "(";'], + ['\\)', 'return ")";'], + [',', 'return ",";'], + ['#', 'return "#";'], + ['indexOf', 'return "INDEX";'], + ['length', 'return "LENGTH";'], + ['substr', 'return "SUBSTR";'], + ['trim', 'return "TRIM";'], + ['"[a-zA-Z0-9\\s,]+"', 'return "STRING";'], + + ["'[a-zA-Z0-9\\s,]+'", 'return "STRING";'], + ['$', 'return "EOF";'] + ] }, - parser = new Parser(grammar); + + operators: [['left', '#', '+', '-'], ['left', '*', '/'], ['left', '^'], ['left', 'UMINUS']], + + bnf: { + expressions: [['e EOF', 'return $1;']], + + e: [ + ['e + e', '$$ = Number($1) + Number($3);'], + ['e - e', '$$ = $1 - $3;'], + ['e * e', '$$ = $1 * $3;'], + ['e / e', '$$ = $1 / $3;'], + ['e ^ e', '$$ = Math.pow($1, $3);'], + ['e # e', '$$ = String($1) + String($3);'], + ['- e', '$$ = -$2;', { prec: 'UMINUS' }], + ['INDEX ( e , e )', '$$ = String($3).indexOf($5)'], + ['SUBSTR ( e , e , e )', '$$ = String($3).substr($5, $7)'], + ['LENGTH ( e )', '$$ = String($3).length'], + ['TRIM ( e )', '$$ = String($3).trim()'], + ['( e )', '$$ = $2;'], + ['NUMBER', '$$ = Number(yytext);'], + ['VARIABLE', '$$ = yy[yytext.substr(1)];'], + ['STRING', '$$ = yytext.substr(1, yytext.length -2);'], + ['E', '$$ = Math.E;'], + ['PI', '$$ = Math.PI;'] + ] + } +}; +const parser = new Parser(grammar); function parse(expression, context, type, callback) { - var result, - error; + let result; + let error; if (type !== 'String' && type !== 'Number') { error = new errors.WrongExpressionType(type); @@ -107,9 +104,8 @@ function parse(expression, context, type, callback) { if (callback) { return callback(error); - } else { - throw error; } + throw error; } if (callback) { @@ -121,23 +117,21 @@ function parse(expression, context, type, callback) { } function extractContext(attributeList) { - var context = {}; + const context = {}; - for (var i = 0; i < attributeList.length; i++) { + for (let i = 0; i < attributeList.length; i++) { context[attributeList[i].name] = attributeList[i].value; } return context; } - function processExpression(context) { return function(expression) { - var result, - cleanedExpression = expression.substr(2, expression.length - 3); + const cleanedExpression = expression.substr(2, expression.length - 3); // Note that parse() function allows both String way processing and Number way processing // (have a look to expression-test.js). However, here we only use one of the possibilities, i.e. String - result = parse(cleanedExpression, context, 'String'); + const result = parse(cleanedExpression, context, 'String'); return { original: expression, @@ -146,12 +140,13 @@ function processExpression(context) { }; } +/* eslint-disable-next-line no-unused-vars */ function applyExpression(expression, context, typeInformation) { - var expressionList = expression.match(/\$\{.*?\}/g) || [], - substitutions = expressionList.map(processExpression(context)), - expressionResult = expression; + const expressionList = expression.match(/\$\{.*?\}/g) || []; + const substitutions = expressionList.map(processExpression(context)); + let expressionResult = expression; - for (var i = 0; i < substitutions.length; i++) { + for (let i = 0; i < substitutions.length; i++) { expressionResult = expressionResult.replace(substitutions[i].original, substitutions[i].value); } @@ -160,7 +155,6 @@ function applyExpression(expression, context, typeInformation) { function expressionApplier(context, typeInformation) { return function(attribute) { - /** * Determines if a value is of type float * @@ -171,12 +165,11 @@ function expressionApplier(context, typeInformation) { return !isNaN(value) && value.toString().indexOf('.') !== -1; } - var newAttribute = { + const newAttribute = { name: attribute.name, type: attribute.type }; - /*jshint camelcase: false */ if (config.checkNgsi2() && attribute.object_id) { newAttribute.object_id = attribute.object_id; } @@ -185,14 +178,11 @@ function expressionApplier(context, typeInformation) { if (attribute.type === 'Number' && isFloat(newAttribute.value)) { newAttribute.value = Number.parseFloat(newAttribute.value); - } - else if (attribute.type === 'Number' && Number.parseInt(newAttribute.value)) { + } else if (attribute.type === 'Number' && Number.parseInt(newAttribute.value)) { newAttribute.value = Number.parseInt(newAttribute.value); - } - else if (attribute.type === 'Boolean') { - newAttribute.value = (newAttribute.value === 'true' || newAttribute.value === '1'); - } - else if (attribute.type === 'None') { + } else if (attribute.type === 'Boolean') { + newAttribute.value = newAttribute.value === 'true' || newAttribute.value === '1'; + } else if (attribute.type === 'None') { newAttribute.value = null; } @@ -201,10 +191,10 @@ function expressionApplier(context, typeInformation) { } function contextAvailable(expression, context) { - var variables = expression.match(/@[a-zA-Z0-9]+/g).map(function(item) { - return item.substr(1); - }), - keys = Object.keys(context); + const variables = expression.match(/@[a-zA-Z0-9]+/g).map(function(item) { + return item.substr(1); + }); + const keys = Object.keys(context); return _.difference(variables, keys).length === 0; } diff --git a/lib/plugins/expressionPlugin.js b/lib/plugins/expressionPlugin.js index 8ed729556..193dcd961 100644 --- a/lib/plugins/expressionPlugin.js +++ b/lib/plugins/expressionPlugin.js @@ -1,4 +1,3 @@ - /* * Copyright 2016 Telefonica Investigación y Desarrollo, S.A.U * @@ -24,28 +23,26 @@ * Modified by: Daniel Calvo - ATOS Research & Innovation */ -'use strict'; - -var _ = require('underscore'), - parser = require('./expressionParser'), - config = require('../commonConfig'), - /*jshint unused:false*/ - logger = require('logops'), - /*jshint unused:false*/ - context = { - op: 'IoTAgentNGSI.expressionPlugin' - }, - utils = require('./pluginUtils'); +const _ = require('underscore'); +const parser = require('./expressionParser'); +const config = require('../commonConfig'); +/* eslint-disable-next-line no-unused-vars */ +const logger = require('logops'); +/* eslint-disable-next-line no-unused-vars */ +const context = { + op: 'IoTAgentNGSI.expressionPlugin' +}; +const utils = require('./pluginUtils'); function mergeAttributes(attrList1, attrList2) { - var finalCollection = _.clone(attrList1), - additionalItems = [], - found; + const finalCollection = _.clone(attrList1); + const additionalItems = []; + let found; - for (var i = 0; i < attrList2.length; i++) { + for (let i = 0; i < attrList2.length; i++) { found = false; - for (var j = 0; j < finalCollection.length; j++) { + for (let j = 0; j < finalCollection.length; j++) { if (finalCollection[j].name === attrList2[i].name) { finalCollection[j].value = attrList2[i].value; found = true; @@ -60,11 +57,10 @@ function mergeAttributes(attrList1, attrList2) { return finalCollection.concat(additionalItems); } - function update(entity, typeInformation, callback) { function processEntityUpdateNgsi1(entity) { - var expressionAttributes = [], - ctx = parser.extractContext(entity.attributes); + let expressionAttributes = []; + const ctx = parser.extractContext(entity.attributes); if (typeInformation.active) { expressionAttributes = parser.processExpressionAttributes(typeInformation, typeInformation.active, ctx); @@ -76,8 +72,8 @@ function update(entity, typeInformation, callback) { } function processEntityUpdateNgsi2(attributes) { - var expressionAttributes = [], - ctx = parser.extractContext(attributes); + let expressionAttributes = []; + const ctx = parser.extractContext(attributes); if (typeInformation.active) { expressionAttributes = parser.processExpressionAttributes(typeInformation, typeInformation.active, ctx); @@ -89,7 +85,7 @@ function update(entity, typeInformation, callback) { try { if (config.checkNgsi2()) { - var attsArray = utils.extractAttributesArrayFromNgsi2Entity(entity); + let attsArray = utils.extractAttributesArrayFromNgsi2Entity(entity); attsArray = processEntityUpdateNgsi2(attsArray); entity = utils.createNgsi2Entity(entity.id, entity.type, attsArray, true); } else { diff --git a/lib/plugins/multiEntity.js b/lib/plugins/multiEntity.js index 05c9f1791..a714c33ff 100644 --- a/lib/plugins/multiEntity.js +++ b/lib/plugins/multiEntity.js @@ -23,23 +23,22 @@ * Modified by: Daniel Calvo - ATOS Research & Innovation */ -'use strict'; - -/* jshint camelcase: false */ - -var _ = require('underscore'), - constants = require('../constants'), - parser = require('./expressionParser'), - config = require('../commonConfig'), - /*jshint unused:false*/ - logger = require('logops'), - /*jshint unused:false*/ - context = { - op: 'IoTAgentNGSI.MultiEntityPlugin' - }, - utils = require('./pluginUtils'), - aliasPlugin = require('./attributeAlias'); - +/* eslint-disable no-prototype-builtins */ +/* eslint-disable array-callback-return */ + +const _ = require('underscore'); +const constants = require('../constants'); +const parser = require('./expressionParser'); +const config = require('../commonConfig'); + +/* eslint-disable-next-line no-unused-vars */ +const logger = require('logops'); +/* eslint-disable-next-line no-unused-vars */ +const context = { + op: 'IoTAgentNGSI.MultiEntityPlugin' +}; +const utils = require('./pluginUtils'); +const aliasPlugin = require('./attributeAlias'); function hasEntityName(item) { return item.entity_name; @@ -66,8 +65,8 @@ function filterOutMultientitiesNgsi1(originalAttrs, meAttributes) { * @return {Array} List of all the attrbiutes without multientity flag. */ function filterOutMultientitiesNgsi2(originalAttrs, meAttributes) { - var result = {}; - for (var att in originalAttrs) { + const result = {}; + for (const att in originalAttrs) { if (originalAttrs.hasOwnProperty(att)) { if (!_.contains(meAttributes, att)) { result[att] = originalAttrs[att]; @@ -90,11 +89,10 @@ function filterOutMultientitiesNgsi2(originalAttrs, meAttributes) { * @return {Array} List of the new Context Entities */ function generateNewCEsNgsi1(entity, newEntities, entityTypes, typeInformation, multiEntityAttributes) { - var result = [], - newEntityAttributes, - newEntityAttributeNames, - entityName, - ctx; + const result = []; + let newEntityAttributes; + let newEntityAttributeNames; + let entityName; function filterByEntityName(entityName) { return function(item) { @@ -106,9 +104,9 @@ function generateNewCEsNgsi1(entity, newEntities, entityTypes, typeInformation, return _.contains(newEntityAttributeNames, item.name); } - ctx = parser.extractContext(entity.contextElements[0].attributes); + const ctx = parser.extractContext(entity.contextElements[0].attributes); - for (var i = 0; i < newEntities.length; i++) { + for (let i = 0; i < newEntities.length; i++) { newEntityAttributeNames = _.pluck(multiEntityAttributes.filter(filterByEntityName(newEntities[i])), 'name'); newEntityAttributes = entity.contextElements[0].attributes.filter(filterByAttributeNames); @@ -127,7 +125,6 @@ function generateNewCEsNgsi1(entity, newEntities, entityTypes, typeInformation, return result; } - /** * Generate new Context Elements for each new Entity, with the attributes of the original entity matching its * entity_name. It considers Ngsiv2. @@ -140,49 +137,47 @@ function generateNewCEsNgsi1(entity, newEntities, entityTypes, typeInformation, * @return {Array} List of the new Context Entities */ function generateNewCEsNgsi2(entity, newEntities, entityTypes, typeInformation, multiEntityAttributes) { - - var result = [], - newEntityAttributes, - newEntityAttributeNames, - newEntityAttributeObjectIds, - entityName, - ctx; + const result = []; + let newEntityAttributes; + let newEntityAttributeNames; + let newEntityAttributeObjectIds; + let entityName; function filterByEntityName(entityName) { return function(item) { return item.entity_name === entityName; }; } - + /* eslint-disable-next-line no-unused-vars */ function filterAttributes() { - var result = {}; - var mappings = aliasPlugin.extractAllMappings(typeInformation); - for (var att in entity) { + const result = {}; + const mappings = aliasPlugin.extractAllMappings(typeInformation); + for (const att in entity) { if (entity.hasOwnProperty(att)) { if (_.contains(newEntityAttributeNames, att)) { if (entity[att].multi && entity[att].multi.length > 0) { - // jshint maxdepth:7 if (mappings.inverse[att] && mappings.inverse[att].length > 0) { - for (var j in (mappings.inverse[att])) { + for (const j in mappings.inverse[att]) { if (_.contains(newEntityAttributeObjectIds, mappings.inverse[att][j])) { - result[att] = _.clone(entity[att]); + result[att] = _.clone(entity[att]); delete entity[att].object_id; delete result[att].multi; } } } - // jshint maxdepth:7 - for (var k in entity[att].multi) { - if (entity[att].multi[k].object_id && _.contains(newEntityAttributeObjectIds, - entity[att].multi[k].object_id)) { + + for (const k in entity[att].multi) { + if ( + entity[att].multi[k].object_id && + _.contains(newEntityAttributeObjectIds, entity[att].multi[k].object_id) + ) { result[att] = entity[att].multi[k]; delete entity[att].multi[k].object_id; - } + } } } else { result[att] = entity[att]; } - } } } @@ -191,23 +186,23 @@ function generateNewCEsNgsi2(entity, newEntities, entityTypes, typeInformation, } function filterByAttributeObjectIds() { - var result = {}; - for (var att in entity) { + const result = {}; + for (const att in entity) { if (entity.hasOwnProperty(att)) { if (_.contains(newEntityAttributeNames, att)) { - if (entity[att].object_id && _.contains(newEntityAttributeObjectIds, entity[att].object_id )){ + if (entity[att].object_id && _.contains(newEntityAttributeObjectIds, entity[att].object_id)) { result[att] = entity[att]; delete entity[att].object_id; - } else { + } else if (entity[att].multi) { // Check matches in rest of multientity attributes with same name (#635) - // jshint maxdepth:7 - if (entity[att].multi) { - for (var j in entity[att].multi) { - if (entity[att].multi[j].object_id && - _.contains(newEntityAttributeObjectIds, entity[att].multi[j].object_id)) { - result[att] = entity[att].multi[j]; - delete entity[att].multi[j].object_id; - } + + for (const j in entity[att].multi) { + if ( + entity[att].multi[j].object_id && + _.contains(newEntityAttributeObjectIds, entity[att].multi[j].object_id) + ) { + result[att] = entity[att].multi[j]; + delete entity[att].multi[j].object_id; } } } @@ -217,13 +212,15 @@ function generateNewCEsNgsi2(entity, newEntities, entityTypes, typeInformation, return result; } - var attsArray = utils.extractAttributesArrayFromNgsi2Entity(entity); - ctx = parser.extractContext(attsArray); + const attsArray = utils.extractAttributesArrayFromNgsi2Entity(entity); + const ctx = parser.extractContext(attsArray); - for (var i = 0; i < newEntities.length; i++) { + for (let i = 0; i < newEntities.length; i++) { newEntityAttributeNames = _.pluck(multiEntityAttributes.filter(filterByEntityName(newEntities[i])), 'name'); - newEntityAttributeObjectIds = _.pluck(multiEntityAttributes.filter( - filterByEntityName(newEntities[i])), 'object_id'); + newEntityAttributeObjectIds = _.pluck( + multiEntityAttributes.filter(filterByEntityName(newEntities[i])), + 'object_id' + ); newEntityAttributes = filterByAttributeObjectIds(); entityName = parser.applyExpression(newEntities[i], ctx, typeInformation); @@ -237,9 +234,9 @@ function generateNewCEsNgsi2(entity, newEntities, entityTypes, typeInformation, } function extractTypes(attributeList, defaultType) { - var typeMap = {}; + const typeMap = {}; - for (var i = 0; i < attributeList.length; i++) { + for (let i = 0; i < attributeList.length; i++) { typeMap[attributeList[i].entity_name] = attributeList[i].entity_type || defaultType; } @@ -259,14 +256,14 @@ function extractTypes(attributeList, defaultType) { * */ function propagateTimestamp(entity, entities) { - var ts = entity[constants.TIMESTAMP_ATTRIBUTE]; + const ts = entity[constants.TIMESTAMP_ATTRIBUTE]; if (!ts) { return; } entities.map(function(en) { // Set timestamp metadata in attributes (except TimeInstant attribute itself) - for (var att in en && att !== constants.TIMESTAMP_ATTRIBUTE) { + for (const att in en && att !== constants.TIMESTAMP_ATTRIBUTE) { if (en.hasOwnProperty(att) && att !== 'id' && att !== 'type') { if (!en[att].metadata) { en[att].metadata = {}; @@ -281,16 +278,16 @@ function propagateTimestamp(entity, entities) { function updateAttributeNgsi1(entity, typeInformation, callback) { if (typeInformation.active) { - var multiEntityAttributes = typeInformation.active.filter(hasEntityName), - newEntities = _.pluck(multiEntityAttributes, 'entity_name'), - attributesList = _.pluck(multiEntityAttributes, 'name'), - entityTypes = extractTypes(multiEntityAttributes, entity.contextElements[0].type), - resultAttributes; + const multiEntityAttributes = typeInformation.active.filter(hasEntityName); + const newEntities = _.pluck(multiEntityAttributes, 'entity_name'); + const attributesList = _.pluck(multiEntityAttributes, 'name'); + const entityTypes = extractTypes(multiEntityAttributes, entity.contextElements[0].type); - resultAttributes = filterOutMultientitiesNgsi1(entity.contextElements[0].attributes, attributesList); + const resultAttributes = filterOutMultientitiesNgsi1(entity.contextElements[0].attributes, attributesList); entity.contextElements = entity.contextElements.concat( - generateNewCEsNgsi1(entity, newEntities, entityTypes, typeInformation, multiEntityAttributes)); + generateNewCEsNgsi1(entity, newEntities, entityTypes, typeInformation, multiEntityAttributes) + ); entity.contextElements[0].attributes = resultAttributes; } @@ -299,20 +296,24 @@ function updateAttributeNgsi1(entity, typeInformation, callback) { } function updateAttributeNgsi2(entity, typeInformation, callback) { - var entities = []; + let entities = []; entities.push(entity); if (typeInformation.active) { - - var multiEntityAttributes = typeInformation.active.filter(hasEntityName), - newEntities = _.pluck(multiEntityAttributes, 'entity_name'), - attributesList = _.pluck(multiEntityAttributes, 'name'), - entityTypes = extractTypes(multiEntityAttributes, typeInformation.type), - resultAttributes; + const multiEntityAttributes = typeInformation.active.filter(hasEntityName); + const newEntities = _.pluck(multiEntityAttributes, 'entity_name'); + const attributesList = _.pluck(multiEntityAttributes, 'name'); + const entityTypes = extractTypes(multiEntityAttributes, typeInformation.type); + let resultAttributes; if (multiEntityAttributes.length > 0) { resultAttributes = filterOutMultientitiesNgsi2(entity, attributesList); - var newCes = generateNewCEsNgsi2(entity, newEntities, entityTypes, typeInformation, - multiEntityAttributes); + const newCes = generateNewCEsNgsi2( + entity, + newEntities, + entityTypes, + typeInformation, + multiEntityAttributes + ); entities = entities.concat(newCes); entities[0] = resultAttributes; propagateTimestamp(entity, entities); diff --git a/lib/plugins/pluginUtils.js b/lib/plugins/pluginUtils.js index 7efbac253..51e37c04b 100644 --- a/lib/plugins/pluginUtils.js +++ b/lib/plugins/pluginUtils.js @@ -23,9 +23,9 @@ * Modified by: Daniel Calvo - ATOS Research & Innovation */ -'use strict'; +/* eslint-disable no-prototype-builtins */ -var config = require('../commonConfig'); +const config = require('../commonConfig'); /** * Creates an array of attributes from an entity @@ -33,15 +33,14 @@ var config = require('../commonConfig'); * @return {Object} Array of attributes extracted from the entity */ function extractAttributesArrayFromNgsi2Entity(entity) { - var attsArray = []; - for (var i in entity) { + const attsArray = []; + for (const i in entity) { if (entity.hasOwnProperty(i)) { if (i !== 'id' && i !== 'type') { - var att = Object.assign({}, entity[i]); + const att = Object.assign({}, entity[i]); if (att.multi) { - // jshint maxdepth:5 - for (var j in att.multi) { - var matt = Object.assign({}, entity[i].multi[j]); + for (const j in att.multi) { + const matt = Object.assign({}, entity[i].multi[j]); matt.name = i; attsArray.push(matt); } @@ -66,31 +65,30 @@ function extractAttributesArrayFromNgsi2Entity(entity) { * @return {Object} A NGSIv2 entity */ function createNgsi2Entity(id, type, attsArray, withObjectId) { - var entity = {}; + const entity = {}; entity.id = id; entity.type = type; - for (var i = 0; i < attsArray.length; i++) { - /*jshint camelcase: false */ + for (let i = 0; i < attsArray.length; i++) { if (entity[attsArray[i].name] && withObjectId && attsArray[i].object_id) { // Check if multiple measures with multientity attributes with same name(#635) if (!entity[attsArray[i].name].multi) { entity[attsArray[i].name].multi = []; } entity[attsArray[i].name].multi.push({ - 'type' : attsArray[i].type, - 'value' : attsArray[i].value, - /*jshint camelcase: false */ - 'object_id' : attsArray[i].object_id, - 'metadata' : attsArray[i].metadata + type: attsArray[i].type, + value: attsArray[i].value, + + object_id: attsArray[i].object_id, + metadata: attsArray[i].metadata }); } else { entity[attsArray[i].name] = { - 'type' : attsArray[i].type, - 'value' : attsArray[i].value, - 'metadata' : attsArray[i].metadata + type: attsArray[i].type, + value: attsArray[i].value, + metadata: attsArray[i].metadata }; if (withObjectId && attsArray[i].object_id) { - entity[attsArray[i].name].object_id = attsArray[i].object_id; + entity[attsArray[i].name].object_id = attsArray[i].object_id; } } } @@ -100,7 +98,6 @@ function createNgsi2Entity(id, type, attsArray, withObjectId) { function createProcessAttribute(fn, attributeType) { return function(attribute) { - if (attribute.type && attribute.type === attributeType) { attribute.value = fn(attribute.value); } @@ -109,10 +106,8 @@ function createProcessAttribute(fn, attributeType) { if (attribute.metadata) { attribute.metadata = attribute.metadata.map(createProcessAttribute(fn, attributeType)); } - } else { - if (attribute.metadatas) { - attribute.metadatas = attribute.metadatas.map(createProcessAttribute(fn, attributeType)); - } + } else if (attribute.metadatas) { + attribute.metadatas = attribute.metadatas.map(createProcessAttribute(fn, attributeType)); } return attribute; @@ -131,14 +126,13 @@ function createProcessAttribute(fn, attributeType) { function createUpdateFilter(fn, attributeType) { return function update(entity, typeInformation, callback) { function processEntityUpdateNgsi1(entity) { - entity.attributes = entity.attributes.map( - createProcessAttribute(fn, attributeType)); + entity.attributes = entity.attributes.map(createProcessAttribute(fn, attributeType)); return entity; } function processEntityUpdateNgsi2(entity) { - var attsArray = extractAttributesArrayFromNgsi2Entity(entity); + let attsArray = extractAttributesArrayFromNgsi2Entity(entity); attsArray = attsArray.map(createProcessAttribute(fn, attributeType)); entity = createNgsi2Entity(entity.id, entity.type, attsArray, true); return entity; @@ -166,13 +160,14 @@ function createQueryFilter(fn, attributeType) { return function query(entity, typeInformation, callback) { function processEntityQueryNgsi1(entity) { entity.contextElement.attributes = entity.contextElement.attributes.map( - createProcessAttribute(fn, attributeType)); + createProcessAttribute(fn, attributeType) + ); return entity; } function processEntityQueryNgsi2(entity) { - var attsArray = extractAttributesArrayFromNgsi2Entity(entity); + let attsArray = extractAttributesArrayFromNgsi2Entity(entity); attsArray = attsArray.map(createProcessAttribute(fn, attributeType)); entity = createNgsi2Entity(entity.id, entity.type, attsArray); return entity; diff --git a/lib/plugins/timestampProcessPlugin.js b/lib/plugins/timestampProcessPlugin.js index 7993add7f..362a15988 100644 --- a/lib/plugins/timestampProcessPlugin.js +++ b/lib/plugins/timestampProcessPlugin.js @@ -23,16 +23,16 @@ * Modified by: Daniel Calvo - ATOS Research & Innovation */ -'use strict'; +/* eslint-disable no-prototype-builtins */ -var errors = require('../errors'), - constants = require('../constants'), - logger = require('logops'), - context = { - op: 'IoTAgentNGSI.TimestampProcessPlugin' - }, - config = require('../commonConfig'), - utils = require('./pluginUtils'); +const errors = require('../errors'); +const constants = require('../constants'); +const logger = require('logops'); +const context = { + op: 'IoTAgentNGSI.TimestampProcessPlugin' +}; +const config = require('../commonConfig'); +const utils = require('./pluginUtils'); /** * Looks for Thinking Thing modules and parses them, updating the entity (NGSIv2) with the transformed value. @@ -40,12 +40,11 @@ var errors = require('../errors'), * @param {Object} entity NGSI Entity as it would have been sent before the plugin. */ function updatePluginNgsi2(entity, entityType, callback) { - var timestamp; + let timestamp; function insertMetadata(element) { - if (element.name !== constants.TIMESTAMP_ATTRIBUTE) { - var metadata = {}; + const metadata = {}; metadata[constants.TIMESTAMP_ATTRIBUTE] = { type: constants.TIMESTAMP_TYPE_NGSI2, value: timestamp.value @@ -57,7 +56,7 @@ function updatePluginNgsi2(entity, entityType, callback) { } function updateSingleEntity(entity) { - var attsArray = utils.extractAttributesArrayFromNgsi2Entity(entity); + let attsArray = utils.extractAttributesArrayFromNgsi2Entity(entity); if (entity && entity[constants.TIMESTAMP_ATTRIBUTE]) { if (entity.hasOwnProperty(constants.TIMESTAMP_ATTRIBUTE)) { @@ -77,14 +76,12 @@ function updatePluginNgsi2(entity, entityType, callback) { } if (entity instanceof Array) { - var results = entity.map(updateSingleEntity); + const results = entity.map(updateSingleEntity); callback(null, results, entityType); } else { - var newEntity = updateSingleEntity(entity); + const newEntity = updateSingleEntity(entity); callback(null, newEntity, entityType); } - - } /** @@ -93,22 +90,24 @@ function updatePluginNgsi2(entity, entityType, callback) { * @param {Object} entity NGSI Entity as it would have been sent before the plugin. */ function updatePluginNgsi1(entity, entityType, callback) { - var timestamp; + let timestamp; function insertMetadata(element) { if (element.name !== constants.TIMESTAMP_ATTRIBUTE) { - element.metadatas = [{ - name: constants.TIMESTAMP_ATTRIBUTE, - type: constants.TIMESTAMP_TYPE, - value: timestamp.value - }]; + element.metadatas = [ + { + name: constants.TIMESTAMP_ATTRIBUTE, + type: constants.TIMESTAMP_TYPE, + value: timestamp.value + } + ]; } return element; } if (entity.contextElements && entity.contextElements[0] && entity.contextElements[0].attributes) { - for (var i in entity.contextElements[0].attributes) { + for (const i in entity.contextElements[0].attributes) { if (entity.contextElements[0].attributes[i].name === constants.TIMESTAMP_ATTRIBUTE) { timestamp = entity.contextElements[0].attributes[i]; } @@ -123,7 +122,6 @@ function updatePluginNgsi1(entity, entityType, callback) { logger.error(context, 'Bad payload received while processing timestamps'); callback(new errors.WrongSyntax(entity)); } - } /** diff --git a/lib/services/commands/commandRegistryMemory.js b/lib/services/commands/commandRegistryMemory.js index b6d0d0ea6..fe61ae0fa 100644 --- a/lib/services/commands/commandRegistryMemory.js +++ b/lib/services/commands/commandRegistryMemory.js @@ -20,43 +20,45 @@ * For those usages not covered by the GNU Affero General Public License * please contact with::daniel.moranjimenez@telefonica.com */ -'use strict'; - -var registeredCommands = {}, - async = require('async'), - apply = async.apply, - logger = require('logops'), - intoTrans = require('../common/domain').intoTrans, - errors = require('../../errors'), - _ = require('underscore'), - context = { - op: 'IoTAgentNGSI.InMemoryCommandRegister' - }, - commandIds = 1; + +let registeredCommands = {}; +const async = require('async'); +const apply = async.apply; +const logger = require('logops'); +const intoTrans = require('../common/domain').intoTrans; +const errors = require('../../errors'); +const _ = require('underscore'); +const context = { + op: 'IoTAgentNGSI.InMemoryCommandRegister' +}; +let commandIds = 1; function findCommand(service, subservice, deviceId, name) { - var keys = Object.keys(registeredCommands).filter(function filterByCriteria(item) { - return registeredCommands[item].service === service && - registeredCommands[item].subservice === subservice && - registeredCommands[item].deviceId === deviceId, - registeredCommands[item].name === name; + const keys = Object.keys(registeredCommands).filter(function filterByCriteria(item) { + return ( + registeredCommands[item].service === service && + registeredCommands[item].subservice === subservice && + registeredCommands[item].deviceId === deviceId, + registeredCommands[item].name === name + ); }); if (keys.length === 1) { return registeredCommands[keys[0]]; - } else { - return null; } + return null; } function exists(service, subservice, deviceId, name) { - var keys = _.keys(registeredCommands); + const keys = _.keys(registeredCommands); - for (var i in keys) { - if (registeredCommands[keys[i]].service === service && + for (const i in keys) { + if ( + registeredCommands[keys[i]].service === service && registeredCommands[keys[i]].subservice === subservice && registeredCommands[keys[i]].name === name && - registeredCommands[keys[i]].deviceId === deviceId) { + registeredCommands[keys[i]].deviceId === deviceId + ) { return true; } } @@ -65,7 +67,7 @@ function exists(service, subservice, deviceId, name) { } function updateCommand(service, subservice, deviceId, command, callback) { - var foundCommand = findCommand(service, subservice, deviceId, command.name); + const foundCommand = findCommand(service, subservice, deviceId, command.name); if (foundCommand) { foundCommand.type = command.type; @@ -81,7 +83,7 @@ function addCommand(service, subservice, deviceId, command, callback) { if (exists(service, subservice, deviceId, command.name)) { updateCommand(service, subservice, deviceId, command, callback); } else { - var storeCommand = _.clone(command); + const storeCommand = _.clone(command); storeCommand._id = commandIds++; @@ -91,8 +93,14 @@ function addCommand(service, subservice, deviceId, command, callback) { registeredCommands[storeCommand._id].subservice = subservice; registeredCommands[storeCommand._id].deviceId = deviceId; - logger.debug(context, 'Storing device command [%s] for service [%s], subservice [%s] and deviceId [%s]', - command.name, storeCommand.service, storeCommand.subservice, deviceId); + logger.debug( + context, + 'Storing device command [%s] for service [%s], subservice [%s] and deviceId [%s]', + command.name, + storeCommand.service, + storeCommand.subservice, + deviceId + ); callback(null); } @@ -100,9 +108,11 @@ function addCommand(service, subservice, deviceId, command, callback) { function getFilteredCommands(service, subservice, deviceId) { return Object.keys(registeredCommands).filter(function filterByCriteria(item) { - return registeredCommands[item].service === service && + return ( + registeredCommands[item].service === service && registeredCommands[item].subservice === subservice && - registeredCommands[item].deviceId === deviceId; + registeredCommands[item].deviceId === deviceId + ); }); } @@ -114,10 +124,10 @@ function getFilteredCommands(service, subservice, deviceId) { * @param {Number} deviceId Id of the target device for the commands. */ function listCommands(service, subservice, deviceId, callback) { - var result = [], - filteredCommands = getFilteredCommands(service, subservice, deviceId); + const result = []; + const filteredCommands = getFilteredCommands(service, subservice, deviceId); - for (var i in filteredCommands) { + for (const i in filteredCommands) { result.push(registeredCommands[filteredCommands[i]]); } @@ -128,7 +138,7 @@ function listCommands(service, subservice, deviceId, callback) { } function remove(service, subservice, deviceId, name, callback) { - var foundCommand = findCommand(service, subservice, deviceId, name); + const foundCommand = findCommand(service, subservice, deviceId, name); if (foundCommand) { delete registeredCommands[foundCommand._id]; @@ -151,16 +161,19 @@ function getExpiredCommands(creationDate) { } function removeFromDate(creationDate, callback) { - var expiredCommands = getExpiredCommands(creationDate), - removalOrders = []; - - for (var i in expiredCommands) { - removalOrders.push(apply(remove, - registeredCommands[expiredCommands[i]].service, - registeredCommands[expiredCommands[i]].subservice, - registeredCommands[expiredCommands[i]].deviceId, - registeredCommands[expiredCommands[i]].name - )); + const expiredCommands = getExpiredCommands(creationDate); + const removalOrders = []; + + for (const i in expiredCommands) { + removalOrders.push( + apply( + remove, + registeredCommands[expiredCommands[i]].service, + registeredCommands[expiredCommands[i]].subservice, + registeredCommands[expiredCommands[i]].deviceId, + registeredCommands[expiredCommands[i]].name + ) + ); } async.series(removalOrders, function(error) { diff --git a/lib/services/commands/commandRegistryMongoDB.js b/lib/services/commands/commandRegistryMongoDB.js index b6940bfbc..b8b36dacd 100644 --- a/lib/services/commands/commandRegistryMongoDB.js +++ b/lib/services/commands/commandRegistryMongoDB.js @@ -20,32 +20,30 @@ * For those usages not covered by the GNU Affero General Public License * please contact with::daniel.moranjimenez@telefonica.com */ -'use strict'; - -var logger = require('logops'), - dbService = require('../../model/dbConn'), - intoTrans = require('../common/domain').intoTrans, - errors = require('../../errors'), - Command = require('../../model/Command'), - async = require('async'), - context = { - op: 'IoTAgentNGSI.MongoDBCommandRegister' - }; + +const logger = require('logops'); +const dbService = require('../../model/dbConn'); +const intoTrans = require('../common/domain').intoTrans; +const errors = require('../../errors'); +const Command = require('../../model/Command'); +const async = require('async'); +const context = { + op: 'IoTAgentNGSI.MongoDBCommandRegister' +}; function findCommand(service, subservice, deviceId, name, callback) { - var query, - queryObj = { - service: service, - subservice: subservice, - deviceId: deviceId, - name: name - }; + const queryObj = { + service, + subservice, + deviceId, + name + }; logger.debug(context, 'Looking for command [%s] for device [%s]', name, deviceId); - query = Command.model.findOne(queryObj); + const query = Command.model.findOne(queryObj); - query.select({__v: 0}); + query.select({ __v: 0 }); query.exec(function handleGet(error, data) { if (error) { @@ -77,14 +75,11 @@ function updateCommand(service, subservice, deviceId, command, callback) { } function createCommand(service, subservice, deviceId, command, callback) { - var commandObj = new Command.model(), - attributeList = [ - 'name', - 'type', - 'value' - ]; - - for (var i = 0; i < attributeList.length; i++) { + /* eslint-disable-next-line new-cap */ + const commandObj = new Command.model(); + const attributeList = ['name', 'type', 'value']; + + for (let i = 0; i < attributeList.length; i++) { commandObj[attributeList[i]] = command[attributeList[i]]; } @@ -118,8 +113,7 @@ function addCommand(service, subservice, deviceId, command, callback) { } function listCommands(service, subservice, deviceId, callback) { - var condition = {}, - query; + const condition = {}; function toObjectFn(obj) { return obj.toObject(); @@ -129,12 +123,12 @@ function listCommands(service, subservice, deviceId, callback) { condition.subservice = subservice; condition.deviceId = deviceId; - query = Command.model.find(condition).sort(); + const query = Command.model.find(condition).sort(); - async.series([ - query.exec.bind(query), - Command.model.countDocuments.bind(Command.model, condition) - ], function(error, results) { + async.series([query.exec.bind(query), Command.model.countDocuments.bind(Command.model, condition)], function( + error, + results + ) { callback(error, { count: results[1], commands: results[0].map(toObjectFn) @@ -143,8 +137,14 @@ function listCommands(service, subservice, deviceId, callback) { } function remove(service, subservice, deviceId, name, callback) { - logger.debug(context, 'Removing command for service [%s] subservice [%s] and DeviceID [%s] with name [%s]', - service, subservice, deviceId, name); + logger.debug( + context, + 'Removing command for service [%s] subservice [%s] and DeviceID [%s] with name [%s]', + service, + subservice, + deviceId, + name + ); findCommand(service, subservice, deviceId, name, function(error, command) { if (error) { @@ -170,9 +170,9 @@ function remove(service, subservice, deviceId, name, callback) { } function listToObject(commandList) { - var result = []; + const result = []; - for (var i = 0; i < commandList.length; i++) { + for (let i = 0; i < commandList.length; i++) { result.push(commandList[i].toObject()); } @@ -180,7 +180,7 @@ function listToObject(commandList) { } function removeFromDate(creationDate, callback) { - var query = { creationDate: { $lt: creationDate } }; + const query = { creationDate: { $lt: creationDate } }; if (Command.model) { Command.model.find(query).exec(function(error, commandList) { @@ -191,8 +191,11 @@ function removeFromDate(creationDate, callback) { callback(new errors.InternalDbError(error)); } else { - logger.debug(context, 'Expired commands successfully removed from MongoDB for date [%s]', - creationDate); + logger.debug( + context, + 'Expired commands successfully removed from MongoDB for date [%s]', + creationDate + ); callback(null, listToObject(commandList)); } diff --git a/lib/services/commands/commandService.js b/lib/services/commands/commandService.js index 990079791..cba365065 100644 --- a/lib/services/commands/commandService.js +++ b/lib/services/commands/commandService.js @@ -21,20 +21,18 @@ * please contact with::daniel.moranjimenez@telefonica.com */ -'use strict'; - -var intoTrans = require('../common/domain').intoTrans, - logger = require('logops'), - async = require('async'), - apply = async.apply, - config = require('../../commonConfig'), - constants = require('../../constants'), - ngsiService = require('../ngsi/ngsiService'), - deviceService = require('../devices/deviceService'), - daemonId, - context = { - op: 'IoTAgentNGSI.CommandService' - }; +const intoTrans = require('../common/domain').intoTrans; +const logger = require('logops'); +const async = require('async'); +const apply = async.apply; +const config = require('../../commonConfig'); +const constants = require('../../constants'); +const ngsiService = require('../ngsi/ngsiService'); +const deviceService = require('../devices/deviceService'); +let daemonId; +const context = { + op: 'IoTAgentNGSI.CommandService' +}; function listCommands(service, subservice, deviceId, callback) { logger.debug(context, 'Listing all commands for device [%s]', deviceId); @@ -71,19 +69,14 @@ function markAsExpired(command) { function calculateTypeInformation(device, group, callback) { deviceService.mergeDeviceWithConfiguration( - [ - 'lazy', - 'active', - 'staticAttributes', - 'commands', - 'subscriptions' - ], + ['lazy', 'active', 'staticAttributes', 'commands', 'subscriptions'], [null, null, [], [], [], [], []], device, group, function(error, typeInformation) { callback(error, device, group, typeInformation); - }); + } + ); } function updateExpiredCommand(device, group, typeInformation, callback) { @@ -95,28 +88,32 @@ function markAsExpired(command) { constants.COMMAND_EXPIRED_MESSAGE, constants.COMMAND_STATUS_ERROR, typeInformation, - callback); + callback + ); } - async.waterfall([ - apply(deviceService.getDevice, command.deviceId, command.service, command.subservice), - getGroup, - calculateTypeInformation, - updateExpiredCommand - ], function(error) { - if (error) { - logger.error(context, 'Error updating polling command to expire: %j', error); - } else { - logger.debug(context, 'Command successfully expired'); + async.waterfall( + [ + apply(deviceService.getDevice, command.deviceId, command.service, command.subservice), + getGroup, + calculateTypeInformation, + updateExpiredCommand + ], + function(error) { + if (error) { + logger.error(context, 'Error updating polling command to expire: %j', error); + } else { + logger.debug(context, 'Command successfully expired'); + } } - }); + ); } function expirationDaemon() { if (config.getConfig().pollingExpiration) { - config.getCommandRegistry().removeFromDate( - Date.now() - config.getConfig().pollingExpiration, - function(error, results) { + config + .getCommandRegistry() + .removeFromDate(Date.now() - config.getConfig().pollingExpiration, function(error, results) { logger.debug(context, 'Executed expiration daemon'); if (error) { diff --git a/lib/services/common/alarmManagement.js b/lib/services/common/alarmManagement.js index 622fb3b1d..df20d3fff 100644 --- a/lib/services/common/alarmManagement.js +++ b/lib/services/common/alarmManagement.js @@ -20,13 +20,12 @@ * For those usages not covered by the GNU Affero General Public License * please contact with::[contacto@tid.es] */ -'use strict'; -var alarmRepository = {}, - logger = require('logops'), - context = { - op: 'IoTAgentNGSI.Alarms' - }; +let alarmRepository = {}; +const logger = require('logops'); +const context = { + op: 'IoTAgentNGSI.Alarms' +}; /** * Raises a new alarm with the provided data, if the alarm was not already risen. @@ -38,7 +37,7 @@ function raise(alarmName, description) { if (!alarmRepository[alarmName]) { alarmRepository[alarmName] = { name: alarmName, - description: description + description }; logger.error(context, 'Raising [%s]: %j', alarmName, description); @@ -93,8 +92,9 @@ function clean(callback) { function intercept(alarmName, targetFn) { function interceptCallback(callback) { return function() { - var originalArguments = Array.prototype.slice.call(arguments), - error = originalArguments.slice(0, 1); + /* eslint-disable-next-line prefer-rest-params */ + const originalArguments = Array.prototype.slice.call(arguments); + const error = originalArguments.slice(0, 1); if (error && error.length !== 0 && error[0]) { raise(alarmName, error[0]); @@ -107,8 +107,9 @@ function intercept(alarmName, targetFn) { } return function() { - var originalArguments = Array.prototype.slice.call(arguments), - callback = originalArguments.splice(-1); + /* eslint-disable-next-line prefer-rest-params */ + const originalArguments = Array.prototype.slice.call(arguments); + const callback = originalArguments.splice(-1); originalArguments.push(interceptCallback(callback[0])); diff --git a/lib/services/common/domain.js b/lib/services/common/domain.js index 0da9f04d3..eadc95082 100644 --- a/lib/services/common/domain.js +++ b/lib/services/common/domain.js @@ -21,28 +21,25 @@ * please contact with::[iot_support@tid.es] */ -'use strict'; - -var domain = require('domain'), - constants = require('../../constants'), - uuid = require('uuid'), - logger = require('logops'), - context = { - op: 'IoTAgentNGSI.DomainControl' - }; +const domain = require('domain'); +const constants = require('../../constants'); +const uuid = require('uuid'); +const logger = require('logops'); +const context = { + op: 'IoTAgentNGSI.DomainControl' +}; -var CORRELATOR_HEADER = 'Fiware-Correlator'; +const CORRELATOR_HEADER = 'Fiware-Correlator'; function getDomainTransaction() { if (domain.active && domain.active.trans) { return domain.active.trans; - } else { - return uuid.v4(); } + return uuid.v4(); } function cleanDomain(domainToClean) { - var responseTime = Date.now() - domainToClean.start; + const responseTime = Date.now() - domainToClean.start; logger.debug(context, 'response-time: ' + responseTime); domainToClean.removeAllListeners('error'); delete domainToClean.trans; @@ -64,7 +61,7 @@ function generateDomainErrorHandler(domainToHandle) { * It also generates a unique request id that can be used to track requests in logs. */ function requestDomain(req, res, next) { - var reqDomain = domain.create(); + const reqDomain = domain.create(); reqDomain.path = req.path; reqDomain.op = req.url; reqDomain.start = Date.now(); @@ -81,8 +78,9 @@ function requestDomain(req, res, next) { } function requestHandler() { - var corr = req.get(CORRELATOR_HEADER); + const corr = req.get(CORRELATOR_HEADER); + /* eslint-disable-next-line no-multi-assign */ reqDomain.trans = req.requestId = getDomainTransaction(); if (corr) { reqDomain.corr = corr; @@ -109,7 +107,7 @@ function requestDomain(req, res, next) { * @return {Object} Return value of the callback function, if any. */ function ensureSouthboundTransaction(context, callback) { - var reqDomain; + let reqDomain; if (!callback && typeof context === 'function') { callback = context; @@ -154,7 +152,8 @@ function ensureSouthboundTransaction(context, callback) { */ function intoTransaction(context, fn) { return function() { - var originalArguments = arguments; + /* eslint-disable-next-line prefer-rest-params */ + const originalArguments = arguments; function expandedFunction() { return fn.apply(fn, originalArguments); diff --git a/lib/services/common/genericMiddleware.js b/lib/services/common/genericMiddleware.js index 0b79198a3..3c61d46f1 100644 --- a/lib/services/common/genericMiddleware.js +++ b/lib/services/common/genericMiddleware.js @@ -21,15 +21,13 @@ * please contact with::daniel.moranjimenez@telefonica.com */ -'use strict'; - -var logger = require('logops'), - revalidator = require('revalidator'), - errors = require('../../errors'), - iotaInformation, - context = { - op: 'IoTAgentNGSI.GenericMiddlewares' - }; +const logger = require('logops'); +const revalidator = require('revalidator'); +const errors = require('../../errors'); +let iotaInformation; +const context = { + op: 'IoTAgentNGSI.GenericMiddlewares' +}; /** * Express middleware for handling errors in the IoTAs. It extracts the code information to return from the error itself @@ -37,8 +35,10 @@ var logger = require('logops'), * * @param {Object} error Error object with all the information. */ + +/* eslint-disable-next-line no-unused-vars */ function handleError(error, req, res, next) { - var code = 500; + let code = 500; logger.debug(context, 'Error [%s] handling request: %s', error.name, error.message); @@ -68,8 +68,10 @@ function traceRequest(req, res, next) { /** * Changes the log level to the one specified in the request. */ + +/* eslint-disable-next-line no-unused-vars */ function changeLogLevel(req, res, next) { - var levels = ['INFO', 'ERROR', 'FATAL', 'DEBUG', 'WARNING']; + const levels = ['INFO', 'ERROR', 'FATAL', 'DEBUG', 'WARNING']; if (!req.query.level) { res.status(400).json({ @@ -88,6 +90,8 @@ function changeLogLevel(req, res, next) { /** * Return the current log level. */ + +/* eslint-disable-next-line no-unused-vars */ function getLogLevel(req, res, next) { res.status(200).json({ level: logger.getLevel() @@ -114,7 +118,7 @@ function ensureType(req, res, next) { function validateJson(template) { return function validate(req, res, next) { if (req.is('json')) { - var errorList = revalidator.validate(req.body, template); + const errorList = revalidator.validate(req.body, template); if (errorList.valid) { next(); @@ -131,6 +135,8 @@ function validateJson(template) { /** * Middleware that returns all the IoTA information stored in the module. */ + +/* eslint-disable-next-line no-unused-vars */ function retrieveVersion(req, res, next) { res.status(200).json(iotaInformation); } diff --git a/lib/services/common/iotManagerService.js b/lib/services/common/iotManagerService.js index b14ad95a5..eccc141cf 100644 --- a/lib/services/common/iotManagerService.js +++ b/lib/services/common/iotManagerService.js @@ -23,26 +23,23 @@ * Modified by: Federico M. Facca - Martel Innovate */ -'use strict'; - -var request = require('request'), - async = require('async'), - errors = require('../../errors'), - constants = require('../../constants'), - config = require('../../commonConfig'), - intoTrans = require('../common/domain').intoTrans, - alarms = require('../common/alarmManagement'), - logger = require('logops'), - context = { - op: 'IoTAgentNGSI.IOTAMService' - }; +const request = require('request'); +const async = require('async'); +const errors = require('../../errors'); +const constants = require('../../constants'); +const config = require('../../commonConfig'); +const intoTrans = require('../common/domain').intoTrans; +const alarms = require('../common/alarmManagement'); +const logger = require('logops'); +const context = { + op: 'IoTAgentNGSI.IOTAMService' +}; /** * Sends the registration to the IoT Agent Manager if it is configured in the config file. */ function register(callback) { function adaptServiceInformation(service) { - /* jshint camelcase: false */ return { apikey: service.apikey, token: service.trust, @@ -70,20 +67,20 @@ function register(callback) { } function sendRegistration(services, callback) { - var resource = constants.DEFAULT_RESOURCE; + let resource = constants.DEFAULT_RESOURCE; // Use an Undefined check since defaultResource override could be blank. - if (config.getConfig().defaultResource !== undefined){ + if (config.getConfig().defaultResource !== undefined) { resource = config.getConfig().defaultResource; } - var options = { + const options = { url: config.getConfig().iotManager.url + config.getConfig().iotManager.path, method: 'POST', json: { protocol: config.getConfig().iotManager.protocol, description: config.getConfig().iotManager.description, iotagent: config.getConfig().providerUrl + (config.getConfig().iotManager.agentPath || ''), - resource: resource, - services: services + resource, + services } }; @@ -96,8 +93,11 @@ function register(callback) { if (result.statusCode !== 200 && result.statusCode !== 201) { alarms.raise(constants.IOTAM_ALARM, 'Wrong status code connecting with the IoTAM'); - logger.error(context, 'IOTAM-001: Error updating information in the IOTAM. Status Code [%d]', - result.statusCode); + logger.error( + context, + 'IOTAM-001: Error updating information in the IOTAM. Status Code [%d]', + result.statusCode + ); } else { alarms.release(constants.IOTAM_ALARM); } @@ -106,14 +106,14 @@ function register(callback) { } function checkConfiguration(callback) { - var attributes = ['protocol', 'description'], - missing = []; + const attributes = ['protocol', 'description']; + const missing = []; if (!config.getConfig().providerUrl) { missing.push('providerUrl'); } - for (var i in attributes) { + for (const i in attributes) { if (!config.getConfig().iotManager[attributes[i]]) { missing.push(attributes[i]); } @@ -127,22 +127,20 @@ function register(callback) { } if (config.getConfig().iotManager) { - async.waterfall([ - checkConfiguration, - getServices, - sendRegistration, - handleRegistration - ], function registerHandler(error) { - if (error) { - logger.error(context, 'Error connecting to IoT Manager: %j', error); - - alarms.raise(constants.IOTAM_ALARM, 'Unknown error connecting with the IoTAM'); - - callback(error); - } else { - callback(); + async.waterfall( + [checkConfiguration, getServices, sendRegistration, handleRegistration], + function registerHandler(error) { + if (error) { + logger.error(context, 'Error connecting to IoT Manager: %j', error); + + alarms.raise(constants.IOTAM_ALARM, 'Unknown error connecting with the IoTAM'); + + callback(error); + } else { + callback(); + } } - }); + ); } else { callback(); } diff --git a/lib/services/common/securityServiceKeystone.js b/lib/services/common/securityServiceKeystone.js index c48a2e942..dded788c2 100644 --- a/lib/services/common/securityServiceKeystone.js +++ b/lib/services/common/securityServiceKeystone.js @@ -1,4 +1,3 @@ - /* * Copyright 2014 Telefonica Investigación y Desarrollo, S.A.U * @@ -22,17 +21,14 @@ * please contact with::daniel.moranjimenez@telefonica.com */ -'use strict'; - -var request = require('request'), - errors = require('../../errors'), - config = require('../../commonConfig'), - intoTrans = require('../common/domain').intoTrans, - logger = require('logops'), - context = { - op: 'IoTAgentNGSI.SecurityService' - }; - +const request = require('request'); +const errors = require('../../errors'); +const config = require('../../commonConfig'); +const intoTrans = require('../common/domain').intoTrans; +const logger = require('logops'); +const context = { + op: 'IoTAgentNGSI.SecurityService' +}; /** * Send a request to the Authorization Server to retrieve a token using the given trust. @@ -40,16 +36,13 @@ var request = require('request'), * @param {String} trust Trust generated in Keystone to act on behalf of a user. */ function auth(trust, callback) { - var options = { - url: config.getConfig().authentication.url + - '/v3/auth/tokens', + const options = { + url: config.getConfig().authentication.url + '/v3/auth/tokens', method: 'POST', json: { auth: { identity: { - methods: [ - 'password' - ], + methods: ['password'], password: { user: { domain: { @@ -71,6 +64,7 @@ function auth(trust, callback) { logger.debug(context, 'Authentication with Keystone using trust [%s]', trust); + /* eslint-disable-next-line no-unused-vars */ request(options, function handleResponse(error, response, body) { if (error) { logger.error(context, 'KEYSTONE-001: Error retrieving token from Keystone: %s', error); @@ -83,8 +77,13 @@ function auth(trust, callback) { callback(new errors.AuthenticationError(trust)); } else { logger.error(context, 'KEYSTONE-002: Unexpected status code: %d', response.statusCode); - callback(new errors.TokenRetrievalError( - trust, 'Unexpected status code retrieving token: %d', response.statusCode)); + callback( + new errors.TokenRetrievalError( + trust, + 'Unexpected status code retrieving token: %d', + response.statusCode + ) + ); } }); } @@ -96,7 +95,6 @@ function auth(trust, callback) { */ function getToken(trust, response, callback) { - logger.debug(context, 'Retrieving token from the KEYSTONE response'); if (response.headers['x-subject-token']) { @@ -105,8 +103,7 @@ function getToken(trust, response, callback) { callback(null, response.headers['x-subject-token']); } else { logger.error(context, 'KEYSTONE-003: Token missing in the response headers', response.headers); - callback(new errors.TokenRetrievalError( - trust, 'Unexpected response format', response.headers)); + callback(new errors.TokenRetrievalError(trust, 'Unexpected response format', response.headers)); } } diff --git a/lib/services/common/securityServiceOAuth2.js b/lib/services/common/securityServiceOAuth2.js index 3a3bcafdf..31c548cc9 100644 --- a/lib/services/common/securityServiceOAuth2.js +++ b/lib/services/common/securityServiceOAuth2.js @@ -1,4 +1,3 @@ - /* * Copyright 2014 Telefonica Investigación y Desarrollo, S.A.U * @@ -25,47 +24,45 @@ * Modified by: Daniel Calvo - ATOS Research & Innovation */ -'use strict'; - -var request = require('request'), - queryString = require('query-string'), - errors = require('../../errors'), - config = require('../../commonConfig'), - intoTrans = require('../common/domain').intoTrans, - logger = require('logops'), - context = { - op: 'IoTAgentNGSI.SecurityService' - }; +/* eslint-disable consistent-return */ +const request = require('request'); +const queryString = require('query-string'); +const errors = require('../../errors'); +const config = require('../../commonConfig'); +const intoTrans = require('../common/domain').intoTrans; +const logger = require('logops'); +const context = { + op: 'IoTAgentNGSI.SecurityService' +}; /** * Send a request to the Authorization Server. * * @param {String} trust refresh_token for the OAuth2 provider to act on behalf of a user. */ -/* jshint camelcase: false */ -function auth(trust, callback) { +function auth(trust, callback) { if (config.getConfig().authentication.permanentToken) { return callback(null, trust); } - var form = { - grant_type: 'refresh_token', - client_id: config.getConfig().authentication.clientId, - client_secret: config.getConfig().authentication.clientSecret, - refresh_token: trust + const form = { + grant_type: 'refresh_token', + client_id: config.getConfig().authentication.clientId, + client_secret: config.getConfig().authentication.clientSecret, + refresh_token: trust }; - var formData = queryString.stringify(form); - var url = config.getConfig().authentication.url + config.getConfig().authentication.tokenPath; + const formData = queryString.stringify(form); + const url = config.getConfig().authentication.url + config.getConfig().authentication.tokenPath; - var options = { - url: url, + const options = { + url, method: 'POST', headers: { - 'Content-Length': formData.length, - 'Content-Type': 'application/x-www-form-urlencoded' + 'Content-Length': formData.length, + 'Content-Type': 'application/x-www-form-urlencoded' }, body: formData }; @@ -78,25 +75,35 @@ function auth(trust, callback) { callback(new errors.TokenRetrievalError(trust, error)); } else if (response.statusCode === 201 || response.statusCode === 200 /* Keyrock response */) { logger.debug(context, 'Authentication with trust [%s] was succesful', trust); - logger.debug(context, - 'Received the following response from the OAuth2 provider:\n\n%s\n\n', JSON.stringify(body, null, 4)); + logger.debug( + context, + 'Received the following response from the OAuth2 provider:\n\n%s\n\n', + JSON.stringify(body, null, 4) + ); callback(null, response); - } else if (response.statusCode === 401 || (response.statusCode === 400 && - JSON.parse(response.body).error_description === 'Invalid refresh token')) { + } else if ( + response.statusCode === 401 || + (response.statusCode === 400 && JSON.parse(response.body).error_description === 'Invalid refresh token') + ) { logger.error(context, 'Authentication rejected: %s', trust); callback(new errors.AuthenticationError(trust)); - } else if (response.statusCode === 400 && - JSON.parse(response.body).error === 'invalid_client') { //Keyrock response + } else if (response.statusCode === 400 && JSON.parse(response.body).error === 'invalid_client') { + //Keyrock response logger.error(context, 'Authentication rejected: %s', trust); callback(new errors.AuthenticationError(trust)); - } else if (response.statusCode === 400 && - JSON.parse(response.body).error === 'invalid_grant') { //Keyrock response + } else if (response.statusCode === 400 && JSON.parse(response.body).error === 'invalid_grant') { + //Keyrock response logger.error(context, 'Authentication rejected: %s', trust); callback(new errors.AuthenticationError(trust)); } else { logger.error(context, 'OAUTH2-002: Unexpected status code: %d', response.statusCode); - callback(new errors.TokenRetrievalError( - trust, 'Unexpected status code retrieving token: %d', response.statusCode)); + callback( + new errors.TokenRetrievalError( + trust, + 'Unexpected status code retrieving token: %d', + response.statusCode + ) + ); } }); } @@ -106,16 +113,15 @@ function auth(trust, callback) { * @param {String} trust refresh_token for the OAuth2 provider to act on behalf of a user. * @param {String} response The authentication response */ -/* jshint camelcase: false */ -function getToken(trust, response, callback) { +function getToken(trust, response, callback) { logger.debug(context, 'Retrieving token from the OAuth2 response'); if (config.getConfig().authentication.permanentToken) { return callback(null, 'Bearer ' + trust); } - var body = JSON.parse(response.body); + const body = JSON.parse(response.body); if (body.access_token) { logger.debug(context, 'Token found [%s] for trust [%s]', body.access_token, trust); @@ -123,8 +129,7 @@ function getToken(trust, response, callback) { callback(null, 'Bearer ' + body.access_token); } else { logger.error(context, 'OAUTH2-003: Token missing in the response body', body); - callback(new errors.TokenRetrievalError( - trust, 'Unexpected response format', body)); + callback(new errors.TokenRetrievalError(trust, 'Unexpected response format', body)); } } diff --git a/lib/services/devices/deviceRegistryMemory.js b/lib/services/devices/deviceRegistryMemory.js index 85052eb28..a4b38684a 100644 --- a/lib/services/devices/deviceRegistryMemory.js +++ b/lib/services/devices/deviceRegistryMemory.js @@ -21,18 +21,20 @@ * please contact with::daniel.moranjimenez@telefonica.com */ -var registeredDevices = {}, - logger = require('logops'), - errors = require('../../errors'), - _ = require('underscore'), - context = { - op: 'IoTAgentNGSI.InMemoryDeviceRegister' - }; +/* eslint-disable no-prototype-builtins */ + +let registeredDevices = {}; +const logger = require('logops'); +const errors = require('../../errors'); +const _ = require('underscore'); +const context = { + op: 'IoTAgentNGSI.InMemoryDeviceRegister' +}; function deepClone(device) { - var initialClone = _.clone(device); + const initialClone = _.clone(device); - for (var i in device) { + for (const i in device) { if (device.hasOwnProperty(i) && Array.isArray(device[i])) { initialClone[i] = device[i].map(_.clone); } @@ -70,9 +72,9 @@ function storeDevice(newDevice, callback) { * @param {String} subservice Subservice inside the service for the removed device. */ function removeDevice(id, service, subservice, callback) { - var services = Object.keys(registeredDevices); + const services = Object.keys(registeredDevices); - for (var i = 0; i < services.length; i++) { + for (let i = 0; i < services.length; i++) { if (registeredDevices[services[i]][id]) { logger.debug(context, 'Removing device with id [%s] from service [%s].', id, services[i]); delete registeredDevices[services[i]][id]; @@ -94,13 +96,11 @@ function getDevicesByService(service, subservice) { return Object.keys(registeredDevices[service]).filter(function filterByService(item) { if (subservice) { return registeredDevices[service][item].subservice === subservice; - } else { - return true; } + return true; }); - } else { - return []; } + return []; } /** @@ -112,16 +112,16 @@ function getDevicesByService(service, subservice) { * @param {Number} offset Number of entries to skip for pagination. */ function listDevices(type, service, subservice, limit, offset, callback) { - var result = [], - skipped = 0, - deviceList = getDevicesByService(service, subservice); - - var countNumber = deviceList.length; - for (var i in deviceList) { + const result = []; + let skipped = 0; + const deviceList = getDevicesByService(service, subservice); + + let countNumber = deviceList.length; + for (const i in deviceList) { if (registeredDevices[service].hasOwnProperty(deviceList[i])) { if (offset && skipped < parseInt(offset, 10)) { skipped++; - } else if (type && registeredDevices[service][deviceList[i]].type === type){ + } else if (type && registeredDevices[service][deviceList[i]].type === type) { result.push(registeredDevices[service][deviceList[i]]); } else if (type) { countNumber--; @@ -150,10 +150,10 @@ function getDevice(id, service, subservice, callback) { } function getByName(name, service, subservice, callback) { - var devices = _.values(registeredDevices[service]), - device; + const devices = _.values(registeredDevices[service]); + let device; - for (var i = 0; i < devices.length; i++) { + for (let i = 0; i < devices.length; i++) { if (devices[i].name === name) { device = devices[i]; } @@ -178,8 +178,8 @@ function clear(callback) { } function getDevicesByAttribute(name, value, service, subservice, callback) { - var devices, - resultDevices = []; + let devices; + const resultDevices = []; if (service) { devices = _.values(registeredDevices[service]); @@ -187,7 +187,7 @@ function getDevicesByAttribute(name, value, service, subservice, callback) { devices = _.flatten(_.values(registeredDevices).map(_.values)); } - for (var i = 0; i < devices.length; i++) { + for (let i = 0; i < devices.length; i++) { if (devices[i][name] === value) { resultDevices.push(devices[i]); } diff --git a/lib/services/devices/deviceRegistryMongoDB.js b/lib/services/devices/deviceRegistryMongoDB.js index 4e70b074b..188ff7c2d 100644 --- a/lib/services/devices/deviceRegistryMongoDB.js +++ b/lib/services/devices/deviceRegistryMongoDB.js @@ -21,18 +21,18 @@ * please contact with::daniel.moranjimenez@telefonica.com */ -var logger = require('logops'), - dbService = require('../../model/dbConn'), - config = require('../../commonConfig'), - fillService = require('./../common/domain').fillService, - alarmsInt = require('../common/alarmManagement').intercept, - errors = require('../../errors'), - constants = require('../../constants'), - Device = require('../../model/Device'), - async = require('async'), - context = { - op: 'IoTAgentNGSI.MongoDBDeviceRegister' - }; +const logger = require('logops'); +const dbService = require('../../model/dbConn'); +const config = require('../../commonConfig'); +const fillService = require('./../common/domain').fillService; +const alarmsInt = require('../common/alarmManagement').intercept; +const errors = require('../../errors'); +const constants = require('../../constants'); +const Device = require('../../model/Device'); +const async = require('async'); +const context = { + op: 'IoTAgentNGSI.MongoDBDeviceRegister' +}; /** * Generates a handler for the save device operations. The handler will take the customary error and the saved device @@ -58,17 +58,37 @@ function saveDeviceHandler(callback) { * @param {Object} newDevice Device object to be stored */ function storeDevice(newDevice, callback) { - var deviceObj = new Device.model(), - attributeList = ['id', 'type', 'name', 'service', 'subservice', 'lazy', 'commands', 'staticAttributes', - 'active', 'registrationId', 'internalId', 'internalAttributes', 'resource', 'apikey', 'protocol', - 'endpoint', 'transport', 'polling', 'timestamp', 'autoprovision']; - - for (var i = 0; i < attributeList.length; i++) { + /* eslint-disable-next-line new-cap */ + const deviceObj = new Device.model(); + const attributeList = [ + 'id', + 'type', + 'name', + 'service', + 'subservice', + 'lazy', + 'commands', + 'staticAttributes', + 'active', + 'registrationId', + 'internalId', + 'internalAttributes', + 'resource', + 'apikey', + 'protocol', + 'endpoint', + 'transport', + 'polling', + 'timestamp', + 'autoprovision' + ]; + + for (let i = 0; i < attributeList.length; i++) { deviceObj[attributeList[i]] = newDevice[attributeList[i]]; } // Ensure protocol is in newDevice - if ( !newDevice.protocol && config.getConfig().iotManager && config.getConfig().iotManager.protocol) { + if (!newDevice.protocol && config.getConfig().iotManager && config.getConfig().iotManager.protocol) { deviceObj.protocol = config.getConfig().iotManager.protocol; } @@ -99,10 +119,10 @@ function storeDevice(newDevice, callback) { * @param {String} subservice Subservice inside the service for the removed device. */ function removeDevice(id, service, subservice, callback) { - var condition = { - id: id, - service: service, - subservice: subservice + const condition = { + id, + service, + subservice }; logger.debug(context, 'Removing device with id [%s]', id); @@ -130,8 +150,7 @@ function removeDevice(id, service, subservice, callback) { * @param {Number} offset Number of entries to skip for pagination. */ function listDevices(type, service, subservice, limit, offset, callback) { - var condition = {}, - query; + const condition = {}; if (type) { condition.type = type; @@ -145,7 +164,7 @@ function listDevices(type, service, subservice, limit, offset, callback) { condition.subservice = subservice; } - query = Device.model.find(condition).sort(); + const query = Device.model.find(condition).sort(); if (limit) { query.limit(parseInt(limit, 10)); @@ -155,10 +174,10 @@ function listDevices(type, service, subservice, limit, offset, callback) { query.skip(parseInt(offset, 10)); } - async.series([ - query.exec.bind(query), - Device.model.countDocuments.bind(Device.model, condition) - ], function(error, results) { + async.series([query.exec.bind(query), Device.model.countDocuments.bind(Device.model, condition)], function( + error, + results + ) { callback(error, { count: results[1], devices: results[0] @@ -174,17 +193,16 @@ function listDevices(type, service, subservice, limit, offset, callback) { * @param {String} subservice Division inside the service (optional). */ function getDeviceById(id, service, subservice, callback) { - var query, - queryParams = { - id: id, - service: service, - subservice: subservice - }; + const queryParams = { + id, + service, + subservice + }; logger.debug(context, 'Looking for device with id [%s].', id); - query = Device.model.findOne(queryParams); - query.select({__v: 0}); + const query = Device.model.findOne(queryParams); + query.select({ __v: 0 }); query.exec(function handleGet(error, data) { if (error) { @@ -209,7 +227,6 @@ function getDeviceById(id, service, subservice, callback) { * @param {String} subservice Division inside the service. */ function getDevice(id, service, subservice, callback) { - getDeviceById(id, service, subservice, function(error, data) { if (error) { callback(error); @@ -220,17 +237,15 @@ function getDevice(id, service, subservice, callback) { } function getByName(name, service, servicepath, callback) { - var query; - logger.debug(context, 'Looking for device with name [%s].', name); - query = Device.model.findOne({ - name: name, - service: service, + const query = Device.model.findOne({ + name, + service, subservice: servicepath }); - query.select({__v: 0}); + query.select({ __v: 0 }); query.exec(function handleGet(error, data) { if (error) { @@ -282,14 +297,12 @@ function clear(callback) { function itemToObject(i) { if (i.toObject) { return i.toObject(); - } else { - return i; } + return i; } function getDevicesByAttribute(name, value, service, subservice, callback) { - var query, - filter = {}; + const filter = {}; if (service) { filter.service = service; @@ -303,8 +316,8 @@ function getDevicesByAttribute(name, value, service, subservice, callback) { logger.debug(context, 'Looking for device with filter [%j].', filter); - query = Device.model.find(filter); - query.select({__v: 0}); + const query = Device.model.find(filter); + query.select({ __v: 0 }); query.exec(function handleGet(error, devices) { if (error) { diff --git a/lib/services/devices/deviceService.js b/lib/services/devices/deviceService.js index ea92e9276..aedbae1b6 100644 --- a/lib/services/devices/deviceService.js +++ b/lib/services/devices/deviceService.js @@ -24,30 +24,35 @@ * Modified by: Daniel Calvo - ATOS Research & Innovation */ -'use strict'; - -var request = require('request'), - async = require('async'), - apply = async.apply, - uuid = require('uuid'), - constants = require('../../constants'), - domain = require('domain'), - intoTrans = require('../common/domain').intoTrans, - alarms = require('../common/alarmManagement'), - groupService = require('../groups/groupService'), - ngsiService = require('../ngsi/ngsiService'), - errors = require('../../errors'), - logger = require('logops'), - config = require('../../commonConfig'), - ngsiParser = require('./../ngsi/ngsiParser'), - registrationUtils = require('./registrationUtils'), - subscriptions = require('../ngsi/subscriptionService'), - _ = require('underscore'), - utils = require('../northBound/restUtils'), - moment = require('moment'), - context = { - op: 'IoTAgentNGSI.DeviceService' - }; +/* eslint-disable no-prototype-builtins */ +/* eslint-disable prefer-spread */ +/* eslint-disable prefer-rest-params */ +/* eslint-disable consistent-return */ + +const request = require('request'); +const async = require('async'); +const apply = async.apply; +const uuid = require('uuid'); +const constants = require('../../constants'); +const domain = require('domain'); +const intoTrans = require('../common/domain').intoTrans; +const alarms = require('../common/alarmManagement'); +const groupService = require('../groups/groupService'); +const ngsiService = require('../ngsi/ngsiService'); +const errors = require('../../errors'); +const logger = require('logops'); +const config = require('../../commonConfig'); +const ngsiParser = require('./../ngsi/ngsiParser'); +const registrationUtils = require('./registrationUtils'); +const subscriptions = require('../ngsi/subscriptionService'); +const _ = require('underscore'); + +const utils = require('../northBound/restUtils'); +const moment = require('moment'); + +const context = { + op: 'IoTAgentNGSI.DeviceService' +}; /** * Process the response from a Register Context request for a device, extracting the 'registrationId' and creating the @@ -57,7 +62,7 @@ var request = require('request'), * */ function processContextRegistration(deviceData, body, callback) { - var newDevice = _.clone(deviceData); + const newDevice = _.clone(deviceData); if (body) { newDevice.registrationId = body.registrationId; @@ -78,14 +83,17 @@ function processContextRegistration(deviceData, body, callback) { function createInitialEntityHandlerNgsi1(deviceData, newDevice, callback) { return function handleInitialEntityResponse(error, response, body) { if (error) { - logger.error(context, - 'ORION-001: Connection error creating inital entity in the Context Broker: %s', error); + logger.error( + context, + 'ORION-001: Connection error creating inital entity in the Context Broker: %s', + error + ); alarms.raise(constants.ORION_ALARM, error); callback(error); } else if (response && body && response.statusCode === 200) { - var errorField = ngsiParser.getErrorField(body); + const errorField = ngsiParser.getErrorField(body); if (errorField) { logger.error(context, 'Update error connecting to the Context Broker: %j', errorField); @@ -96,12 +104,14 @@ function createInitialEntityHandlerNgsi1(deviceData, newDevice, callback) { callback(null, newDevice); } } else { - var errorObj; - - logger.error(context, - 'Protocol error connecting to the Context Broker [%d]: %s', response.statusCode, body); + logger.error( + context, + 'Protocol error connecting to the Context Broker [%d]: %s', + response.statusCode, + body + ); - errorObj = new errors.EntityGenericError(deviceData.id, deviceData.type, body); + const errorObj = new errors.EntityGenericError(deviceData.id, deviceData.type, body); callback(errorObj); } @@ -120,8 +130,11 @@ function createInitialEntityHandlerNgsi1(deviceData, newDevice, callback) { function createInitialEntityHandlerNgsi2(deviceData, newDevice, callback) { return function handleInitialEntityResponse(error, response, body) { if (error) { - logger.error(context, - 'ORION-001: Connection error creating inital entity in the Context Broker: %s', error); + logger.error( + context, + 'ORION-001: Connection error creating inital entity in the Context Broker: %s', + error + ); alarms.raise(constants.ORION_ALARM, error); @@ -131,12 +144,14 @@ function createInitialEntityHandlerNgsi2(deviceData, newDevice, callback) { logger.debug(context, 'Initial entity created successfully.'); callback(null, newDevice); } else { - var errorObj; - - logger.error(context, - 'Protocol error connecting to the Context Broker [%d]: %s', response.statusCode, body); + logger.error( + context, + 'Protocol error connecting to the Context Broker [%d]: %s', + response.statusCode, + body + ); - errorObj = new errors.EntityGenericError(deviceData.id, deviceData.type, body); + const errorObj = new errors.EntityGenericError(deviceData.id, deviceData.type, body); callback(errorObj); } @@ -154,8 +169,11 @@ function createInitialEntityHandlerNgsi2(deviceData, newDevice, callback) { function updateEntityHandlerNgsi2(deviceData, updatedDevice, callback) { return function handleEntityResponse(error, response, body) { if (error) { - logger.error(context, - 'ORION-001: Connection error creating inital entity in the Context Broker: %s', error); + logger.error( + context, + 'ORION-001: Connection error creating inital entity in the Context Broker: %s', + error + ); alarms.raise(constants.ORION_ALARM, error); @@ -165,12 +183,14 @@ function updateEntityHandlerNgsi2(deviceData, updatedDevice, callback) { logger.debug(context, 'Entity updated successfully.'); callback(null, updatedDevice); } else { - var errorObj; + logger.error( + context, + 'Protocol error connecting to the Context Broker [%d]: %s', + response.statusCode, + body + ); - logger.error(context, - 'Protocol error connecting to the Context Broker [%d]: %s', response.statusCode, body); - - errorObj = new errors.EntityGenericError(deviceData.id, deviceData.type, body); + const errorObj = new errors.EntityGenericError(deviceData.id, deviceData.type, body); callback(errorObj); } @@ -195,7 +215,7 @@ function getInitialValueForType(type) { * @param {Object} json2 JSON object to be merged. */ function jsonConcat(json1, json2) { - for (var key in json2) { + for (const key in json2) { if (json2.hasOwnProperty(key)) { json1[key] = json2[key]; } @@ -210,14 +230,13 @@ function jsonConcat(json1, json2) { * @return {Object} List of device's attributes formatted in NGSIv2. */ function formatAttributesNgsi2(originalVector, staticAtts) { - var attributeList = {}; + const attributeList = {}; if (originalVector && originalVector.length) { - for (var i = 0; i < originalVector.length; i++) { - + for (let i = 0; i < originalVector.length; i++) { // (#628) check if attribute has entity_name: // In that case attribute should not be appear in current entity - /*jshint camelcase: false */ + if (!originalVector[i].entity_name) { attributeList[originalVector[i].name] = { type: originalVector[i].type, @@ -230,7 +249,6 @@ function formatAttributesNgsi2(originalVector, staticAtts) { attributeList[originalVector[i].name].value = getInitialValueForType(originalVector[i].type); } } - } } @@ -244,10 +262,10 @@ function formatAttributesNgsi2(originalVector, staticAtts) { * @return {Object} List of device's commands formatted in NGSIv2. */ function formatCommandsNgsi2(originalVector) { - var attributeList = {}; + const attributeList = {}; if (originalVector && originalVector.length) { - for (var i = 0; i < originalVector.length; i++) { + for (let i = 0; i < originalVector.length; i++) { attributeList[originalVector[i].name + constants.COMMAND_STATUS_SUFIX] = { type: constants.COMMAND_STATUS, value: 'UNKNOWN' @@ -269,42 +287,44 @@ function formatCommandsNgsi2(originalVector) { * @param {String} deviceData Device data. */ function executeWithSecurity(requestOptions, deviceData, callback) { - logger.debug(context, 'executeWithSecurity'); - config.getGroupRegistry().getType(deviceData.type, function(error, deviceGroup) { - var typeInformation; - if (error) { - logger.debug(context, 'error %j in get group device', error); - } + logger.debug(context, 'executeWithSecurity'); + config.getGroupRegistry().getType(deviceData.type, function(error, deviceGroup) { + let typeInformation; + if (error) { + logger.debug(context, 'error %j in get group device', error); + } - if (deviceGroup) { - typeInformation = deviceGroup; - } else { - typeInformation = config.getConfig().types[deviceData.type]; - } + if (deviceGroup) { + typeInformation = deviceGroup; + } else { + typeInformation = config.getConfig().types[deviceData.type]; + } - if (config.getConfig().authentication && config.getConfig().authentication.enabled) { - var security = config.getSecurityService(); - if (typeInformation && typeInformation.trust) { - async.waterfall([ + if (config.getConfig().authentication && config.getConfig().authentication.enabled) { + const security = config.getSecurityService(); + if (typeInformation && typeInformation.trust) { + async.waterfall( + [ apply(security.auth, typeInformation.trust), apply(ngsiService.updateTrust, deviceGroup, null, typeInformation.trust), apply(security.getToken, typeInformation.trust) - ], function(error, token) { + ], + function(error, token) { if (error) { callback(new errors.SecurityInformationMissing(typeInformation.type)); - } - else { + } else { requestOptions.headers[config.getConfig().authentication.header] = token; request(requestOptions, callback); } - }); - } else { - callback(new errors.SecurityInformationMissing(typeInformation.type)); - } + } + ); } else { - request(requestOptions, callback); + callback(new errors.SecurityInformationMissing(typeInformation.type)); } - }); + } else { + request(requestOptions, callback); + } + }); } /** @@ -315,7 +335,7 @@ function executeWithSecurity(requestOptions, deviceData, callback) { * @param {Object} newDevice Device object that will be stored in the database. */ function createInitialEntityNgsi2(deviceData, newDevice, callback) { - var options = { + const options = { url: config.getConfig().contextBroker.url + '/v2/entities?options=upsert', method: 'POST', json: { @@ -340,10 +360,14 @@ function createInitialEntityNgsi2(deviceData, newDevice, callback) { jsonConcat(options.json, formatCommandsNgsi2(deviceData.commands)); logger.debug(context, 'deviceData: %j', deviceData); - if ( (('timestamp' in deviceData && deviceData.timestamp !== undefined) ? - deviceData.timestamp : config.getConfig().timestamp) && - ! utils.isTimestampedNgsi2(options.json)) { - logger.debug(context, 'config.timestamp %s %s', deviceData.timestamp, config.getConfig().timestamp); + + if ( + ('timestamp' in deviceData && deviceData.timestamp !== undefined + ? deviceData.timestamp + : config.getConfig().timestamp) && + !utils.isTimestampedNgsi2(options.json) + ) { + logger.debug(context, 'config.timestamp %s %s', deviceData.timestamp, config.getConfig().timestamp); options.json[constants.TIMESTAMP_ATTRIBUTE] = { type: constants.TIMESTAMP_TYPE_NGSI2, value: moment() @@ -363,41 +387,41 @@ function createInitialEntityNgsi2(deviceData, newDevice, callback) { * @param {Object} newDevice Device object that will be stored in the database. */ function createInitialEntityNgsi1(deviceData, newDevice, callback) { - var cbHost = config.getConfig().contextBroker.url; + let cbHost = config.getConfig().contextBroker.url; if (deviceData.cbHost && deviceData.cbHost.indexOf('://') !== -1) { cbHost = deviceData.cbHost; } else if (deviceData.cbHost && deviceData.cbHost.indexOf('://') === -1) { cbHost = 'http://' + deviceData.cbHost; } - var options = { - url: cbHost + '/v1/updateContext', - method: 'POST', - json: { - contextElements: [ - { - type: deviceData.type, - isPattern: 'false', - id: String(deviceData.name), - attributes: [] - } - ], - updateAction: 'APPEND' - }, - headers: { - 'fiware-service': deviceData.service, - 'fiware-servicepath': deviceData.subservice, - 'fiware-correlator': (domain.active && domain.active.corr) || uuid.v4() - } - }; + const options = { + url: cbHost + '/v1/updateContext', + method: 'POST', + json: { + contextElements: [ + { + type: deviceData.type, + isPattern: 'false', + id: String(deviceData.name), + attributes: [] + } + ], + updateAction: 'APPEND' + }, + headers: { + 'fiware-service': deviceData.service, + 'fiware-servicepath': deviceData.subservice, + 'fiware-correlator': (domain.active && domain.active.corr) || uuid.v4() + } + }; function formatAttributes(originalVector) { - var attributeList = []; + const attributeList = []; if (originalVector && originalVector.length) { - for (var i = 0; i < originalVector.length; i++) { + for (let i = 0; i < originalVector.length; i++) { // (#628) check if attribute has entity_name: // In that case attribute should not be appear in current entity - /*jshint camelcase: false */ + if (!originalVector[i].entity_name) { attributeList.push({ name: originalVector[i].name, @@ -412,10 +436,10 @@ function createInitialEntityNgsi1(deviceData, newDevice, callback) { } function formatCommands(originalVector) { - var attributeList = []; + const attributeList = []; if (originalVector && originalVector.length) { - for (var i = 0; i < originalVector.length; i++) { + for (let i = 0; i < originalVector.length; i++) { attributeList.push({ name: originalVector[i].name + constants.COMMAND_STATUS_SUFIX, type: constants.COMMAND_STATUS, @@ -435,11 +459,15 @@ function createInitialEntityNgsi1(deviceData, newDevice, callback) { options.json.contextElements[0].attributes = [].concat( formatAttributes(deviceData.active), deviceData.staticAttributes, - formatCommands(deviceData.commands)); - - if ( (('timestamp' in deviceData && deviceData.timestamp !== undefined) ? - deviceData.timestamp : config.getConfig().timestamp) && - ! utils.isTimestamped(options.json)) { + formatCommands(deviceData.commands) + ); + + if ( + ('timestamp' in deviceData && deviceData.timestamp !== undefined + ? deviceData.timestamp + : config.getConfig().timestamp) && + !utils.isTimestamped(options.json) + ) { options.json.contextElements[0].attributes.push({ name: constants.TIMESTAMP_ATTRIBUTE, type: constants.TIMESTAMP_TYPE, @@ -473,11 +501,10 @@ function createInitialEntity(deviceData, newDevice, callback) { * @param {Object} updatedDevice Device object that will be stored in the database. */ function updateEntityNgsi2(deviceData, updatedDevice, callback) { - var options = { + const options = { url: config.getConfig().contextBroker.url + '/v2/entities/' + String(deviceData.name) + '/attrs', method: 'POST', - json: { - }, + json: {}, headers: { 'fiware-service': deviceData.service, 'fiware-servicepath': deviceData.subservice, @@ -492,16 +519,19 @@ function updateEntityNgsi2(deviceData, updatedDevice, callback) { } if (deviceData.type) { - options.url += '?type=' + deviceData.type; + options.url += '?type=' + deviceData.type; } jsonConcat(options.json, formatAttributesNgsi2(deviceData.active, false)); jsonConcat(options.json, formatAttributesNgsi2(deviceData.staticAttributes, true)); jsonConcat(options.json, formatCommandsNgsi2(deviceData.commands)); - if ( (('timestamp' in deviceData && deviceData.timestamp !== undefined) ? - deviceData.timestamp : config.getConfig().timestamp) && - ! utils.isTimestampedNgsi2(options.json)) { + if ( + ('timestamp' in deviceData && deviceData.timestamp !== undefined + ? deviceData.timestamp + : config.getConfig().timestamp) && + !utils.isTimestampedNgsi2(options.json) + ) { options.json[constants.TIMESTAMP_ATTRIBUTE] = { type: constants.TIMESTAMP_TYPE_NGSI2, value: moment() @@ -512,8 +542,7 @@ function updateEntityNgsi2(deviceData, updatedDevice, callback) { if (Object.keys(options.json).length === 0 && options.json.constructor === Object) { logger.debug(context, 'Skip updating entity in the Context Broker (no actual attribute change)'); callback(null, updatedDevice); - } - else{ + } else { logger.debug(context, 'Updating entity in the Context Broker:\n %s', JSON.stringify(options, null, 4)); request(options, updateEntityHandlerNgsi2(deviceData, updatedDevice, callback)); } @@ -526,8 +555,6 @@ function updateEntityNgsi2(deviceData, updatedDevice, callback) { * @return {*} Completed attribute */ function setDefaultAttributeIds(attribute) { - /* jshint camelcase: false */ - if (!attribute.object_id && attribute.name) { attribute.object_id = attribute.name; } @@ -550,19 +577,18 @@ function setDefaultAttributeIds(attribute) { * @return {Array} Merge of the attributes of the device and those of the configuration. */ function mergeArrays(original, newArray) { - /* jshint camelcase: false */ - var originalKeys = _.pluck(original, 'object_id'), - newKeys = _.pluck(newArray, 'object_id'), - addedKeys = _.difference(newKeys, originalKeys), - differenceArray = newArray.filter(function(item) { - return item.object_id && addedKeys.indexOf(item.object_id) >= 0; - }), - originalNames = _.pluck(original, 'name'), - newNames = _.pluck(newArray, 'name'), - addedNames = _.difference(newNames, originalNames), - differenceNamesArray = newArray.filter(function(item) { - return addedNames.indexOf(item.name) >= 0 && (!item.object_id || newKeys.indexOf(item.object_id) < 0); - }); + const originalKeys = _.pluck(original, 'object_id'); + const newKeys = _.pluck(newArray, 'object_id'); + const addedKeys = _.difference(newKeys, originalKeys); + const differenceArray = newArray.filter(function(item) { + return item.object_id && addedKeys.indexOf(item.object_id) >= 0; + }); + const originalNames = _.pluck(original, 'name'); + const newNames = _.pluck(newArray, 'name'); + const addedNames = _.difference(newNames, originalNames); + const differenceNamesArray = newArray.filter(function(item) { + return addedNames.indexOf(item.name) >= 0 && (!item.object_id || newKeys.indexOf(item.object_id) < 0); + }); return original.concat(differenceArray).concat(differenceNamesArray); } @@ -577,8 +603,8 @@ function mergeArrays(original, newArray) { */ function mergeDeviceWithConfiguration(fields, defaults, deviceData, configuration, callback) { logger.debug(context, 'deviceData after merge with conf: %j', deviceData); - for (var i = 0; i < fields.length; i++) { - var confField = (fields[i] === 'active') ? 'attributes' : fields[i]; + for (let i = 0; i < fields.length; i++) { + const confField = fields[i] === 'active' ? 'attributes' : fields[i]; if (deviceData && deviceData[fields[i]] && ['active', 'lazy', 'commands'].indexOf(fields[i]) >= 0) { deviceData[fields[i]] = deviceData[fields[i]].map(setDefaultAttributeIds); @@ -598,8 +624,12 @@ function mergeDeviceWithConfiguration(fields, defaults, deviceData, configuratio if (deviceData[fields[i]] && configuration && configuration[confField]) { deviceData[fields[i]] = mergeArrays(deviceData[fields[i]], configuration[confField]); - } else if (!deviceData[fields[i]] && configuration && - confField in configuration && configuration[confField] !== undefined) { + } else if ( + !deviceData[fields[i]] && + configuration && + confField in configuration && + configuration[confField] !== undefined + ) { deviceData[fields[i]] = configuration[confField]; } else if (!deviceData[fields[i]] && (!configuration || !configuration[confField])) { deviceData[fields[i]] = defaults[i]; @@ -621,7 +651,7 @@ function mergeDeviceWithConfiguration(fields, defaults, deviceData, configuratio */ function findConfigurationGroup(deviceObj, callback) { function handlerGroupFind(error, group) { - var effectiveGroup = group; + let effectiveGroup = group; if (!group && config.getConfig().types[deviceObj.type]) { effectiveGroup = config.getConfig().types[deviceObj.type]; @@ -633,17 +663,11 @@ function findConfigurationGroup(deviceObj, callback) { } if (config.getConfig().singleConfigurationMode === true) { - config.getGroupRegistry().find( - deviceObj.service, - deviceObj.subservice, - handlerGroupFind); + config.getGroupRegistry().find(deviceObj.service, deviceObj.subservice, handlerGroupFind); } else { - config.getGroupRegistry().findType( - deviceObj.service, - deviceObj.subservice, - deviceObj.type, - deviceObj.apikey, - handlerGroupFind); + config + .getGroupRegistry() + .findType(deviceObj.service, deviceObj.subservice, deviceObj.type, deviceObj.apikey, handlerGroupFind); } } @@ -661,6 +685,7 @@ function findConfigurationGroup(deviceObj, callback) { */ function registerDevice(deviceObj, callback) { function checkDuplicates(deviceObj, innerCb) { + /* eslint-disable-next-line no-unused-vars */ config.getRegistry().get(deviceObj.id, deviceObj.service, deviceObj.subservice, function(error, device) { if (!error) { innerCb(new errors.DuplicateDeviceId(deviceObj.id)); @@ -671,8 +696,8 @@ function registerDevice(deviceObj, callback) { } function prepareDeviceData(deviceObj, configuration, callback) { - var deviceData = _.clone(deviceObj), - selectedConfiguration; + const deviceData = _.clone(deviceObj); + let selectedConfiguration; if (!deviceData.type) { if (configuration && configuration.type) { @@ -703,45 +728,46 @@ function registerDevice(deviceObj, callback) { logger.debug(context, 'Registering device into NGSI Service:\n%s', JSON.stringify(deviceData, null, 4)); - async.waterfall([ - apply(registrationUtils.sendRegistrations, false, deviceData), - apply(processContextRegistration, deviceData), - apply(createInitialEntity, deviceData) - ], function(error, results) { - if (error) { - callback(error); - } else { - deviceObj.registrationId = results.registrationId; - deviceObj.name = deviceData.name; - deviceObj.service = deviceData.service; - deviceObj.subservice = deviceData.subservice; - deviceObj.type = deviceData.type; - if ('timestamp' in deviceData && deviceData.timestamp !== undefined) { - deviceObj.timestamp = deviceData.timestamp; - } - if ('autoprovision' in deviceData && deviceData.autoprovision !== undefined) { - deviceObj.autoprovision = deviceData.autoprovision; + async.waterfall( + [ + apply(registrationUtils.sendRegistrations, false, deviceData), + apply(processContextRegistration, deviceData), + apply(createInitialEntity, deviceData) + ], + function(error, results) { + if (error) { + callback(error); + } else { + deviceObj.registrationId = results.registrationId; + deviceObj.name = deviceData.name; + deviceObj.service = deviceData.service; + deviceObj.subservice = deviceData.subservice; + deviceObj.type = deviceData.type; + if ('timestamp' in deviceData && deviceData.timestamp !== undefined) { + deviceObj.timestamp = deviceData.timestamp; + } + if ('autoprovision' in deviceData && deviceData.autoprovision !== undefined) { + deviceObj.autoprovision = deviceData.autoprovision; + } + config.getRegistry().store(deviceObj, callback); } - config.getRegistry().store(deviceObj, callback); } - }); + ); } - async.waterfall([ - apply(checkDuplicates, deviceObj), - apply(findConfigurationGroup, deviceObj), - apply(prepareDeviceData, deviceObj), - apply(mergeDeviceWithConfiguration, - [ - 'lazy', - 'active', - 'staticAttributes', - 'commands', - 'subscriptions' - ], - [null, null, [], [], [], [], []] - ) - ], completeRegistrations); + async.waterfall( + [ + apply(checkDuplicates, deviceObj), + apply(findConfigurationGroup, deviceObj), + apply(prepareDeviceData, deviceObj), + apply( + mergeDeviceWithConfiguration, + ['lazy', 'active', 'staticAttributes', 'commands', 'subscriptions'], + [null, null, [], [], [], [], []] + ) + ], + completeRegistrations + ); } function removeAllSubscriptions(device, callback) { @@ -776,34 +802,35 @@ function unregisterDevice(id, service, subservice, callback) { config.getRegistry().get(id, service, subservice, function(error, device) { if (error) { - callback(error); + callback(error); } else { - async.waterfall([ - apply(findConfigurationGroup, device), - apply(mergeDeviceWithConfiguration, - [ - 'lazy', - 'active', - 'staticAttributes', - 'commands', - 'subscriptions' - ], - [null, null, [], [], [], [], []], - device - ) - ], function(error, mergedDevice) { - if (error) { - callback(error); - } else { - async.waterfall([ - apply(removeAllSubscriptions, mergedDevice), - processUnsubscribes, - apply(registrationUtils.sendRegistrations, true, mergedDevice), - processContextUnregister, - apply(config.getRegistry().remove, id, service, subservice) - ], callback); + async.waterfall( + [ + apply(findConfigurationGroup, device), + apply( + mergeDeviceWithConfiguration, + ['lazy', 'active', 'staticAttributes', 'commands', 'subscriptions'], + [null, null, [], [], [], [], []], + device + ) + ], + function(error, mergedDevice) { + if (error) { + callback(error); + } else { + async.waterfall( + [ + apply(removeAllSubscriptions, mergedDevice), + processUnsubscribes, + apply(registrationUtils.sendRegistrations, true, mergedDevice), + processContextUnregister, + apply(config.getRegistry().remove, id, service, subservice) + ], + callback + ); + } } - }); + ); } }); } @@ -853,10 +880,10 @@ function updateRegisterDeviceNgsi1(deviceObj, callback) { } function getAttributeDifference(oldArray, newArray) { - var oldActiveKeys, - newActiveKeys, - updateKeys, - result; + let oldActiveKeys; + let newActiveKeys; + let updateKeys; + let result; if (oldArray && newArray) { newActiveKeys = _.pluck(newArray, 'name'); @@ -877,13 +904,13 @@ function updateRegisterDeviceNgsi1(deviceObj, callback) { } function extractDeviceDifference(newDevice, oldDevice, callback) { - var deviceData = { - id: oldDevice.id, - name: oldDevice.name, - type: oldDevice.type, - service: oldDevice.service, - subservice: oldDevice.subservice - }; + const deviceData = { + id: oldDevice.id, + name: oldDevice.name, + type: oldDevice.type, + service: oldDevice.service, + subservice: oldDevice.subservice + }; deviceData.active = getAttributeDifference(oldDevice.active, newDevice.active); deviceData.lazy = getAttributeDifference(oldDevice.lazy, newDevice.lazy); @@ -893,15 +920,18 @@ function updateRegisterDeviceNgsi1(deviceObj, callback) { callback(null, deviceData, oldDevice); } - async.waterfall([ - apply(config.getRegistry().get, deviceObj.id, deviceObj.service, deviceObj.subservice), - apply(extractDeviceDifference, deviceObj), - createInitialEntity, - apply(combineWithNewDevice, deviceObj), - apply(registrationUtils.sendRegistrations, false), - apply(processContextRegistration, deviceObj), - config.getRegistry().update - ], callback); + async.waterfall( + [ + apply(config.getRegistry().get, deviceObj.id, deviceObj.service, deviceObj.subservice), + apply(extractDeviceDifference, deviceObj), + createInitialEntity, + apply(combineWithNewDevice, deviceObj), + apply(registrationUtils.sendRegistrations, false), + apply(processContextRegistration, deviceObj), + config.getRegistry().update + ], + callback + ); } /** @@ -949,10 +979,10 @@ function updateRegisterDeviceNgsi2(deviceObj, callback) { } function getAttributeDifference(oldArray, newArray) { - var oldActiveKeys, - newActiveKeys, - updateKeys, - result; + let oldActiveKeys; + let newActiveKeys; + let updateKeys; + let result; if (oldArray && newArray) { newActiveKeys = _.pluck(newArray, 'name'); @@ -973,13 +1003,13 @@ function updateRegisterDeviceNgsi2(deviceObj, callback) { } function extractDeviceDifference(newDevice, oldDevice, callback) { - var deviceData = { - id: oldDevice.id, - name: oldDevice.name, - type: oldDevice.type, - service: oldDevice.service, - subservice: oldDevice.subservice - }; + const deviceData = { + id: oldDevice.id, + name: oldDevice.name, + type: oldDevice.type, + service: oldDevice.service, + subservice: oldDevice.subservice + }; deviceData.active = getAttributeDifference(oldDevice.active, newDevice.active); deviceData.lazy = getAttributeDifference(oldDevice.lazy, newDevice.lazy); @@ -989,18 +1019,20 @@ function updateRegisterDeviceNgsi2(deviceObj, callback) { callback(null, deviceData, oldDevice); } - async.waterfall([ - apply(config.getRegistry().get, deviceObj.id, deviceObj.service, deviceObj.subservice), - apply(extractDeviceDifference, deviceObj), - updateEntityNgsi2, - apply(combineWithNewDevice, deviceObj), - apply(registrationUtils.sendRegistrations, false), - apply(processContextRegistration, deviceObj), - config.getRegistry().update - ], callback); + async.waterfall( + [ + apply(config.getRegistry().get, deviceObj.id, deviceObj.service, deviceObj.subservice), + apply(extractDeviceDifference, deviceObj), + updateEntityNgsi2, + apply(combineWithNewDevice, deviceObj), + apply(registrationUtils.sendRegistrations, false), + apply(processContextRegistration, deviceObj), + config.getRegistry().update + ], + callback + ); } - function updateRegisterDevice(deviceObj, callback) { if (config.checkNgsi2()) { updateRegisterDeviceNgsi2(deviceObj, callback); @@ -1029,7 +1061,7 @@ function listDevicesWithType(type, service, subservice, limit, offset, callback) service = null; subservice = null; } else { - logger.fatal(context, 'GENERAL-001: Couldn\'t find callback in listDevices() call.'); + logger.fatal(context, "GENERAL-001: Couldn't find callback in listDevices() call."); } } @@ -1055,7 +1087,7 @@ function listDevices(service, subservice, limit, offset, callback) { service = null; subservice = null; } else { - logger.fatal(context, 'GENERAL-001: Couldn\'t find callback in listDevices() call.'); + logger.fatal(context, "GENERAL-001: Couldn't find callback in listDevices() call."); } } @@ -1111,12 +1143,12 @@ function getDevicesByAttribute(attributeName, attributeValue, service, subservic */ function checkRegistry(fn) { return function() { - var args = Array.prototype.slice.call(arguments), - callbacks = args.slice(-1); + const args = Array.prototype.slice.call(arguments); + const callbacks = args.slice(-1); if (config.getRegistry()) { fn.apply(null, args); - } else if (callbacks && callbacks.length === 1 && (typeof callbacks[0] === 'function')) { + } else if (callbacks && callbacks.length === 1 && typeof callbacks[0] === 'function') { logger.error(context, 'Tried to access device information before a registry was available'); callbacks[0](new errors.RegistryNotAvailable()); } else { @@ -1125,13 +1157,12 @@ function checkRegistry(fn) { }; } - function findOrCreate(deviceId, group, callback) { getDevice(deviceId, group.service, group.subservice, function(error, device) { if (!error && device) { callback(null, device, group); } else if (error.name === 'DEVICE_NOT_FOUND') { - var newDevice = { + const newDevice = { id: deviceId, service: group.service, subservice: group.subservice, @@ -1173,27 +1204,24 @@ function retrieveDevice(deviceId, apiKey, callback) { } else if (devices && devices.length === 1) { callback(null, devices[0]); } else { - logger.error(context, 'Couldn\'t find device data for APIKey [%s] and DeviceId[%s]', - deviceId, apiKey); + logger.error(context, "Couldn't find device data for APIKey [%s] and DeviceId[%s]", deviceId, apiKey); callback(new errors.DeviceNotFound(deviceId)); } }); } else { - async.waterfall([ - apply(groupService.get, config.getConfig().defaultResource || '', apiKey), - apply(findOrCreate, deviceId), - apply(mergeDeviceWithConfiguration, - [ - 'lazy', - 'active', - 'staticAttributes', - 'commands', - 'subscriptions' - ], - [null, null, [], [], [], [], []] - ) - ], callback); + async.waterfall( + [ + apply(groupService.get, config.getConfig().defaultResource || '', apiKey), + apply(findOrCreate, deviceId), + apply( + mergeDeviceWithConfiguration, + ['lazy', 'active', 'staticAttributes', 'commands', 'subscriptions'], + [null, null, [], [], [], [], []] + ) + ], + callback + ); } } diff --git a/lib/services/devices/registrationUtils.js b/lib/services/devices/registrationUtils.js index 14bfed6d0..d0884326f 100644 --- a/lib/services/devices/registrationUtils.js +++ b/lib/services/devices/registrationUtils.js @@ -24,19 +24,17 @@ * Modified by: Daniel Calvo - ATOS Research & Innovation */ -'use strict'; - -var errors = require('../../errors'), - logger = require('logops'), - _ = require('underscore'), - intoTrans = require('../common/domain').intoTrans, - config = require('../../commonConfig'), - ngsiParser = require('./../ngsi/ngsiParser'), - context = { - op: 'IoTAgentNGSI.DeviceService' - }, - async = require('async'), - deviceService = require('./deviceService'); +const errors = require('../../errors'); +const logger = require('logops'); +const _ = require('underscore'); +const intoTrans = require('../common/domain').intoTrans; +const config = require('../../commonConfig'); +const ngsiParser = require('./../ngsi/ngsiParser'); +const context = { + op: 'IoTAgentNGSI.DeviceService' +}; +const async = require('async'); +const deviceService = require('./deviceService'); /** * Generates a handler for the registration requests that checks all the possible errors derived from the registration. @@ -52,7 +50,7 @@ function createRegistrationHandler(unregister, deviceData, callback) { logger.error(context, 'ORION-002: Connection error sending registrations to the Context Broker: %s', error); callback(error); } else if (response && body && response.statusCode === 200) { - var errorField = ngsiParser.getErrorField(body); + const errorField = ngsiParser.getErrorField(body); if (errorField) { logger.error(context, 'Registration error connecting to the Context Broker: %j', errorField); @@ -62,7 +60,7 @@ function createRegistrationHandler(unregister, deviceData, callback) { callback(null, body); } } else { - var errorObj; + let errorObj; logger.error(context, 'ORION-003: Protocol error connecting to the Context Broker: %j', errorObj); @@ -86,24 +84,24 @@ function createRegistrationHandler(unregister, deviceData, callback) { * @return {Function} The generated handler. */ function createRegistrationHandlerNgsi2(unregister, deviceData, callback) { + /* eslint-disable-next-line no-unused-vars */ return function handleRegistrationResponse(error, response, body) { if (error) { logger.error(context, 'ORION-002: Connection error sending registrations to the Context Broker: %s', error); callback(error); } else if (response && response.statusCode === 201 && response.headers.location && unregister === false) { logger.debug(context, 'Registration success.'); - callback(null, {registrationId: - response.headers.location.substr(response.headers.location.lastIndexOf('/') + 1)}); + callback(null, { + registrationId: response.headers.location.substr(response.headers.location.lastIndexOf('/') + 1) + }); } else if (response && response.statusCode === 204 && unregister === true) { logger.debug(context, 'Unregistration success.'); callback(null, null); - } - else if (response && response.statusCode && response.statusCode !== 500) { + } else if (response && response.statusCode && response.statusCode !== 500) { logger.error(context, 'Registration error connecting to the Context Broker: %j', response.statusCode); callback(new errors.BadRequest(JSON.stringify(response.statusCode))); - } - else { - var errorObj; + } else { + let errorObj; logger.error(context, 'ORION-003: Protocol error connecting to the Context Broker: %j', errorObj); @@ -129,14 +127,14 @@ function createRegistrationHandlerNgsi2(unregister, deviceData, callback) { * @param {Object} deviceData Object containing all the deviceData needed to send the registration. */ function sendRegistrationsNgsi1(unregister, deviceData, callback) { - var cbHost = config.getConfig().contextBroker.url; + let cbHost = config.getConfig().contextBroker.url; if (deviceData.cbHost && deviceData.cbHost.indexOf('://') !== -1) { cbHost = deviceData.cbHost; } else if (deviceData.cbHost && deviceData.cbHost.indexOf('://') === -1) { cbHost = 'http://' + deviceData.cbHost; } - var options = { + const options = { url: cbHost + '/NGSI9/registerContext', method: 'POST', json: { @@ -153,7 +151,7 @@ function sendRegistrationsNgsi1(unregister, deviceData, callback) { providingApplication: config.getConfig().providerUrl } ], - duration: (unregister) ? 'PT1S' : config.getConfig().deviceRegistrationDuration + duration: unregister ? 'PT1S' : config.getConfig().deviceRegistrationDuration }, headers: { 'fiware-service': deviceData.service, @@ -162,10 +160,10 @@ function sendRegistrationsNgsi1(unregister, deviceData, callback) { }; function formatAttributes(originalVector) { - var attributeList = []; + const attributeList = []; if (originalVector && originalVector.length) { - for (var i = 0; i < originalVector.length; i++) { + for (let i = 0; i < originalVector.length; i++) { attributeList.push({ name: originalVector[i].name, type: originalVector[i].type @@ -177,7 +175,7 @@ function sendRegistrationsNgsi1(unregister, deviceData, callback) { } function mergeWithSameName(old, current) { - var keys = _.pluck(old, 'name'); + const keys = _.pluck(old, 'name'); if (keys.indexOf(current.name) < 0) { old.push(current); @@ -190,10 +188,9 @@ function sendRegistrationsNgsi1(unregister, deviceData, callback) { options.json.registrationId = deviceData.registrationId; } - options.json.contextRegistrations[0].attributes = options.json.contextRegistrations[0].attributes.concat( - formatAttributes(deviceData.lazy), - formatAttributes(deviceData.commands) - ).reduce(mergeWithSameName, []); + options.json.contextRegistrations[0].attributes = options.json.contextRegistrations[0].attributes + .concat(formatAttributes(deviceData.lazy), formatAttributes(deviceData.commands)) + .reduce(mergeWithSameName, []); if (options.json.contextRegistrations[0].attributes.length === 0) { logger.debug(context, 'No Context Provider registrations found for unregister'); @@ -205,7 +202,8 @@ function sendRegistrationsNgsi1(unregister, deviceData, callback) { deviceService.executeWithSecurity( options, deviceData, - createRegistrationHandler(unregister, deviceData, callback)); + createRegistrationHandler(unregister, deviceData, callback) + ); } } @@ -215,13 +213,13 @@ function sendRegistrationsNgsi1(unregister, deviceData, callback) { * @param {Object} deviceData Object containing all the deviceData needed to send the registration. */ function sendUnregistrationsNgsi2(deviceData, callback) { - var cbHost = config.getConfig().contextBroker.url; + let cbHost = config.getConfig().contextBroker.url; if (deviceData.cbHost && deviceData.cbHost.indexOf('://') !== -1) { cbHost = deviceData.cbHost; } else if (deviceData.cbHost && deviceData.cbHost.indexOf('://') === -1) { cbHost = 'http://' + deviceData.cbHost; } - var options = { + const options = { url: cbHost + '/v2/registrations/' + deviceData.registrationId, method: 'DELETE', json: true, @@ -242,13 +240,12 @@ function sendUnregistrationsNgsi2(deviceData, callback) { deviceService.executeWithSecurity( options, deviceData, - createRegistrationHandlerNgsi2(true, deviceData, callback)); + createRegistrationHandlerNgsi2(true, deviceData, callback) + ); } else { logger.debug(context, 'No Context Provider registrations found for unregister'); callback(null, deviceData); } - - } /** @@ -258,25 +255,24 @@ function sendUnregistrationsNgsi2(deviceData, callback) { * @param {Object} deviceData Object containing all the deviceData needed to send the registration. */ function sendRegistrationsNgsi2(unregister, deviceData, callback) { - var cbHost = config.getConfig().contextBroker.url; + let cbHost = config.getConfig().contextBroker.url; if (deviceData.cbHost && deviceData.cbHost.indexOf('://') !== -1) { cbHost = deviceData.cbHost; } else if (deviceData.cbHost && deviceData.cbHost.indexOf('://') === -1) { cbHost = 'http://' + deviceData.cbHost; } - var options = { + const options = { url: cbHost + '/v2/registrations', method: 'POST', json: { dataProvided: { - entities: - [ + entities: [ { type: deviceData.type, id: String(deviceData.name) } ], - attrs: [], + attrs: [] }, provider: { http: { @@ -291,10 +287,10 @@ function sendRegistrationsNgsi2(unregister, deviceData, callback) { }; function formatAttributes(originalVector) { - var attributeList = []; + const attributeList = []; if (originalVector && originalVector.length) { - for (var i = 0; i < originalVector.length; i++) { + for (let i = 0; i < originalVector.length; i++) { attributeList.push(originalVector[i].name); } } @@ -302,7 +298,6 @@ function sendRegistrationsNgsi2(unregister, deviceData, callback) { return attributeList; } - function mergeWithSameName(old, current) { if (old.indexOf(current) < 0) { old.push(current); @@ -315,7 +310,7 @@ function sendRegistrationsNgsi2(unregister, deviceData, callback) { // this function should use the new API. This is just a temporary solution which implies deleting the // registration and creating a new one. function updateRegistrationNgsi2(deviceData, callback) { - var functions = []; + const functions = []; function removeRegistrationId(deviceData, unregistrationResult, callback) { delete deviceData.registrationId; @@ -330,34 +325,31 @@ function sendRegistrationsNgsi2(unregister, deviceData, callback) { if (unregister) { sendUnregistrationsNgsi2(deviceData, callback); + } else if (deviceData.registrationId) { + updateRegistrationNgsi2(deviceData, callback); } else { - - if (deviceData.registrationId) { - updateRegistrationNgsi2(deviceData, callback); + options.json.dataProvided.attrs = options.json.dataProvided.attrs + .concat(formatAttributes(deviceData.lazy), formatAttributes(deviceData.commands)) + .reduce(mergeWithSameName, []); + + if (options.json.dataProvided.attrs.length === 0) { + logger.debug( + context, + 'Registration with Context Provider is not needed. Device without lazy atts or commands' + ); + callback(null, deviceData); } else { - options.json.dataProvided.attrs = options.json.dataProvided.attrs.concat( - formatAttributes(deviceData.lazy), - formatAttributes(deviceData.commands) - ).reduce(mergeWithSameName, []); - - if (options.json.dataProvided.attrs.length === 0) { - logger.debug(context, 'Registration with Context Provider is not needed.' + - 'Device without lazy atts or commands'); - callback(null, deviceData); - } else { - logger.debug(context, 'Sending device registrations to Context Broker at [%s]', options.url); - logger.debug(context, 'Using the following request:\n\n%s\n\n', JSON.stringify(options, null, 4)); - deviceService.executeWithSecurity( - options, - deviceData, - createRegistrationHandlerNgsi2(unregister, deviceData, callback)); - } + logger.debug(context, 'Sending device registrations to Context Broker at [%s]', options.url); + logger.debug(context, 'Using the following request:\n\n%s\n\n', JSON.stringify(options, null, 4)); + deviceService.executeWithSecurity( + options, + deviceData, + createRegistrationHandlerNgsi2(unregister, deviceData, callback) + ); } } } - - /** * Sends a Context Provider registration or unregistration request to the Context Broker. As registrations cannot be * removed, an unregistration consists of an update of the existent registration to make reduce its duration to diff --git a/lib/services/groups/groupRegistryMemory.js b/lib/services/groups/groupRegistryMemory.js index b71f7987c..99428c2db 100644 --- a/lib/services/groups/groupRegistryMemory.js +++ b/lib/services/groups/groupRegistryMemory.js @@ -20,24 +20,27 @@ * For those usages not covered by the GNU Affero General Public License * please contact with::daniel.moranjimenez@telefonica.com */ -'use strict'; - -var registeredGroups = {}, - logger = require('logops'), - intoTrans = require('../common/domain').intoTrans, - errors = require('../../errors'), - _ = require('underscore'), - context = { - op: 'IoTAgentNGSI.InMemoryGroupRegister' - }, - groupIds = 1; + +/* eslint-disable no-prototype-builtins */ + +let registeredGroups = {}; +const logger = require('logops'); +const intoTrans = require('../common/domain').intoTrans; +const errors = require('../../errors'); +const _ = require('underscore'); +const context = { + op: 'IoTAgentNGSI.InMemoryGroupRegister' +}; +let groupIds = 1; function exists(group) { - var keys = _.keys(registeredGroups); + const keys = _.keys(registeredGroups); - for (var i in keys) { - if (registeredGroups[keys[i]].apikey === group.apikey && - registeredGroups[keys[i]].resource === group.resource) { + for (const i in keys) { + if ( + registeredGroups[keys[i]].apikey === group.apikey && + registeredGroups[keys[i]].resource === group.resource + ) { return true; } } @@ -49,15 +52,20 @@ function createGroup(group, callback) { if (exists(group)) { callback(new errors.DuplicateGroup(group.resource, group.apikey)); } else { - var storeGroup = _.clone(group); + const storeGroup = _.clone(group); storeGroup._id = groupIds++; registeredGroups[storeGroup._id] = storeGroup; registeredGroups[storeGroup._id].creationDate = Date.now(); - logger.debug(context, 'Storing device group for service [%s] and subservice [%s]', - storeGroup._id, storeGroup.service, storeGroup.subservice); + logger.debug( + context, + 'Storing device group for service [%s] and subservice [%s]', + storeGroup._id, + storeGroup.service, + storeGroup.subservice + ); callback(null); } @@ -73,9 +81,8 @@ function getConfigurationsByService(service) { return Object.keys(registeredGroups).filter(function filterByService(item) { if (service) { return registeredGroups[item].service === service; - } else { - return true; } + return true; }); } @@ -89,11 +96,11 @@ function getConfigurationsByService(service) { * @param {Number} offset Number of entries to skip for pagination. */ function listGroups(service, limit, offset, callback) { - var result = [], - skipped = 0, - filteredGroups = getConfigurationsByService(service); + const result = []; + let skipped = 0; + const filteredGroups = getConfigurationsByService(service); - for (var i in filteredGroups) { + for (const i in filteredGroups) { if (registeredGroups.hasOwnProperty(filteredGroups[i])) { if (offset && skipped < parseInt(offset, 10)) { skipped++; @@ -124,12 +131,14 @@ function clear(callback) { } function find(service, subservice, callback) { - var result; + let result; - for (var i in registeredGroups) { - if (registeredGroups.hasOwnProperty(i) && + for (const i in registeredGroups) { + if ( + registeredGroups.hasOwnProperty(i) && registeredGroups[i].service === service && - registeredGroups[i].subservice === subservice) { + registeredGroups[i].subservice === subservice + ) { result = registeredGroups[i]; break; } @@ -144,27 +153,28 @@ function find(service, subservice, callback) { function findBy(fields) { return function() { - var result, - queryObj = {}, - i = 0, - callback; + let result; + const queryObj = {}; + let i = 0; + /* eslint-disable-next-line prefer-rest-params */ while (typeof arguments[i] !== 'function') { + /* eslint-disable-next-line prefer-rest-params */ queryObj[fields[i]] = arguments[i]; i++; } - callback = arguments[i]; + /* eslint-disable-next-line prefer-rest-params */ + const callback = arguments[i]; logger.debug(context, 'Looking for device params %j', fields); - for (var p in registeredGroups) { + for (const p in registeredGroups) { if (registeredGroups.hasOwnProperty(p)) { - var found = 0; + let found = 0; - for (var j in queryObj) { - if (queryObj.hasOwnProperty(j) && - registeredGroups[p][j] === queryObj[j]) { + for (const j in queryObj) { + if (queryObj.hasOwnProperty(j) && registeredGroups[p][j] === queryObj[j]) { found++; } } @@ -185,12 +195,14 @@ function findBy(fields) { } function getSingleGroup(resource, apikey, callback) { - var result; + let result; - for (var i in registeredGroups) { - if (registeredGroups.hasOwnProperty(i) && + for (const i in registeredGroups) { + if ( + registeredGroups.hasOwnProperty(i) && registeredGroups[i].resource === resource && - registeredGroups[i].apikey === apikey) { + registeredGroups[i].apikey === apikey + ) { result = registeredGroups[i]; break; } @@ -204,11 +216,10 @@ function getSingleGroup(resource, apikey, callback) { } function getSingleGroupType(type, callback) { - var result; + let result; - for (var i in registeredGroups) { - if (registeredGroups.hasOwnProperty(i) && - registeredGroups[i].type === type) { + for (const i in registeredGroups) { + if (registeredGroups.hasOwnProperty(i) && registeredGroups[i].type === type) { result = registeredGroups[i]; break; } @@ -221,13 +232,11 @@ function getSingleGroupType(type, callback) { } } - - function update(id, body, callback) { - var groupToModify = registeredGroups[id]; + const groupToModify = registeredGroups[id]; if (groupToModify) { - for (var i in body) { + for (const i in body) { if (body.hasOwnProperty(i)) { groupToModify[i] = body[i]; } @@ -240,7 +249,7 @@ function update(id, body, callback) { } function remove(id, callback) { - var removedObject = registeredGroups[id]; + const removedObject = registeredGroups[id]; delete registeredGroups[id]; callback(null, removedObject); diff --git a/lib/services/groups/groupRegistryMongoDB.js b/lib/services/groups/groupRegistryMongoDB.js index 56b5be92e..49e4d16a3 100644 --- a/lib/services/groups/groupRegistryMongoDB.js +++ b/lib/services/groups/groupRegistryMongoDB.js @@ -22,20 +22,19 @@ * * Modified by: Daniel Calvo - ATOS Research & Innovation */ -'use strict'; - -var logger = require('logops'), - dbService = require('../../model/dbConn'), - intoTrans = require('../common/domain').intoTrans, - fillService = require('./../common/domain').fillService, - alarmsInt = require('../common/alarmManagement').intercept, - constants = require('../../constants'), - errors = require('../../errors'), - Group = require('../../model/Group'), - async = require('async'), - context = { - op: 'IoTAgentNGSI.MongoDBGroupRegister' - }; + +const logger = require('logops'); +const dbService = require('../../model/dbConn'); +const intoTrans = require('../common/domain').intoTrans; +const fillService = require('./../common/domain').fillService; +const alarmsInt = require('../common/alarmManagement').intercept; +const constants = require('../../constants'); +const errors = require('../../errors'); +const Group = require('../../model/Group'); +const async = require('async'); +const context = { + op: 'IoTAgentNGSI.MongoDBGroupRegister' +}; /** * Generates a handler for the save device group operations. The handler will take the customary error and the saved @@ -44,6 +43,7 @@ var logger = require('logops'), * @return {Function} The generated handler. */ function saveGroupHandler(groupDAO, callback) { + /* eslint-disable-next-line no-unused-vars */ return function saveHandler(error, result) { if (error) { logger.debug(fillService(context, groupDAO), 'Error storing device group information: %s', error); @@ -56,38 +56,49 @@ function saveGroupHandler(groupDAO, callback) { } function createGroup(group, callback) { - var groupObj = new Group.model(), - attributeList = [ - 'url', - 'resource', - 'apikey', - 'type', - 'service', - 'subservice', - 'trust', - 'cbHost', - 'timezone', - 'timestamp', - 'commands', - 'lazy', - 'attributes', - 'staticAttributes', - 'internalAttributes', - 'autoprovision', - ]; - - for (var i = 0; i < attributeList.length; i++) { + /* eslint-disable-next-line new-cap */ + const groupObj = new Group.model(); + const attributeList = [ + 'url', + 'resource', + 'apikey', + 'type', + 'service', + 'subservice', + 'trust', + 'cbHost', + 'timezone', + 'timestamp', + 'commands', + 'lazy', + 'attributes', + 'staticAttributes', + 'internalAttributes', + 'autoprovision' + ]; + + for (let i = 0; i < attributeList.length; i++) { groupObj[attributeList[i]] = group[attributeList[i]]; } - logger.debug(context, 'Storing device group with id [%s], type [%s], apikey [%s] and resource [%s]', - groupObj._id, groupObj.type, groupObj.apikey, groupObj.resource); + logger.debug( + context, + 'Storing device group with id [%s], type [%s], apikey [%s] and resource [%s]', + groupObj._id, + groupObj.type, + groupObj.apikey, + groupObj.resource + ); groupObj.save(function saveHandler(error, groupDAO) { if (error) { if (error.code === 11000) { - logger.debug(context, 'Duplicate group entry with resource [%s] and apiKey [%s]', - group.resource, group.apikey); + logger.debug( + context, + 'Duplicate group entry with resource [%s] and apiKey [%s]', + group.resource, + group.apikey + ); callback(new errors.DuplicateGroup(group.resource, group.apikey)); } else { @@ -109,8 +120,7 @@ function createGroup(group, callback) { * @param {Number} offset Number of entries to skip for pagination. */ function listGroups(service, limit, offset, callback) { - var condition = {}, - query; + const condition = {}; function toObjectFn(obj) { return obj.toObject(); @@ -120,7 +130,7 @@ function listGroups(service, limit, offset, callback) { condition.service = service; } - query = Group.model.find(condition).sort(); + const query = Group.model.find(condition).sort(); if (limit) { query.limit(parseInt(limit, 10)); @@ -130,10 +140,10 @@ function listGroups(service, limit, offset, callback) { query.skip(parseInt(offset, 10)); } - async.series([ - query.exec.bind(query), - Group.model.countDocuments.bind(Group.model, condition) - ], function(error, results) { + async.series([query.exec.bind(query), Group.model.countDocuments.bind(Group.model, condition)], function( + error, + results + ) { callback(error, { count: results[1], services: results[0].map(toObjectFn) @@ -142,12 +152,10 @@ function listGroups(service, limit, offset, callback) { } function getById(id, callback) { - var query; - logger.debug(context, 'Looking for device group with id [%s].', id); - query = Group.model.findOne({_id: id}); - query.select({__v: 0}); + const query = Group.model.findOne({ _id: id }); + query.select({ __v: 0 }); query.exec(function handleGet(error, data) { if (error) { @@ -173,8 +181,7 @@ function getById(id, callback) { * @param {Function} callback The callback function. */ function find(service, subservice, callback) { - var condition = {}, - query; + const condition = {}; function toObjectFn(obj) { return obj.toObject(); @@ -183,12 +190,12 @@ function find(service, subservice, callback) { condition.service = service; condition.subservice = subservice; - query = Group.model.find(condition).sort(); + const query = Group.model.find(condition).sort(); - async.series([ - query.exec.bind(query), - Group.model.countDocuments.bind(Group.model, condition) - ], function(error, results) { + async.series([query.exec.bind(query), Group.model.countDocuments.bind(Group.model, condition)], function( + error, + results + ) { callback(error, { count: results[1], services: results[0].map(toObjectFn) @@ -196,28 +203,29 @@ function find(service, subservice, callback) { }); } - function findBy(fields) { return function() { - var query, - queryObj = {}, - i = 0, - callback; + const queryObj = {}; + let i = 0; + /* eslint-disable-next-line prefer-rest-params */ while (typeof arguments[i] !== 'function') { + /* eslint-disable-next-line prefer-rest-params */ if (arguments[i]) { + /* eslint-disable-next-line prefer-rest-params */ queryObj[fields[i]] = arguments[i]; } i++; } - callback = arguments[i]; + /* eslint-disable-next-line prefer-rest-params */ + const callback = arguments[i]; logger.debug(context, 'Looking for group params %j with queryObj %j', fields, queryObj); - query = Group.model.findOne(queryObj); + const query = Group.model.findOne(queryObj); - query.select({__v: 0}); + query.select({ __v: 0 }); query.exec(function handleGet(error, data) { if (error) { @@ -226,7 +234,6 @@ function findBy(fields) { } else if (data) { logger.debug(context, 'Device group data found: %j', data.toObject()); callback(null, data.toObject()); - } else { logger.debug(context, 'Device group for fields [%j] not found: [%j]', fields, queryObj); @@ -242,7 +249,7 @@ function update(id, body, callback) { if (error) { callback(error); } else { - var attributes = [ + const attributes = [ 'url', 'apikey', 'type', @@ -258,7 +265,7 @@ function update(id, body, callback) { 'staticAttributes' ]; - for (var i = 0; i < attributes.length; i++) { + for (let i = 0; i < attributes.length; i++) { if (body[attributes[i]]) { group[attributes[i]] = body[attributes[i]]; } @@ -304,8 +311,10 @@ exports.create = alarmsInt(constants.MONGO_ALARM, intoTrans(context, createGroup exports.list = alarmsInt(constants.MONGO_ALARM, intoTrans(context, listGroups)); exports.init = alarmsInt(constants.MONGO_ALARM, intoTrans(context, init)); exports.find = alarmsInt(constants.MONGO_ALARM, intoTrans(context, find)); -exports.findType = alarmsInt(constants.MONGO_ALARM, - intoTrans(context, findBy(['service', 'subservice', 'type', 'apikey']))); +exports.findType = alarmsInt( + constants.MONGO_ALARM, + intoTrans(context, findBy(['service', 'subservice', 'type', 'apikey'])) +); exports.findBy = alarmsInt(constants.MONGO_ALARM, intoTrans(context, findBy)); exports.get = alarmsInt(constants.MONGO_ALARM, intoTrans(context, findBy(['resource', 'apikey']))); exports.getType = alarmsInt(constants.MONGO_ALARM, intoTrans(context, findBy(['type']))); diff --git a/lib/services/groups/groupService.js b/lib/services/groups/groupService.js index fd1dc56c1..c1ec46527 100644 --- a/lib/services/groups/groupService.js +++ b/lib/services/groups/groupService.js @@ -21,19 +21,17 @@ * please contact with::daniel.moranjimenez@telefonica.com */ -'use strict'; - -var async = require('async'), - iotManagerService = require('./../common/iotManagerService'), - intoTrans = require('../common/domain').intoTrans, - apply = async.apply, - deviceService = require('../devices/deviceService'), - logger = require('logops'), - config = require('../../commonConfig'), - errors = require('../../errors'), - context = { - op: 'IoTAgentNGSI.DeviceGroupService' - }; +const async = require('async'); +const iotManagerService = require('./../common/iotManagerService'); +const intoTrans = require('../common/domain').intoTrans; +const apply = async.apply; +const deviceService = require('../devices/deviceService'); +const logger = require('logops'); +const config = require('../../commonConfig'); +const errors = require('../../errors'); +const context = { + op: 'IoTAgentNGSI.DeviceGroupService' +}; /** * Validate the Device Group: check mandatory params, and its check for duplicates with existing groups. This last @@ -43,7 +41,7 @@ var async = require('async'), * @param {Object} group Validate the device group */ function validateGroup(group, callback) { - var validations = []; + const validations = []; logger.debug(context, 'validateGroup %j', group); function generateDuplicateHandler(innerCb) { @@ -104,12 +102,12 @@ function validateGroup(group, callback) { * @param {Object} groupSet Set of device groups to add to the registry. */ function createGroup(groupSet, callback) { - var insertions = [], - insertedGroups = []; + const insertions = []; + const insertedGroups = []; logger.debug(context, 'Creating new set of %d services', groupSet.services.length); - for (var i = 0; i < groupSet.services.length; i++) { + for (let i = 0; i < groupSet.services.length; i++) { insertions.push(async.apply(validateGroup, groupSet.services[i])); insertions.push(async.apply(config.getGroupRegistry().create, groupSet.services[i])); insertedGroups.push(groupSet.services[i]); @@ -150,6 +148,7 @@ function checkServiceIdentity(service, subservice, deviceGroup, callback) { * @return {Function} A handler for the group related functions. */ function handleWithIotaRegistration(callback) { + /* eslint-disable-next-line no-unused-vars */ return function(error, objectResult) { if (error) { callback(error); @@ -181,19 +180,16 @@ function remove(service, subservice, resource, apikey, device, callback) { } function deleteDevices(device, service, subservice, id, callback) { - if(device) { - deviceService.listDevices(service, subservice, function (error, devices) { + if (device) { + deviceService.listDevices(service, subservice, function(error, devices) { if (error) { - callback(error); - } else { - if (devices && devices.count > 0){ - - async.map(devices.devices, unregisterDevice, function(error) { - if (error) { - callback(error); - } - }); - } + callback(error); + } else if (devices && devices.count > 0) { + async.map(devices.devices, unregisterDevice, function(error) { + if (error) { + callback(error); + } + }); } }); } @@ -201,13 +197,16 @@ function remove(service, subservice, resource, apikey, device, callback) { callback(null, id); } - async.waterfall([ - apply(config.getGroupRegistry().get, resource, apikey), - apply(checkServiceIdentity, service, subservice), - extractId, - apply(deleteDevices, device, service, subservice), - config.getGroupRegistry().remove - ], handleWithIotaRegistration(callback)); + async.waterfall( + [ + apply(config.getGroupRegistry().get, resource, apikey), + apply(checkServiceIdentity, service, subservice), + extractId, + apply(deleteDevices, device, service, subservice), + config.getGroupRegistry().remove + ], + handleWithIotaRegistration(callback) + ); } /** @@ -225,12 +224,15 @@ function update(service, subservice, resource, apikey, body, callback) { callback(null, deviceGroup._id, body); } - async.waterfall([ - apply(config.getGroupRegistry().get, resource, apikey), - apply(checkServiceIdentity, service, subservice), - extractId, - config.getGroupRegistry().update - ], handleWithIotaRegistration(callback)); + async.waterfall( + [ + apply(config.getGroupRegistry().get, resource, apikey), + apply(checkServiceIdentity, service, subservice), + extractId, + config.getGroupRegistry().update + ], + handleWithIotaRegistration(callback) + ); } /** @@ -266,16 +268,23 @@ function getGroup(resource, apikey, callback) { * @param {String} type Type of the device. */ function getEffectiveApiKey(service, subservice, type, callback) { - logger.debug(context, 'Getting effective API Key for service [%s], subservice [%s] and type [%s]', - service, subservice, type); + logger.debug( + context, + 'Getting effective API Key for service [%s], subservice [%s] and type [%s]', + service, + subservice, + type + ); function handleFindGroup(error, group) { if (group) { logger.debug(context, 'Using found group: %j', group); callback(null, group.apikey); - } else if (config.getConfig().types && + } else if ( + config.getConfig().types && config.getConfig().types[type] && - config.getConfig().types[type].apikey) { + config.getConfig().types[type].apikey + ) { logger.debug(context, 'Using API Key for type [%s]: %s', type, config.getConfig().types[type].apikey); callback(null, config.getConfig().types[type].apikey); } else if (config.getConfig().defaultKey) { diff --git a/lib/services/ngsi/ngsiParser.js b/lib/services/ngsi/ngsiParser.js index b1b76bc97..012b03611 100644 --- a/lib/services/ngsi/ngsiParser.js +++ b/lib/services/ngsi/ngsiParser.js @@ -20,16 +20,11 @@ * For those usages not covered by the GNU Affero General Public License * please contact with::[contacto@tid.es] */ -'use strict'; -/*jshint unused:false*/ -var async = require('async'), - errors = require('../../errors'), - logger = require('logops'), - intoTrans = require('../common/domain').intoTrans, - context = { - op: 'IoTAgentNGSI.NGSIParser' - }; +const intoTrans = require('../common/domain').intoTrans; +const context = { + op: 'IoTAgentNGSI.NGSIParser' +}; /** * Given a NGSI Body, determines whether it contains any NGSI error. @@ -38,11 +33,10 @@ var async = require('async'), * @return {Number|*} */ function getErrorField(body) { - var errorField = body.errorCode || - body.orionError; + let errorField = body.errorCode || body.orionError; if (body && body.contextResponses) { - for (var i in body.contextResponses) { + for (const i in body.contextResponses) { if (body.contextResponses[i].statusCode && body.contextResponses[i].statusCode.code !== '200') { errorField = body.contextResponses[i].statusCode; } diff --git a/lib/services/ngsi/ngsiService.js b/lib/services/ngsi/ngsiService.js index b915372b4..38753c46e 100644 --- a/lib/services/ngsi/ngsiService.js +++ b/lib/services/ngsi/ngsiService.js @@ -24,27 +24,31 @@ * Modified by: Daniel Calvo - ATOS Research & Innovation */ -'use strict'; - -var request = require('request'), - statsService = require('./../stats/statsRegistry'), - async = require('async'), - apply = async.apply, - intoTrans = require('../common/domain').intoTrans, - alarms = require('../common/alarmManagement'), - errors = require('../../errors'), - utils = require('../northBound/restUtils'), - config = require('../../commonConfig'), - constants = require('../../constants'), - moment = require('moment-timezone'), - logger = require('logops'), - ngsiParser = require('./ngsiParser'), - _ = require('underscore'), - context = { - op: 'IoTAgentNGSI.NGSIService' - }, - updateMiddleware = [], - queryMiddleware = []; +/* eslint-disable no-prototype-builtins */ + +const request = require('request'); +const statsService = require('./../stats/statsRegistry'); +const async = require('async'); +const apply = async.apply; +const intoTrans = require('../common/domain').intoTrans; +const alarms = require('../common/alarmManagement'); +const errors = require('../../errors'); + +const utils = require('../northBound/restUtils'); + +const config = require('../../commonConfig'); +const constants = require('../../constants'); + +const moment = require('moment-timezone'); + +const logger = require('logops'); +const ngsiParser = require('./ngsiParser'); +const _ = require('underscore'); +const context = { + op: 'IoTAgentNGSI.NGSIService' +}; +let updateMiddleware = []; +let queryMiddleware = []; /** * Generate an operation handler for NGSI-based operations (query and update). The handler takes care of identifiying @@ -68,19 +72,28 @@ function generateNGSIOperationHandler(operationName, entityName, typeInformation alarms.raise(constants.ORION_ALARM, error); callback(error); } else if (body && body.orionError) { - logger.debug(context, 'Orion error found executing ' + operationName + ' action in Context Broker: %j', - body.orionError); + logger.debug( + context, + 'Orion error found executing ' + operationName + ' action in Context Broker: %j', + body.orionError + ); callback(new errors.BadRequest(body.orionError.details)); } else if (response && body && response.statusCode === 200) { - var errorField = ngsiParser.getErrorField(body); + const errorField = ngsiParser.getErrorField(body); - logger.debug(context, - 'Received the following request from the CB:\n\n%s\n\n', JSON.stringify(body, null, 4)); + logger.debug( + context, + 'Received the following request from the CB:\n\n%s\n\n', + JSON.stringify(body, null, 4) + ); if (errorField) { - logger.error(context, - 'Operation ' + operationName + ' error connecting to the Context Broker: %j', errorField); + logger.error( + context, + 'Operation ' + operationName + ' error connecting to the Context Broker: %j', + errorField + ); if (errorField.code && errorField.code === '404') { callback(new errors.DeviceNotFound(entityName)); @@ -94,16 +107,26 @@ function generateNGSIOperationHandler(operationName, entityName, typeInformation } } else if (response && (response.statusCode === 403 || response.statusCode === 401)) { logger.debug(context, 'Access forbidden executing ' + operationName + ' operation'); - callback(new errors.AccessForbidden( - token, - options.headers['fiware-service'], - options.headers['fiware-servicepath'])); + callback( + new errors.AccessForbidden( + token, + options.headers['fiware-service'], + options.headers['fiware-servicepath'] + ) + ); } else { logger.debug(context, 'Unknown error executing ' + operationName + ' operation'); - callback(new errors.EntityGenericError(entityName, typeInformation.type, { - details: body - }, response.statusCode)); + callback( + new errors.EntityGenericError( + entityName, + typeInformation.type, + { + details: body + }, + response.statusCode + ) + ); } }; } @@ -130,40 +153,58 @@ function generateNGSI2OperationHandler(operationName, entityName, typeInformatio alarms.raise(constants.ORION_ALARM, error); callback(error); } else if (body && body.orionError) { - logger.debug(context, 'Orion error found executing ' + operationName + ' action in Context Broker: %j', - body.orionError); + logger.debug( + context, + 'Orion error found executing ' + operationName + ' action in Context Broker: %j', + body.orionError + ); callback(new errors.BadRequest(body.orionError.details)); - } else if (response && operationName === 'update' && (response.statusCode === 204)) { - logger.debug(context, 'Received the following response from the CB: Value updated successfully\n'); - alarms.release(constants.ORION_ALARM); - callback(null, body); + } else if (response && operationName === 'update' && response.statusCode === 204) { + logger.debug(context, 'Received the following response from the CB: Value updated successfully\n'); + alarms.release(constants.ORION_ALARM); + callback(null, body); } else if (response && operationName === 'query' && body !== undefined && response.statusCode === 200) { - logger.debug(context, - 'Received the following response from the CB:\n\n%s\n\n', JSON.stringify(body, null, 4)); - logger.debug(context, 'Value queried successfully'); - alarms.release(constants.ORION_ALARM); - callback(null, body); + logger.debug( + context, + 'Received the following response from the CB:\n\n%s\n\n', + JSON.stringify(body, null, 4) + ); + logger.debug(context, 'Value queried successfully'); + alarms.release(constants.ORION_ALARM); + callback(null, body); } else if (response && operationName === 'query' && response.statusCode === 204) { - logger.debug(context, - 'Received the following response from the CB:\n\n%s\n\n', JSON.stringify(body, null, 4)); + logger.debug( + context, + 'Received the following response from the CB:\n\n%s\n\n', + JSON.stringify(body, null, 4) + ); - logger.error(context, - 'Operation ' + operationName + ' bad status code from the CB: 204.' + - 'A query operation must always return a body'); + logger.error( + context, + 'Operation ' + + operationName + + ' bad status code from the CB: 204.' + + 'A query operation must always return a body' + ); callback(new errors.BadAnswer(response.statusCode, operationName)); } else if (response && (response.statusCode === 403 || response.statusCode === 401)) { logger.debug(context, 'Access forbidden executing ' + operationName + ' operation'); - callback(new errors.AccessForbidden( - token, - options.headers['fiware-service'], - options.headers['fiware-servicepath'])); + callback( + new errors.AccessForbidden( + token, + options.headers['fiware-service'], + options.headers['fiware-servicepath'] + ) + ); } else if (response && body && response.statusCode === 404) { - logger.debug(context, - 'Received the following response from the CB:\n\n%s\n\n', JSON.stringify(body, null, 4)); + logger.debug( + context, + 'Received the following response from the CB:\n\n%s\n\n', + JSON.stringify(body, null, 4) + ); - logger.error(context, - 'Operation ' + operationName + ' error connecting to the Context Broker: %j', body); + logger.error(context, 'Operation ' + operationName + ' error connecting to the Context Broker: %j', body); if (response.statusCode && response.statusCode === 404) { callback(new errors.DeviceNotFound(entityName)); @@ -172,13 +213,11 @@ function generateNGSI2OperationHandler(operationName, entityName, typeInformatio } } else { logger.debug(context, 'Unknown error executing ' + operationName + ' operation'); - if (! (body instanceof Array || body instanceof Object)) - { + if (!(body instanceof Array || body instanceof Object)) { body = JSON.parse(body); } - callback(new errors.EntityGenericError(entityName, typeInformation.type, - body, response.statusCode)); + callback(new errors.EntityGenericError(entityName, typeInformation.type, body, response.statusCode)); } }; } @@ -192,13 +231,13 @@ function generateNGSI2OperationHandler(operationName, entityName, typeInformatio * @return {Object} Containing all the information of the request but the payload.c */ function createRequestObject(url, typeInformation, token) { - var cbHost = config.getConfig().contextBroker.url, - options, - serviceContext = {}, - headers = { - 'fiware-service': config.getConfig().service, - 'fiware-servicepath': config.getConfig().subservice - }; + let cbHost = config.getConfig().contextBroker.url; + + const serviceContext = {}; + const headers = { + 'fiware-service': config.getConfig().service, + 'fiware-servicepath': config.getConfig().subservice + }; if (config.getConfig().authentication && config.getConfig().authentication.enabled) { headers[config.getConfig().authentication.header] = token; @@ -222,13 +261,12 @@ function createRequestObject(url, typeInformation, token) { } } - options = { + const options = { url: cbHost + url, method: 'POST', - headers: headers + headers }; - return intoTrans(serviceContext, function() { return options; })(); @@ -244,7 +282,7 @@ function applyMiddlewares(middlewareCollection, entity, typeInformation, callbac } if (middlewareCollection && middlewareCollection.length > 0) { - var middlewareList = _.clone(middlewareCollection); + const middlewareList = _.clone(middlewareCollection); middlewareList.unshift(emptyMiddleware); middlewareList.push(endMiddleware); @@ -256,28 +294,31 @@ function applyMiddlewares(middlewareCollection, entity, typeInformation, callbac } function addTimestamp(payload, timezone) { - - var timestamp = { - name: constants.TIMESTAMP_ATTRIBUTE, - type: constants.TIMESTAMP_TYPE - }; + const timestamp = { + name: constants.TIMESTAMP_ATTRIBUTE, + type: constants.TIMESTAMP_TYPE + }; if (!timezone) { - timestamp.value = (new Date()).toISOString(); + timestamp.value = new Date().toISOString(); } else { - timestamp.value = moment().tz(timezone).format('YYYY-MM-DD[T]HH:mm:ss.SSSZ'); + timestamp.value = moment() + .tz(timezone) + .format('YYYY-MM-DD[T]HH:mm:ss.SSSZ'); } function addMetadata(attribute) { - var timestampFound = false; + let timestampFound = false; if (!attribute.metadatas) { attribute.metadatas = []; } - for (var i = 0; i < attribute.metadatas.length; i++) { - if (attribute.metadatas[i].type === constants.TIMESTAMP_TYPE && - attribute.metadatas[i].name === constants.TIMESTAMP_ATTRIBUTE) { + for (let i = 0; i < attribute.metadatas.length; i++) { + if ( + attribute.metadatas[i].type === constants.TIMESTAMP_TYPE && + attribute.metadatas[i].name === constants.TIMESTAMP_ATTRIBUTE + ) { attribute.metadatas[i].value = timestamp.value; timestampFound = true; break; @@ -297,33 +338,35 @@ function addTimestamp(payload, timezone) { } function addTimestampNgsi2(payload, timezone) { - function addTimestampEntity(entity, timezone) { - - var timestamp = { - type: constants.TIMESTAMP_TYPE_NGSI2 - }; + const timestamp = { + type: constants.TIMESTAMP_TYPE_NGSI2 + }; if (!timezone) { - timestamp.value = (new Date()).toISOString(); + timestamp.value = new Date().toISOString(); } else { - timestamp.value = moment().tz(timezone).format('YYYY-MM-DD[T]HH:mm:ss.SSSZ'); + timestamp.value = moment() + .tz(timezone) + .format('YYYY-MM-DD[T]HH:mm:ss.SSSZ'); } function addMetadata(attribute) { - var timestampFound = false; + let timestampFound = false; if (!attribute.metadata) { attribute.metadata = {}; } - for (var i = 0; i < attribute.metadata.length; i++) { + for (let i = 0; i < attribute.metadata.length; i++) { if (attribute.metadata[i] === constants.TIMESTAMP_ATTRIBUTE) { - if (attribute.metadata[constants.TIMESTAMP_ATTRIBUTE].type === constants.TIMESTAMP_TYPE_NGSI2 && - attribute.metadata[constants.TIMESTAMP_ATTRIBUTE].value === timestamp.value) { - timestampFound = true; - break; - } + if ( + attribute.metadata[constants.TIMESTAMP_ATTRIBUTE].type === constants.TIMESTAMP_TYPE_NGSI2 && + attribute.metadata[constants.TIMESTAMP_ATTRIBUTE].value === timestamp.value + ) { + timestampFound = true; + break; + } } } @@ -333,8 +376,8 @@ function addTimestampNgsi2(payload, timezone) { return attribute; } - var keyCount = 0; - for (var key in entity) { + let keyCount = 0; + for (const key in entity) { if (entity.hasOwnProperty(key) && key !== 'id' && key !== 'type') { addMetadata(entity[key]); keyCount += 1; @@ -350,17 +393,15 @@ function addTimestampNgsi2(payload, timezone) { } if (payload instanceof Array) { - for (var i = 0; i < payload.length; i++) { + for (let i = 0; i < payload.length; i++) { if (!utils.isTimestampedNgsi2(payload[i])) { payload[i] = addTimestampEntity(payload[i], timezone); } } return payload; - } else { - return addTimestampEntity(payload, timezone); } - + return addTimestampEntity(payload, timezone); } /** @@ -370,7 +411,6 @@ function addTimestampNgsi2(payload, timezone) { * @return {String} New payload where attributes's values are casted to the corresponding JSON types */ function castJsonNativeAttributes(payload) { - /** * Determines if a value is of type float * @@ -385,27 +425,31 @@ function castJsonNativeAttributes(payload) { return payload; } - for (var key in payload) { - if (payload.hasOwnProperty(key) && payload[key].value && - payload[key].type && typeof(payload[key].value) === 'string') { + for (const key in payload) { + if ( + payload.hasOwnProperty(key) && + payload[key].value && + payload[key].type && + typeof payload[key].value === 'string' + ) { if (payload[key].type === 'Number' && isFloat(payload[key].value)) { payload[key].value = Number.parseFloat(payload[key].value); } else if (payload[key].type === 'Number' && Number.parseInt(payload[key].value)) { payload[key].value = Number.parseInt(payload[key].value); - } - else if (payload[key].type === 'Boolean') { - payload[key].value = (payload[key].value === 'true' || payload[key].value === '1'); - } - else if (payload[key].type === 'None') { + } else if (payload[key].type === 'Boolean') { + payload[key].value = payload[key].value === 'true' || payload[key].value === '1'; + } else if (payload[key].type === 'None') { payload[key].value = null; - } - else if (payload[key].type === 'Array' || payload[key].type === 'Object') { + } else if (payload[key].type === 'Array' || payload[key].type === 'Object') { try { - var parsedValue = JSON.parse(payload[key].value); + const parsedValue = JSON.parse(payload[key].value); payload[key].value = parsedValue; } catch (e) { - logger.error(context, 'Bad attribute value type.' + - 'Expecting JSON Array or JSON Object. Received:%s', payload[key].value); + logger.error( + context, + 'Bad attribute value type. Expecting JSON Array or JSON Object. Received:%s', + payload[key].value + ); } } } @@ -424,17 +468,15 @@ function castJsonNativeAttributes(payload) { * @param {String} token User token to identify against the PEP Proxies (optional). */ function sendUpdateValueNgsi2(entityName, attributes, typeInformation, token, callback) { + let payload = {}; + + let url = '/v2/entities/' + entityName + '/attrs'; - var payload = {}; - - var url = '/v2/entities/' + entityName + '/attrs'; - if (typeInformation.type) { - url += '?type=' + typeInformation.type; - } - - var options = createRequestObject(url, typeInformation, token); - + url += '?type=' + typeInformation.type; + } + + let options = createRequestObject(url, typeInformation, token); if (typeInformation && typeInformation.staticAttributes) { attributes = attributes.concat(typeInformation.staticAttributes); @@ -448,12 +490,12 @@ function sendUpdateValueNgsi2(entityName, attributes, typeInformation, token, ca payload.id = entityName; payload.type = typeInformation.type; - for (var i = 0; i < attributes.length; i++) { + for (let i = 0; i < attributes.length; i++) { if (attributes[i].name && attributes[i].type) { payload[attributes[i].name] = { - 'value' : attributes[i].value, - 'type' : attributes[i].type, - 'metadata' : attributes[i].metadata + value: attributes[i].value, + type: attributes[i].type, + metadata: attributes[i].metadata }; } else { callback(new errors.BadRequest(null, entityName)); @@ -461,96 +503,99 @@ function sendUpdateValueNgsi2(entityName, attributes, typeInformation, token, ca } } payload = castJsonNativeAttributes(payload); - async.waterfall([ - apply(statsService.add, 'measureRequests', 1), - apply(applyMiddlewares, updateMiddleware, payload, typeInformation)], + async.waterfall( + [ + apply(statsService.add, 'measureRequests', 1), + apply(applyMiddlewares, updateMiddleware, payload, typeInformation) + ], function(error, result) { - if (error) { - callback(error); - } else { - if (result) { - // The payload has been transformed by multientity plugin. It is not a JSON object but an Array. - if (result instanceof Array) { - options = createRequestObject( - '/v2/op/update', - typeInformation, - token); - - if ( ('timestamp' in typeInformation && typeInformation.timestamp !== - undefined) ? typeInformation.timestamp : config.getConfig().timestamp) { - // jshint maxdepth:5 - if (!utils.isTimestampedNgsi2(result)) { - options.json = addTimestampNgsi2(result, typeInformation.timezone); - // jshint maxdepth:5 - } else if (!utils.IsValidTimestampedNgsi2(result)) { - logger.error(context, 'Invalid timestamp:%s', JSON.stringify(result)); - callback(new errors.BadTimestamp(result)); - return; + if (error) { + callback(error); + } else { + if (result) { + // The payload has been transformed by multientity plugin. It is not a JSON object but an Array. + if (result instanceof Array) { + options = createRequestObject('/v2/op/update', typeInformation, token); + + if ( + 'timestamp' in typeInformation && typeInformation.timestamp !== undefined + ? typeInformation.timestamp + : config.getConfig().timestamp + ) { + if (!utils.isTimestampedNgsi2(result)) { + options.json = addTimestampNgsi2(result, typeInformation.timezone); + } else if (!utils.IsValidTimestampedNgsi2(result)) { + logger.error(context, 'Invalid timestamp:%s', JSON.stringify(result)); + callback(new errors.BadTimestamp(result)); + return; + } } - } - options.json = { - actionType: 'append', - entities: result - }; - } else { - delete result.id; - delete result.type; - options.json = result; - logger.debug(context, 'typeInformation: %j', typeInformation); - if ( ('timestamp' in typeInformation && typeInformation.timestamp !== - undefined) ? typeInformation.timestamp : config.getConfig().timestamp) { - if (!utils.isTimestampedNgsi2(options.json)) { - options.json = addTimestampNgsi2(options.json, typeInformation.timezone); - } else if (!utils.IsValidTimestampedNgsi2(options.json)) { - logger.error(context, 'Invalid timestamp:%s', JSON.stringify(options.json)); - callback(new errors.BadTimestamp(options.json)); - return; + options.json = { + actionType: 'append', + entities: result + }; + } else { + delete result.id; + delete result.type; + options.json = result; + logger.debug(context, 'typeInformation: %j', typeInformation); + + if ( + 'timestamp' in typeInformation && typeInformation.timestamp !== undefined + ? typeInformation.timestamp + : config.getConfig().timestamp + ) { + if (!utils.isTimestampedNgsi2(options.json)) { + options.json = addTimestampNgsi2(options.json, typeInformation.timezone); + } else if (!utils.IsValidTimestampedNgsi2(options.json)) { + logger.error(context, 'Invalid timestamp:%s', JSON.stringify(options.json)); + callback(new errors.BadTimestamp(options.json)); + return; + } } } + } else { + delete payload.id; + delete payload.type; + options.json = payload; } - } else { - delete payload.id; - delete payload.type; - options.json = payload; - } - // Purge object_id from entities before sent to CB - // object_id was added by createNgsi2Entity to allow multientity - // with duplicate attribute names. - var att; - if (options.json.entities) { - for (var entity = 0; entity < options.json.entities.length; entity++) { - for (att in options.json.entities[entity]) { - /*jshint camelcase: false */ - if (options.json.entities[entity][att].object_id) { - /*jshint camelcase: false */ - delete options.json.entities[entity][att].object_id; + // Purge object_id from entities before sent to CB + // object_id was added by createNgsi2Entity to allow multientity + // with duplicate attribute names. + let att; + if (options.json.entities) { + for (let entity = 0; entity < options.json.entities.length; entity++) { + for (att in options.json.entities[entity]) { + if (options.json.entities[entity][att].object_id) { + delete options.json.entities[entity][att].object_id; + } + if (options.json.entities[entity][att].multi) { + delete options.json.entities[entity][att].multi; + } } - if (options.json.entities[entity][att].multi) { - delete options.json.entities[entity][att].multi; - } - } - } - } else { - for (att in options.json) { - /*jshint camelcase: false */ - if (options.json[att].object_id) { - /*jshint camelcase: false */ - delete options.json[att].object_id; } - if (options.json[att].multi) { - delete options.json[att].multi; + } else { + for (att in options.json) { + if (options.json[att].object_id) { + delete options.json[att].object_id; + } + if (options.json[att].multi) { + delete options.json[att].multi; + } } } - } - logger.debug(context, 'Updating device value in the Context Broker at [%s]', options.url); - logger.debug(context, 'Using the following request:\n\n%s\n\n', JSON.stringify(options, null, 4)); + logger.debug(context, 'Updating device value in the Context Broker at [%s]', options.url); + logger.debug(context, 'Using the following request:\n\n%s\n\n', JSON.stringify(options, null, 4)); - request(options, - generateNGSI2OperationHandler('update', entityName, typeInformation, token, options, callback)); + request( + options, + generateNGSI2OperationHandler('update', entityName, typeInformation, token, options, callback) + ); + } } - }); + ); } /** @@ -562,9 +607,9 @@ function sendUpdateValueNgsi2(entityName, attributes, typeInformation, token, ca * @param {Object} typeInformation Configuration information for the device. * @param {String} token User token to identify against the PEP Proxies (optional). */ + function sendUpdateValueNgsi1(entityName, attributes, typeInformation, token, callback) { - var options = createRequestObject('/v1/updateContext', typeInformation, token), - payload; + const options = createRequestObject('/v1/updateContext', typeInformation, token); if (typeInformation && typeInformation.staticAttributes) { attributes = attributes.concat(typeInformation.staticAttributes); @@ -575,55 +620,64 @@ function sendUpdateValueNgsi1(entityName, attributes, typeInformation, token, ca return; } - payload = { - contextElements: [ - { - type: typeInformation.type, - isPattern: 'false', - id: entityName, - attributes: attributes - } - ] + const payload = { + contextElements: [ + { + type: typeInformation.type, + isPattern: 'false', + id: entityName, + attributes + } + ] }; - if ('autoprovision' in typeInformation && - /* jshint -W101 */ - typeInformation.autoprovision === undefined ? typeInformation.autoprovision === true : config.getConfig().appendMode === true) { + if ( + 'autoprovision' in typeInformation && typeInformation.autoprovision === undefined + ? typeInformation.autoprovision === true + : config.getConfig().appendMode === true + ) { payload.updateAction = 'APPEND'; } else { payload.updateAction = 'UPDATE'; } - async.waterfall([ - apply(statsService.add, 'measureRequests', 1), - apply(applyMiddlewares, updateMiddleware, payload, typeInformation) - ], function(error, result) { - if (error) { - callback(error); - } else { - if (result) { - options.json = result; + async.waterfall( + [ + apply(statsService.add, 'measureRequests', 1), + apply(applyMiddlewares, updateMiddleware, payload, typeInformation) + ], + function(error, result) { + if (error) { + callback(error); } else { - options.json = payload; - } + if (result) { + options.json = result; + } else { + options.json = payload; + } - if ( ('timestamp' in typeInformation && typeInformation.timestamp !== undefined) ? - typeInformation.timestamp : config.getConfig().timestamp) { - if (!utils.isTimestamped(options.json)) { - options.json = addTimestamp(options.json, typeInformation.timezone); - } else if (!utils.IsValidTimestamped(options.json)) { - logger.error(context, 'Invalid timestamp:%s', JSON.stringify(options.json)); - callback(new errors.BadTimestamp(options.json)); - return; + if ( + 'timestamp' in typeInformation && typeInformation.timestamp !== undefined + ? typeInformation.timestamp + : config.getConfig().timestamp + ) { + if (!utils.isTimestamped(options.json)) { + options.json = addTimestamp(options.json, typeInformation.timezone); + } else if (!utils.IsValidTimestamped(options.json)) { + logger.error(context, 'Invalid timestamp:%s', JSON.stringify(options.json)); + callback(new errors.BadTimestamp(options.json)); + return; + } } - - } - logger.debug(context, 'Updating device value in the Context Broker at [%s]', options.url); - logger.debug(context, 'Using the following request:\n\n%s\n\n', JSON.stringify(options, null, 4)); + logger.debug(context, 'Updating device value in the Context Broker at [%s]', options.url); + logger.debug(context, 'Using the following request:\n\n%s\n\n', JSON.stringify(options, null, 4)); - request(options, - generateNGSIOperationHandler('update', entityName, typeInformation, token, options, callback)); + request( + options, + generateNGSIOperationHandler('update', entityName, typeInformation, token, options, callback) + ); + } } - }); + ); } /** @@ -653,12 +707,12 @@ function sendUpdateValue(entityName, attributes, typeInformation, token, callbac * @param {String} token User token to identify against the PEP Proxies (optional). */ function sendQueryValueNgsi2(entityName, attributes, typeInformation, token, callback) { - var url = '/v2/entities/' + entityName + '/attrs'; + let url = '/v2/entities/' + entityName + '/attrs'; if (attributes && attributes.length > 0) { - var attributesQueryParam = ''; + let attributesQueryParam = ''; - for (var i = 0; i < attributes.length; i++) { + for (let i = 0; i < attributes.length; i++) { attributesQueryParam = attributesQueryParam + attributes[i]; if (i < attributes.length - 1) { attributesQueryParam = attributesQueryParam + ','; @@ -672,11 +726,11 @@ function sendQueryValueNgsi2(entityName, attributes, typeInformation, token, cal if (attributes && attributes.length > 0) { url += '&type=' + typeInformation.type; } else { - url += '?type=' + typeInformation.type; + url += '?type=' + typeInformation.type; } } - var options = createRequestObject(url, typeInformation, token); + const options = createRequestObject(url, typeInformation, token); options.method = 'GET'; options.json = true; @@ -688,16 +742,16 @@ function sendQueryValueNgsi2(entityName, attributes, typeInformation, token, cal logger.debug(context, 'Querying values of the device in the Context Broker at [%s]', options.url); logger.debug(context, 'Using the following request:\n\n%s\n\n', JSON.stringify(options, null, 4)); - - request(options, - generateNGSI2OperationHandler('query', entityName, typeInformation, token, options, - function(error, result) { - if (error) { - callback(error); - } else { - applyMiddlewares(queryMiddleware, result, typeInformation, callback); - } - })); + request( + options, + generateNGSI2OperationHandler('query', entityName, typeInformation, token, options, function(error, result) { + if (error) { + callback(error); + } else { + applyMiddlewares(queryMiddleware, result, typeInformation, callback); + } + }) + ); } /** @@ -710,7 +764,7 @@ function sendQueryValueNgsi2(entityName, attributes, typeInformation, token, cal * @param {String} token User token to identify against the PEP Proxies (optional). */ function sendQueryValueNgsi1(entityName, attributes, typeInformation, token, callback) { - var options = createRequestObject('/v1/queryContext', typeInformation, token); + const options = createRequestObject('/v1/queryContext', typeInformation, token); if (!typeInformation || !typeInformation.type) { callback(new errors.TypeNotFound(null, entityName)); @@ -718,29 +772,29 @@ function sendQueryValueNgsi1(entityName, attributes, typeInformation, token, cal } options.json = { - entities: [ - { - type: typeInformation.type, - isPattern: 'false', - id: entityName - } - ], - attributes: attributes - }; + entities: [ + { + type: typeInformation.type, + isPattern: 'false', + id: entityName + } + ], + attributes + }; logger.debug(context, 'Querying values of the device in the Context Broker at [%s]', options.url); logger.debug(context, 'Using the following request:\n\n%s\n\n', JSON.stringify(options, null, 4)); - - request(options, - generateNGSIOperationHandler('query', entityName, typeInformation, token, options, - function(error, result) { - if (error) { - callback(error); - } else { - applyMiddlewares(queryMiddleware, result, typeInformation, callback); - } - })); + request( + options, + generateNGSIOperationHandler('query', entityName, typeInformation, token, options, function(error, result) { + if (error) { + callback(error); + } else { + applyMiddlewares(queryMiddleware, result, typeInformation, callback); + } + }) + ); } /** @@ -774,10 +828,11 @@ function sendQueryValue(entityName, attributes, typeInformation, token, callback function updateTrust(deviceGroup, deviceInformation, trust, response, callback) { if (deviceGroup && response && response.body && !config.getConfig().authentication.permanentToken) { - var body = JSON.parse(response.body); - /* jshint camelcase: false */ + const body = JSON.parse(response.body); + if (body && body.refresh_token) { deviceGroup.trust = body.refresh_token; + /* eslint-disable-next-line no-unused-vars */ config.getGroupRegistry().update(deviceGroup._id, deviceGroup, function(error, cb) { callback(null, response); }); @@ -798,13 +853,18 @@ function updateTrust(deviceGroup, deviceInformation, trust, response, callback) * @return {Function} The function that gets all the information wrapping the given operation. */ function executeWithDeviceInformation(operationFunction) { - return function(entityName, type, apikey, attributes, deviceInformation, callback) { - logger.debug(context, + logger.debug( + context, 'executeWithDeviceInfo entityName %s type %s apikey %s attributes %j deviceInformation %j', - entityName, type, apikey, attributes, deviceInformation); + entityName, + type, + apikey, + attributes, + deviceInformation + ); config.getGroupRegistry().getType(type, function(error, deviceGroup) { - var typeInformation; + let typeInformation; if (error) { logger.debug(context, 'error %j in get group device', error); } @@ -825,21 +885,24 @@ function executeWithDeviceInformation(operationFunction) { typeInformation.trust = config.getConfig().types[type].trust; } - if(deviceGroup && deviceGroup.cbHost) { + if (deviceGroup && deviceGroup.cbHost) { typeInformation.cbHost = deviceGroup.cbHost; } } } if (config.getConfig().authentication && config.getConfig().authentication.enabled) { - var security = config.getSecurityService(); + const security = config.getSecurityService(); if (typeInformation && typeInformation.trust) { - async.waterfall([ - apply(security.auth, typeInformation.trust), - apply(updateTrust, deviceGroup, deviceInformation, typeInformation.trust), - apply(security.getToken, typeInformation.trust), - apply(operationFunction, entityName, attributes, typeInformation) - ], callback); + async.waterfall( + [ + apply(security.auth, typeInformation.trust), + apply(updateTrust, deviceGroup, deviceInformation, typeInformation.trust), + apply(security.getToken, typeInformation.trust), + apply(operationFunction, entityName, attributes, typeInformation) + ], + callback + ); } else { callback(new errors.SecurityInformationMissing(typeInformation.type)); } @@ -862,24 +925,31 @@ function executeWithDeviceInformation(operationFunction) { * @param {String} commandResult Result of the command in string format. * @param {Object} deviceInformation Device information, including security and service information. (optional). */ -function setCommandResult(entityName, resource, apikey, commandName, - commandResult, status, deviceInformation, callback) { - +function setCommandResult( + entityName, + resource, + apikey, + commandName, + commandResult, + status, + deviceInformation, + callback +) { config.getGroupRegistry().get(resource, apikey, function(error, deviceGroup) { - var typeInformation, - commandInfo, - attributes = [ - { - name: commandName + constants.COMMAND_STATUS_SUFIX, - type: constants.COMMAND_STATUS, - value: status - }, - { - name: commandName + constants.COMMAND_RESULT_SUFIX, - type: constants.COMMAND_RESULT, - value: commandResult - } - ]; + let typeInformation; + + const attributes = [ + { + name: commandName + constants.COMMAND_STATUS_SUFIX, + type: constants.COMMAND_STATUS, + value: status + }, + { + name: commandName + constants.COMMAND_RESULT_SUFIX, + type: constants.COMMAND_RESULT, + value: commandResult + } + ]; if (!callback) { callback = deviceInformation; @@ -909,17 +979,10 @@ function setCommandResult(entityName, resource, apikey, commandName, typeInformation.subservice = config.getConfig().subservice; } - commandInfo = _.where(typeInformation.commands, {name: commandName}); + const commandInfo = _.where(typeInformation.commands, { name: commandName }); if (commandInfo.length === 1) { - exports.update( - entityName, - resource, - apikey, - attributes, - typeInformation, - callback - ); + exports.update(entityName, resource, apikey, attributes, typeInformation, callback); } else { callback(new errors.CommandNotFound(commandName)); } diff --git a/lib/services/ngsi/subscriptionService.js b/lib/services/ngsi/subscriptionService.js index e1e5a3799..4cfc1b993 100644 --- a/lib/services/ngsi/subscriptionService.js +++ b/lib/services/ngsi/subscriptionService.js @@ -24,17 +24,14 @@ * Modified by: Daniel Calvo - ATOS Research & Innovation */ -'use strict'; - -var errors = require('../../errors'), - intoTrans = require('../common/domain').intoTrans, - logger = require('logops'), - config = require('../../commonConfig'), - deviceService = require('../devices/deviceService'), - context = { - op: 'IoTAgentNGSI.NGSIService' - }; - +const errors = require('../../errors'); +const intoTrans = require('../common/domain').intoTrans; +const logger = require('logops'); +const config = require('../../commonConfig'); +const deviceService = require('../devices/deviceService'); +const context = { + op: 'IoTAgentNGSI.NGSIService' +}; /** * Generate a new subscription request handler using NGSIv1, based on the device and triggers given to the function. @@ -50,23 +47,37 @@ function createSubscriptionHandlerNgsi1(device, triggers, store, callback) { if (error || !body) { logger.debug( context, - 'Transport error found subscribing device with id [%s] to entity [%s]', device.id, device.name); + 'Transport error found subscribing device with id [%s] to entity [%s]', + device.id, + device.name + ); callback(error); - } else if (response.statusCode !== 200 && response.statusCode !== 201) { - logger.debug(context, 'Unknown error subscribing device with id [%s] to entity [%s]: $s', - response.statusCode); - - callback(new errors.EntityGenericError(device.name, device.type, { - details: body - }, response.statusCode)); + logger.debug( + context, + 'Unknown error subscribing device with id [%s] to entity [%s]: $s', + response.statusCode + ); + callback( + new errors.EntityGenericError( + device.name, + device.type, + { + details: body + }, + response.statusCode + ) + ); } else if (body && body.orionError) { logger.debug( context, 'Orion found subscribing device with id [%s] to entity [%s]: %s', - device.id, device.name, body.orionError); + device.id, + device.name, + body.orionError + ); callback(new errors.BadRequest(body.orionError.details)); } else if (store) { @@ -76,7 +87,7 @@ function createSubscriptionHandlerNgsi1(device, triggers, store, callback) { device.subscriptions.push({ id: body.subscribeResponse.subscriptionId, - triggers: triggers + triggers }); config.getRegistry().update(device, callback); @@ -100,23 +111,37 @@ function createSubscriptionHandlerNgsi2(device, triggers, store, callback) { if (error) { logger.debug( context, - 'Transport error found subscribing device with id [%s] to entity [%s]', device.id, device.name); + 'Transport error found subscribing device with id [%s] to entity [%s]', + device.id, + device.name + ); callback(error); - } else if (response.statusCode !== 200 && response.statusCode !== 201) { - logger.debug(context, 'Unknown error subscribing device with id [%s] to entity [%s]: $s', - response.statusCode); - - callback(new errors.EntityGenericError(device.name, device.type, { - details: body - }, response.statusCode)); + logger.debug( + context, + 'Unknown error subscribing device with id [%s] to entity [%s]: $s', + response.statusCode + ); + callback( + new errors.EntityGenericError( + device.name, + device.type, + { + details: body + }, + response.statusCode + ) + ); } else if (body && body.orionError) { logger.debug( context, 'Orion found subscribing device with id [%s] to entity [%s]: %s', - device.id, device.name, body.orionError); + device.id, + device.name, + body.orionError + ); callback(new errors.BadRequest(body.orionError.details)); } else if (store) { @@ -126,7 +151,7 @@ function createSubscriptionHandlerNgsi2(device, triggers, store, callback) { device.subscriptions.push({ id: response.headers.location.substr(response.headers.location.lastIndexOf('/') + 1), - triggers: triggers + triggers }); config.getRegistry().update(device, callback); @@ -146,31 +171,31 @@ function createSubscriptionHandlerNgsi2(device, triggers, store, callback) { * @param {Object} content Array with the names of the attributes to retrieve in the notification. */ function subscribeNgsi1(device, triggers, content, callback) { - var options = { + const options = { method: 'POST', headers: { 'fiware-service': device.service, 'fiware-servicepath': device.subservice }, json: { - entities: [ - { - type: device.type, - isPattern: 'false', - id: device.name - } - ], - reference: config.getConfig().providerUrl + '/notify', - duration: config.getConfig().deviceRegistrationDuration || 'P100Y', - notifyConditions: [ - { - type: 'ONCHANGE', - condValues: triggers - } - ] - } - }, - store = true; + entities: [ + { + type: device.type, + isPattern: 'false', + id: device.name + } + ], + reference: config.getConfig().providerUrl + '/notify', + duration: config.getConfig().deviceRegistrationDuration || 'P100Y', + notifyConditions: [ + { + type: 'ONCHANGE', + condValues: triggers + } + ] + } + }; + let store = true; if (content) { options.json.attributes = content; @@ -184,8 +209,11 @@ function subscribeNgsi1(device, triggers, content, callback) { } else { options.uri = config.getConfig().contextBroker.url + '/v1/subscribeContext'; } - deviceService.executeWithSecurity(options, - device, createSubscriptionHandlerNgsi1(device, triggers, store, callback)); + deviceService.executeWithSecurity( + options, + device, + createSubscriptionHandlerNgsi1(device, triggers, store, callback) + ); } /** @@ -198,37 +226,36 @@ function subscribeNgsi1(device, triggers, content, callback) { * @param {Object} content Array with the names of the attributes to retrieve in the notification. */ function subscribeNgsi2(device, triggers, content, callback) { - var options = { + const options = { method: 'POST', headers: { 'fiware-service': device.service, 'fiware-servicepath': device.subservice }, json: { - subject: - { - entities: [ - { - id: device.name, - type: device.type - } - ], - - condition: { - attrs: triggers - }, - }, - notification: { - http: { - url: config.getConfig().providerUrl + '/notify' - }, - attrs: content || [], - attrsFormat: 'normalized' + subject: { + entities: [ + { + id: device.name, + type: device.type + } + ], + + condition: { + attrs: triggers } + }, + notification: { + http: { + url: config.getConfig().providerUrl + '/notify' + }, + attrs: content || [], + attrsFormat: 'normalized' + } } }; - var store = true; + let store = true; if (content) { store = false; @@ -241,8 +268,11 @@ function subscribeNgsi2(device, triggers, content, callback) { } else { options.uri = config.getConfig().contextBroker.url + '/v2/subscriptions'; } - deviceService.executeWithSecurity(options, - device, createSubscriptionHandlerNgsi2(device, triggers, store, callback)); + deviceService.executeWithSecurity( + options, + device, + createSubscriptionHandlerNgsi2(device, triggers, store, callback) + ); } /** @@ -276,25 +306,37 @@ function createUnsubscribeHandlerNgsi1(device, id, callback) { if (error || !body) { logger.debug( context, - 'Transport error found subscribing device with id [%s] to entity [%s]', device.id, device.name); + 'Transport error found subscribing device with id [%s] to entity [%s]', + device.id, + device.name + ); callback(error); - } else if (response.statusCode !== 200 && response.statusCode !== 201) { logger.debug( context, 'Unknown error subscribing device with id [%s] to entity [%s]: $s', - response.statusCode); - - callback(new errors.EntityGenericError(device.name, device.type, { - details: body - }, response.statusCode)); + response.statusCode + ); + callback( + new errors.EntityGenericError( + device.name, + device.type, + { + details: body + }, + response.statusCode + ) + ); } else if (body && body.orionError) { logger.debug( context, 'Orion found subscribing device with id [%s] to entity [%s]: %s', - device.id, device.name, body.orionError); + device.id, + device.name, + body.orionError + ); callback(new errors.BadRequest(body.orionError.details)); } else { @@ -318,25 +360,37 @@ function createUnsubscribeHandlerNgsi2(device, id, callback) { if (error) { logger.debug( context, - 'Transport error found subscribing device with id [%s] to entity [%s]', device.id, device.name); + 'Transport error found subscribing device with id [%s] to entity [%s]', + device.id, + device.name + ); callback(error); - } else if (response.statusCode !== 204) { logger.debug( context, 'Unknown error subscribing device with id [%s] to entity [%s]: $s', - response.statusCode); - - callback(new errors.EntityGenericError(device.name, device.type, { - details: body - }, response.statusCode)); + response.statusCode + ); + callback( + new errors.EntityGenericError( + device.name, + device.type, + { + details: body + }, + response.statusCode + ) + ); } else if (body && body.orionError) { logger.debug( context, 'Orion found subscribing device with id [%s] to entity [%s]: %s', - device.id, device.name, body.orionError); + device.id, + device.name, + body.orionError + ); callback(new errors.BadRequest(body.orionError.details)); } else { @@ -353,7 +407,7 @@ function createUnsubscribeHandlerNgsi2(device, id, callback) { * @param {String} id ID of the subscription to remove. */ function unsubscribeNgsi1(device, id, callback) { - var options = { + const options = { method: 'POST', headers: { 'fiware-service': device.service, @@ -362,7 +416,6 @@ function unsubscribeNgsi1(device, id, callback) { json: { subscriptionId: id } - }; if (device.cbHost && device.cbHost.indexOf('://') !== -1) { @@ -382,7 +435,7 @@ function unsubscribeNgsi1(device, id, callback) { * @param {String} id ID of the subscription to remove. */ function unsubscribeNgsi2(device, id, callback) { - var options = { + const options = { method: 'DELETE', headers: { 'fiware-service': device.service, diff --git a/lib/services/northBound/contextServer.js b/lib/services/northBound/contextServer.js index d757bc89b..14c2ac3fc 100644 --- a/lib/services/northBound/contextServer.js +++ b/lib/services/northBound/contextServer.js @@ -22,33 +22,37 @@ * * Modified by: Daniel Calvo - ATOS Research & Innovation */ -'use strict'; - -var async = require('async'), - apply = async.apply, - logger = require('logops'), - constants = require('../../constants'), - errors = require('../../errors'), - ngsi = require('../ngsi/ngsiService'), - intoTrans = require('../common/domain').intoTrans, - deviceService = require('../devices/deviceService'), - commands = require('../commands/commandService'), - middlewares = require('../common/genericMiddleware'), - _ = require('underscore'), - config = require('../../commonConfig'), - context = { - op: 'IoTAgentNGSI.ContextServer' - }, - updateContextTemplateNgsi1 = require('../../templates/updateContextNgsi1.json'), - updateContextTemplateNgsi2 = require('../../templates/updateContextNgsi2.json'), - queryContextTemplate = require('../../templates/queryContext.json'), - notificationTemplateNgsi1 = require('../../templates/notificationTemplateNgsi1.json'), - notificationTemplateNgsi2 = require('../../templates/notificationTemplateNgsi2.json'), - notificationMiddlewares = [], - updateHandler, - commandHandler, - queryHandler, - notificationHandler; + +/* eslint-disable no-useless-escape */ +/* eslint-disable no-unused-vars */ +/* eslint-disable no-prototype-builtins */ +/* eslint-disable consistent-return */ + +const async = require('async'); +const apply = async.apply; +const logger = require('logops'); +const constants = require('../../constants'); +const errors = require('../../errors'); +const ngsi = require('../ngsi/ngsiService'); +const intoTrans = require('../common/domain').intoTrans; +const deviceService = require('../devices/deviceService'); +const commands = require('../commands/commandService'); +const middlewares = require('../common/genericMiddleware'); +const _ = require('underscore'); +const config = require('../../commonConfig'); +const context = { + op: 'IoTAgentNGSI.ContextServer' +}; +const updateContextTemplateNgsi1 = require('../../templates/updateContextNgsi1.json'); +const updateContextTemplateNgsi2 = require('../../templates/updateContextNgsi2.json'); +const queryContextTemplate = require('../../templates/queryContext.json'); +const notificationTemplateNgsi1 = require('../../templates/notificationTemplateNgsi1.json'); +const notificationTemplateNgsi2 = require('../../templates/notificationTemplateNgsi2.json'); +let notificationMiddlewares = []; +let updateHandler; +let commandHandler; +let queryHandler; +let notificationHandler; /** * Create the response for an UpdateContext operation, based on the results of the individual updates. The signature @@ -60,12 +64,12 @@ var async = require('async'), * @return {{contextResponses: Array}} */ function createUpdateResponse(req, res, results) { - var result = { + const result = { contextResponses: [] }; - for (var i = 0; i < req.body.contextElements.length; i++) { - var contextResponse = { + for (let i = 0; i < req.body.contextElements.length; i++) { + const contextResponse = { contextElement: { attributes: req.body.contextElements[i].attributes, id: req.body.contextElements[i].id, @@ -78,7 +82,7 @@ function createUpdateResponse(req, res, results) { } }; - for (var j = 0; j < contextResponse.contextElement.attributes.length; j++) { + for (let j = 0; j < contextResponse.contextElement.attributes.length; j++) { contextResponse.contextElement.attributes[i].value = ''; } @@ -100,12 +104,12 @@ function createUpdateResponse(req, res, results) { * @return {{contextResponses: Array}} */ function createQueryResponse(req, res, results) { - var result = { + const result = { contextResponses: [] }; - for (var i = 0; i < results.length; i++) { - var contextResponse = { + for (let i = 0; i < results.length; i++) { + const contextResponse = { contextElement: results[i], statusCode: { code: 200, @@ -135,13 +139,13 @@ function createQueryResponse(req, res, results) { * @param {Array} attributes List of attributes to update with their types and values. */ function executeUpdateSideEffects(device, id, type, service, subservice, attributes, callback) { - var sideEffects = []; + const sideEffects = []; if (device.commands) { - for (var i = 0; i < device.commands.length; i++) { - for (var j = 0; j < attributes.length; j++) { + for (let i = 0; i < device.commands.length; i++) { + for (let j = 0; j < attributes.length; j++) { if (device.commands[i].name === attributes[j].name) { - var newAttributes = [ + const newAttributes = [ { name: device.commands[i].name + '_status', type: constants.COMMAND_STATUS, @@ -150,13 +154,7 @@ function executeUpdateSideEffects(device, id, type, service, subservice, attribu ]; sideEffects.push( - apply(ngsi.update, - device.name, - device.resource, - device.apikey, - newAttributes, - device - ) + apply(ngsi.update, device.name, device.resource, device.apikey, newAttributes, device) ); } } @@ -190,13 +188,13 @@ function pushCommandsToQueue(device, id, type, service, subservice, attributes, */ function generateUpdateActionsNgsi1(req, contextElement, callback) { function splitUpdates(device, callback) { - var attributes = [], - commands = [], - found; + let attributes = []; + const commands = []; + let found; if (device.commands) { - attributeLoop: for (var i in contextElement.attributes) { - for (var j in device.commands) { + attributeLoop: for (const i in contextElement.attributes) { + for (const j in device.commands) { if (contextElement.attributes[i].name === device.commands[j].name) { commands.push(contextElement.attributes[i]); found = true; @@ -206,7 +204,6 @@ function generateUpdateActionsNgsi1(req, contextElement, callback) { attributes.push(contextElement.attributes[i]); } - } else { attributes = contextElement.attributes; } @@ -215,7 +212,7 @@ function generateUpdateActionsNgsi1(req, contextElement, callback) { } function createActionsArray(attributes, commands, device, callback) { - var updateActions = []; + const updateActions = []; if (updateHandler) { updateActions.push( @@ -225,7 +222,8 @@ function generateUpdateActionsNgsi1(req, contextElement, callback) { contextElement.type, req.headers['fiware-service'], req.headers['fiware-servicepath'], - attributes) + attributes + ) ); } @@ -239,7 +237,8 @@ function generateUpdateActionsNgsi1(req, contextElement, callback) { contextElement.type, req.headers['fiware-service'], req.headers['fiware-servicepath'], - contextElement.attributes) + contextElement.attributes + ) ); } else { updateActions.push( @@ -249,7 +248,8 @@ function generateUpdateActionsNgsi1(req, contextElement, callback) { contextElement.type, req.headers['fiware-service'], req.headers['fiware-servicepath'], - commands) + commands + ) ); } } @@ -262,36 +262,38 @@ function generateUpdateActionsNgsi1(req, contextElement, callback) { contextElement.type, req.headers['fiware-service'], req.headers['fiware-servicepath'], - contextElement.attributes) + contextElement.attributes + ) ); callback(null, updateActions); } - deviceService.getDeviceByName(contextElement.id, req.headers['fiware-service'], req.headers['fiware-servicepath'], + deviceService.getDeviceByName( + contextElement.id, + req.headers['fiware-service'], + req.headers['fiware-servicepath'], function(error, deviceObj) { if (error) { callback(error); } else { - async.waterfall([ - apply(deviceService.findConfigurationGroup, deviceObj), - apply(deviceService.mergeDeviceWithConfiguration, - [ - 'lazy', - 'internalAttributes', - 'active', - 'staticAttributes', - 'commands', - 'subscriptions' - ], - [null, null, [], [], [], [], []], - deviceObj - ), - splitUpdates, - createActionsArray - ], callback); + async.waterfall( + [ + apply(deviceService.findConfigurationGroup, deviceObj), + apply( + deviceService.mergeDeviceWithConfiguration, + ['lazy', 'internalAttributes', 'active', 'staticAttributes', 'commands', 'subscriptions'], + [null, null, [], [], [], [], []], + deviceObj + ), + splitUpdates, + createActionsArray + ], + callback + ); } - }); + } + ); } /** @@ -302,27 +304,26 @@ function generateUpdateActionsNgsi1(req, contextElement, callback) { * @param {Object} contextElement Context Element whose actions will be extracted. */ function generateUpdateActionsNgsi2(req, contextElement, callback) { - var entityId; - var entityType; + let entityId; + let entityType; if (contextElement.id && contextElement.type) { entityId = contextElement.id; entityType = contextElement.type; - }else if (req.params.entity) { + } else if (req.params.entity) { entityId = req.params.entity; } function splitUpdates(device, callback) { - var attributes = [], - commands = [], - found, - newAtt, - i; + const attributes = []; + const commands = []; + let found; + let newAtt; + let i; if (device.commands) { attributeLoop: for (i in contextElement) { - for (var j in device.commands) { - + for (const j in device.commands) { if (i === device.commands[j].name) { newAtt = {}; newAtt[i] = contextElement[i]; @@ -333,7 +334,6 @@ function generateUpdateActionsNgsi2(req, contextElement, callback) { } } } - } for (i in contextElement) { @@ -349,9 +349,9 @@ function generateUpdateActionsNgsi2(req, contextElement, callback) { } function createActionsArray(attributes, commands, device, callback) { - var updateActions = []; + const updateActions = []; - if(!entityType) { + if (!entityType) { entityType = device.type; } @@ -363,7 +363,8 @@ function generateUpdateActionsNgsi2(req, contextElement, callback) { entityType, req.headers['fiware-service'], req.headers['fiware-servicepath'], - attributes) + attributes + ) ); } @@ -377,7 +378,8 @@ function generateUpdateActionsNgsi2(req, contextElement, callback) { entityType, req.headers['fiware-service'], req.headers['fiware-servicepath'], - attributes) + attributes + ) ); } else { updateActions.push( @@ -387,7 +389,8 @@ function generateUpdateActionsNgsi2(req, contextElement, callback) { entityType, req.headers['fiware-service'], req.headers['fiware-servicepath'], - commands) + commands + ) ); } } @@ -400,36 +403,36 @@ function generateUpdateActionsNgsi2(req, contextElement, callback) { entityType, req.headers['fiware-service'], req.headers['fiware-servicepath'], - attributes) + attributes + ) ); callback(null, updateActions); } - deviceService.getDeviceByName(entityId, req.headers['fiware-service'], req.headers['fiware-servicepath'], - function(error, deviceObj) { - if (error) { - callback(error); - } else { - async.waterfall([ + deviceService.getDeviceByName(entityId, req.headers['fiware-service'], req.headers['fiware-servicepath'], function( + error, + deviceObj + ) { + if (error) { + callback(error); + } else { + async.waterfall( + [ apply(deviceService.findConfigurationGroup, deviceObj), - apply(deviceService.mergeDeviceWithConfiguration, - [ - 'lazy', - 'internalAttributes', - 'active', - 'staticAttributes', - 'commands', - 'subscriptions' - ], + apply( + deviceService.mergeDeviceWithConfiguration, + ['lazy', 'internalAttributes', 'active', 'staticAttributes', 'commands', 'subscriptions'], [null, null, [], [], [], [], []], deviceObj ), splitUpdates, createActionsArray - ], callback); - } - }); + ], + callback + ); + } + }); } /** @@ -444,24 +447,23 @@ function handleUpdateNgsi2(req, res, next) { logger.debug(context, 'Handling update from [%s]', req.get('host')); logger.debug(context, req.body); - async.waterfall([ - apply(async.map, req.body.entities, apply(generateUpdateActionsNgsi2, req)), - reduceActions, - async.series - ], function(error, result) { - if (error) { - logger.debug(context, 'There was an error handling the update action: %s.', error); + async.waterfall( + [apply(async.map, req.body.entities, apply(generateUpdateActionsNgsi2, req)), reduceActions, async.series], + function(error, result) { + if (error) { + logger.debug(context, 'There was an error handling the update action: %s.', error); - next(error); - } else { - logger.debug(context, 'Update action from [%s] handled successfully.', req.get('host')); - res.status(204).json(); + next(error); + } else { + logger.debug(context, 'Update action from [%s] handled successfully.', req.get('host')); + res.status(204).json(); + } } - }); + ); } else { logger.error(context, 'Tried to handle an update request before the update handler was stablished.'); - var errorNotFound = new Error({ + const errorNotFound = new Error({ message: 'Update handler not found' }); next(errorNotFound); @@ -474,7 +476,6 @@ function handleUpdateNgsi2(req, res, next) { * to the user update handler function is made. */ function handleUpdateNgsi1(req, res, next) { - function reduceActions(actions, callback) { callback(null, _.flatten(actions)); } @@ -483,24 +484,27 @@ function handleUpdateNgsi1(req, res, next) { logger.debug(context, 'Handling update from [%s]', req.get('host')); logger.debug(context, req.body); - async.waterfall([ - apply(async.map, req.body.contextElements, apply(generateUpdateActionsNgsi1, req)), - reduceActions, - async.series - ], function(error, result) { - if (error) { - logger.debug(context, 'There was an error handling the update action: %s.', error); + async.waterfall( + [ + apply(async.map, req.body.contextElements, apply(generateUpdateActionsNgsi1, req)), + reduceActions, + async.series + ], + function(error, result) { + if (error) { + logger.debug(context, 'There was an error handling the update action: %s.', error); - next(error); - } else { - logger.debug(context, 'Update action from [%s] handled successfully.', req.get('host')); - res.status(200).json(createUpdateResponse(req, res, result)); + next(error); + } else { + logger.debug(context, 'Update action from [%s] handled successfully.', req.get('host')); + res.status(200).json(createUpdateResponse(req, res, result)); + } } - }); + ); } else { logger.error(context, 'Tried to handle an update request before the update handler was stablished.'); - var errorNotFound = new Error({ + const errorNotFound = new Error({ message: 'Update handler not found' }); next(errorNotFound); @@ -518,10 +522,10 @@ function handleUpdateNgsi1(req, res, next) { * @param {Array} attributes List of attributes to read. */ function defaultQueryHandlerNgsi1(id, type, service, subservice, attributes, callback) { - var contextElement = { - type: type, + const contextElement = { + type, isPattern: false, - id: id, + id, attributes: [] }; @@ -529,10 +533,10 @@ function defaultQueryHandlerNgsi1(id, type, service, subservice, attributes, cal if (error) { callback(error); } else { - for (var i = 0; i < attributes.length; i++) { - var lazyAttribute = _.findWhere(ngsiDevice.lazy, { name: attributes[i] }), - command = _.findWhere(ngsiDevice.commands, { name: attributes[i] }), - attributeType; + for (let i = 0; i < attributes.length; i++) { + const lazyAttribute = _.findWhere(ngsiDevice.lazy, { name: attributes[i] }); + const command = _.findWhere(ngsiDevice.commands, { name: attributes[i] }); + let attributeType; if (command) { attributeType = command.type; @@ -565,19 +569,19 @@ function defaultQueryHandlerNgsi1(id, type, service, subservice, attributes, cal * @param {Array} attributes List of attributes to read. */ function defaultQueryHandlerNgsi2(id, type, service, subservice, attributes, callback) { - var contextElement = { - type: type, - id: id + const contextElement = { + type, + id }; deviceService.getDeviceByName(id, service, subservice, function(error, ngsiDevice) { if (error) { callback(error); } else { - for (var i = 0; i < attributes.length; i++) { - var lazyAttribute = _.findWhere(ngsiDevice.lazy, { name: attributes[i] }), - command = _.findWhere(ngsiDevice.commands, { name: attributes[i] }), - attributeType; + for (let i = 0; i < attributes.length; i++) { + const lazyAttribute = _.findWhere(ngsiDevice.lazy, { name: attributes[i] }); + const command = _.findWhere(ngsiDevice.commands, { name: attributes[i] }); + let attributeType; if (command) { attributeType = command.type; @@ -609,13 +613,12 @@ function handleQueryNgsi1(req, res, next) { } function addStaticAttributes(attributes, device, contextElement, callback) { - function inAttributes(item) { return item.name && attributes.indexOf(item.name) >= 0; } if (device.staticAttributes) { - var selectedAttributes = device.staticAttributes.filter(inAttributes); + const selectedAttributes = device.staticAttributes.filter(inAttributes); if (selectedAttributes.length > 0) { if (contextElement.attributes) { @@ -637,13 +640,14 @@ function handleQueryNgsi1(req, res, next) { logger.debug(context, 'Handling stored set of attributes: %j', attributes); callback(null, device.lazy.map(getName)); } else { - logger.debug(context, 'Couldn\'t find any attributes. Handling with null reference'); + logger.debug(context, "Couldn't find any attributes. Handling with null reference"); + callback(null, null); } } function createQueryRequests(attributes, contextEntity, callback) { - var actualHandler; + let actualHandler; if (queryHandler) { actualHandler = queryHandler; @@ -651,39 +655,33 @@ function handleQueryNgsi1(req, res, next) { actualHandler = defaultQueryHandlerNgsi1; } - async.waterfall([ - apply( - deviceService.getDeviceByName, - contextEntity.id, - req.headers['fiware-service'], - req.headers['fiware-servicepath']), - deviceService.findConfigurationGroup - ], function handleFindDevice(error, device) { - var executeCompleteAttributes = apply( - completeAttributes, - attributes, - device + async.waterfall( + [ + apply( + deviceService.getDeviceByName, + contextEntity.id, + req.headers['fiware-service'], + req.headers['fiware-servicepath'] ), - executeQueryHandler = apply( + deviceService.findConfigurationGroup + ], + function handleFindDevice(error, device) { + const executeCompleteAttributes = apply(completeAttributes, attributes, device); + const executeQueryHandler = apply( actualHandler, contextEntity.id, contextEntity.type, req.headers['fiware-service'], req.headers['fiware-servicepath'] - ), - executeAddStaticAttributes = apply( - addStaticAttributes, - attributes, - device ); + const executeAddStaticAttributes = apply(addStaticAttributes, attributes, device); - callback(error, apply(async.waterfall, [ - executeCompleteAttributes, - executeQueryHandler, - executeAddStaticAttributes - ])); - }); - + callback( + error, + apply(async.waterfall, [executeCompleteAttributes, executeQueryHandler, executeAddStaticAttributes]) + ); + } + ); } function handleQueryContextRequests(error, result) { @@ -698,10 +696,10 @@ function handleQueryNgsi1(req, res, next) { logger.debug(context, 'Handling query from [%s]', req.get('host')); - async.waterfall([ - apply(async.map, req.body.entities, apply(createQueryRequests, req.body.attributes)), - async.series - ], handleQueryContextRequests); + async.waterfall( + [apply(async.map, req.body.entities, apply(createQueryRequests, req.body.attributes)), async.series], + handleQueryContextRequests + ); } /** @@ -713,25 +711,22 @@ function handleQueryNgsi2(req, res, next) { } function addStaticAttributes(attributes, device, contextElement, callback) { - function inAttributes(item) { return item.name && attributes.indexOf(item.name) >= 0; } if (device.staticAttributes) { - - var selectedAttributes = []; + let selectedAttributes = []; if (attributes === undefined || attributes.length === 0) { selectedAttributes = device.staticAttributes; - } - else { + } else { selectedAttributes = device.staticAttributes.filter(inAttributes); } - for (var att in selectedAttributes) { + for (const att in selectedAttributes) { contextElement[selectedAttributes[att].name] = { - 'type' : selectedAttributes[att].type, - 'value' : selectedAttributes[att].value + type: selectedAttributes[att].type, + value: selectedAttributes[att].value }; } } @@ -745,55 +740,44 @@ function handleQueryNgsi2(req, res, next) { callback(null, attributes); } else if (device.lazy) { logger.debug(context, 'Handling stored set of attributes: %j', attributes); - var results = device.lazy.map(getName); + const results = device.lazy.map(getName); callback(null, results); } else { - logger.debug(context, 'Couldn\'t find any attributes. Handling with null reference'); + logger.debug(context, "Couldn't find any attributes. Handling with null reference"); + callback(null, null); } } function finishQueryForDevice(attributes, contextEntity, actualHandler, device, callback) { - var contextId = contextEntity.id; - var contextType = contextEntity.type; - if(!contextId) { + let contextId = contextEntity.id; + let contextType = contextEntity.type; + if (!contextId) { contextId = device.id; } - if(!contextType) { + if (!contextType) { contextType = device.type; } deviceService.findConfigurationGroup(device, function(error, group) { - var executeCompleteAttributes = apply( - completeAttributes, - attributes, - group - ), - executeQueryHandler = apply( - actualHandler, - contextId, - contextType, - req.headers['fiware-service'], - req.headers['fiware-servicepath'] - ), - executeAddStaticAttributes = apply( - addStaticAttributes, - attributes, - group - ); + const executeCompleteAttributes = apply(completeAttributes, attributes, group); + const executeQueryHandler = apply( + actualHandler, + contextId, + contextType, + req.headers['fiware-service'], + req.headers['fiware-servicepath'] + ); + const executeAddStaticAttributes = apply(addStaticAttributes, attributes, group); - async.waterfall([ - executeCompleteAttributes, - executeQueryHandler, - executeAddStaticAttributes - ], callback); - }); + async.waterfall([executeCompleteAttributes, executeQueryHandler, executeAddStaticAttributes], callback); + }); } function createQueryRequest(attributes, contextEntity, callback) { - var actualHandler; - var getFunction; + let actualHandler; + let getFunction; if (queryHandler) { actualHandler = queryHandler; @@ -806,7 +790,8 @@ function handleQueryNgsi2(req, res, next) { deviceService.getDeviceByName, contextEntity.id, req.headers['fiware-service'], - req.headers['fiware-servicepath']); + req.headers['fiware-servicepath'] + ); } else { getFunction = apply( deviceService.listDevicesWithType, @@ -814,7 +799,8 @@ function handleQueryNgsi2(req, res, next) { req.headers['fiware-service'], req.headers['fiware-servicepath'], null, - null); + null + ); } getFunction(function handleFindDevice(error, innerDevice) { @@ -823,31 +809,30 @@ function handleQueryNgsi2(req, res, next) { return callback(new errors.DeviceNotFound(contextEntity.id)); } - if(innerDevice.count) { + if (innerDevice.count) { if (innerDevice.count === 0) { return callback(null, []); - } else { - deviceList = innerDevice.devices; } + deviceList = innerDevice.devices; } else { deviceList = [innerDevice]; } - async.map(deviceList, async.apply( - finishQueryForDevice, attributes, contextEntity, actualHandler), function (error, results) { + async.map(deviceList, async.apply(finishQueryForDevice, attributes, contextEntity, actualHandler), function( + error, + results + ) { if (error) { callback(error); - } - else if(innerDevice.count) { - callback(null,results); - } else if(Array.isArray(results) && results.length > 0){ + } else if (innerDevice.count) { + callback(null, results); + } else if (Array.isArray(results) && results.length > 0) { callback(null, results); } else { callback(null, results); } }); }); - } function handleQueryContextRequests(error, result) { @@ -861,33 +846,31 @@ function handleQueryNgsi2(req, res, next) { } logger.debug(context, 'Handling query from [%s]', req.get('host')); - var contextEntity = {}; + const contextEntity = {}; // At the present moment, IOTA supports query request with one entity and without patterns. This is aligned // with the utilization cases in combination with ContextBroker. Other cases are returned as error - if (req.body.entities.length !== 1) - { - logger.warn('queries with entities number different to 1 are not supported (%d found)', - req.body.entities.length); - handleQueryContextRequests({code: 400, name: 'BadRequest', message: 'more than one entity in query'}); + if (req.body.entities.length !== 1) { + logger.warn( + 'queries with entities number different to 1 are not supported (%d found)', + req.body.entities.length + ); + handleQueryContextRequests({ code: 400, name: 'BadRequest', message: 'more than one entity in query' }); return; } - if (req.body.entities[0].idPattern) - { + if (req.body.entities[0].idPattern) { logger.warn('queries with idPattern are not supported'); - handleQueryContextRequests({code: 400, name: 'BadRequest', message: 'idPattern usage in query'}); + handleQueryContextRequests({ code: 400, name: 'BadRequest', message: 'idPattern usage in query' }); return; } contextEntity.id = req.body.entities[0].id; contextEntity.type = req.body.entities[0].type; - var queryAtts = req.body.attrs; + const queryAtts = req.body.attrs; createQueryRequest(queryAtts, contextEntity, handleQueryContextRequests); - } function handleNotificationNgsi1(req, res, next) { - function checkStatus(statusCode, callback) { if (statusCode.code && statusCode.code === '200') { callback(); @@ -907,15 +890,16 @@ function handleNotificationNgsi1(req, res, next) { } else { callback(null, device, contextResponse.contextElement.attributes); } - }); + } + ); } function applyNotificationMiddlewares(device, values, callback) { if (notificationMiddlewares.length > 0) { - var firstMiddleware = notificationMiddlewares.slice(0, 1)[0], - rest = notificationMiddlewares.slice(1), - startMiddleware = apply(firstMiddleware, device, values), - composedMiddlewares = [startMiddleware].concat(rest); + const firstMiddleware = notificationMiddlewares.slice(0, 1)[0]; + const rest = notificationMiddlewares.slice(1); + const startMiddleware = apply(firstMiddleware, device, values); + const composedMiddlewares = [startMiddleware].concat(rest); async.waterfall(composedMiddlewares, callback); } else { @@ -924,12 +908,15 @@ function handleNotificationNgsi1(req, res, next) { } function createNotificationHandler(contextResponse, callback) { - async.waterfall([ - apply(checkStatus, contextResponse.statusCode), - apply(extractInformation, contextResponse), - applyNotificationMiddlewares, - notificationHandler - ], callback); + async.waterfall( + [ + apply(checkStatus, contextResponse.statusCode), + apply(extractInformation, contextResponse), + applyNotificationMiddlewares, + notificationHandler + ], + callback + ); } function handleNotificationRequests(error) { @@ -945,9 +932,8 @@ function handleNotificationNgsi1(req, res, next) { logger.debug(context, 'Handling notification from [%s]', req.get('host')); async.map(req.body.contextResponses, createNotificationHandler, handleNotificationRequests); - } else { - var errorNotFound = new Error({ + const errorNotFound = new Error({ message: 'Notification handler not found' }); @@ -959,11 +945,11 @@ function handleNotificationNgsi1(req, res, next) { function handleNotificationNgsi2(req, res, next) { function extractInformation(dataElement, callback) { - var atts = []; - for (var key in dataElement) { + const atts = []; + for (const key in dataElement) { if (dataElement.hasOwnProperty(key)) { if (key !== 'id' && key !== 'type') { - var att = {}; + const att = {}; att.type = dataElement[key].type; att.value = dataElement[key].value; att.name = key; @@ -981,15 +967,16 @@ function handleNotificationNgsi2(req, res, next) { } else { callback(null, device, atts); } - }); + } + ); } function applyNotificationMiddlewares(device, values, callback) { if (notificationMiddlewares.length > 0) { - var firstMiddleware = notificationMiddlewares.slice(0, 1)[0], - rest = notificationMiddlewares.slice(1), - startMiddleware = apply(firstMiddleware, device, values), - composedMiddlewares = [startMiddleware].concat(rest); + const firstMiddleware = notificationMiddlewares.slice(0, 1)[0]; + const rest = notificationMiddlewares.slice(1); + const startMiddleware = apply(firstMiddleware, device, values); + const composedMiddlewares = [startMiddleware].concat(rest); async.waterfall(composedMiddlewares, callback); } else { @@ -998,11 +985,10 @@ function handleNotificationNgsi2(req, res, next) { } function createNotificationHandler(contextResponse, callback) { - async.waterfall([ - apply(extractInformation, contextResponse), - applyNotificationMiddlewares, - notificationHandler - ], callback); + async.waterfall( + [apply(extractInformation, contextResponse), applyNotificationMiddlewares, notificationHandler], + callback + ); } function handleNotificationRequests(error) { @@ -1017,9 +1003,8 @@ function handleNotificationNgsi2(req, res, next) { if (notificationHandler) { logger.debug(context, 'Handling notification from [%s]', req.get('host')); async.map(req.body.data, createNotificationHandler, handleNotificationRequests); - } else { - var errorNotFound = new Error({ + const errorNotFound = new Error({ message: 'Notification handler not found' }); @@ -1027,7 +1012,6 @@ function handleNotificationNgsi2(req, res, next) { next(errorNotFound); } - } /** @@ -1087,7 +1071,7 @@ function setNotificationHandler(newHandler) { } function queryErrorHandlingNgsi1(error, req, res, next) { - var code = 500; + let code = 500; logger.debug(context, 'Query NGSIv1 error [%s] handling request: %s', error.name, error.message); @@ -1097,7 +1081,7 @@ function queryErrorHandlingNgsi1(error, req, res, next) { res.status(code).json({ errorCode: { - code: code, + code, reasonPhrase: error.name, details: error.message.replace(/[<>\"\'=;\(\)]/g, '') } @@ -1105,7 +1089,7 @@ function queryErrorHandlingNgsi1(error, req, res, next) { } function queryErrorHandlingNgsi2(error, req, res, next) { - var code = 500; + let code = 500; logger.debug(context, 'Query NGSIv2 error [%s] handling request: %s', error.name, error.message); @@ -1120,7 +1104,7 @@ function queryErrorHandlingNgsi2(error, req, res, next) { } function updateErrorHandlingNgsi1(error, req, res, next) { - var code = 500; + let code = 500; logger.debug(context, 'Update NGSIv1 error [%s] handing request: %s', error.name, error.message); @@ -1128,24 +1112,22 @@ function updateErrorHandlingNgsi1(error, req, res, next) { code = error.code; } - res.status(code).json( - { - contextResponses: [ - { - contextElement: req.body, - statusCode: { - code: code, - reasonPhrase: error.name, - details: error.message.replace(/[<>\"\'=;\(\)]/g, '') - } + res.status(code).json({ + contextResponses: [ + { + contextElement: req.body, + statusCode: { + code, + reasonPhrase: error.name, + details: error.message.replace(/[<>\"\'=;\(\)]/g, '') } - ] - } - ); + } + ] + }); } function updateErrorHandlingNgsi2(error, req, res, next) { - var code = 500; + let code = 500; logger.debug(context, 'Update NGSIv2 error [%s] handing request: %s', error.name, error.message); @@ -1166,51 +1148,34 @@ function updateErrorHandlingNgsi2(error, req, res, next) { */ function loadContextRoutes(router) { //TODO: remove '//' paths when the appropriate patch comes to Orion - var updateMiddlewaresNgsi1 = [ - middlewares.ensureType, - middlewares.validateJson(updateContextTemplateNgsi1), - handleUpdateNgsi1, - updateErrorHandlingNgsi1 - ], - updateMiddlewaresNgsi2 = [ - middlewares.ensureType, - middlewares.validateJson(updateContextTemplateNgsi2), - handleUpdateNgsi2, - updateErrorHandlingNgsi2 - ], - queryMiddlewaresNgsi1 = [ - middlewares.ensureType, - middlewares.validateJson(queryContextTemplate), - handleQueryNgsi1, - queryErrorHandlingNgsi1 - ], - queryMiddlewaresNgsi2 = [ - handleQueryNgsi2, - queryErrorHandlingNgsi2 - ], - updatePathsNgsi1 = [ - '/v1/updateContext', - '/NGSI10/updateContext', - '//updateContext' - ], - updatePathsNgsi2 = [ - '/v2/op/update', - '//op/update' - ], - queryPathsNgsi1 = [ - '/v1/queryContext', - '/NGSI10/queryContext', - '//queryContext' - ], - queryPathsNgsi2 = [ - '/v2/op/query', - '//op/query' - ]; - // In a more evolved implementation, more endpoints could be added to queryPathsNgsi2 - // according to http://fiware.github.io/specifications/ngsiv2/stable. + const updateMiddlewaresNgsi1 = [ + middlewares.ensureType, + middlewares.validateJson(updateContextTemplateNgsi1), + handleUpdateNgsi1, + updateErrorHandlingNgsi1 + ]; + const updateMiddlewaresNgsi2 = [ + middlewares.ensureType, + middlewares.validateJson(updateContextTemplateNgsi2), + handleUpdateNgsi2, + updateErrorHandlingNgsi2 + ]; + const queryMiddlewaresNgsi1 = [ + middlewares.ensureType, + middlewares.validateJson(queryContextTemplate), + handleQueryNgsi1, + queryErrorHandlingNgsi1 + ]; + const queryMiddlewaresNgsi2 = [handleQueryNgsi2, queryErrorHandlingNgsi2]; + const updatePathsNgsi1 = ['/v1/updateContext', '/NGSI10/updateContext', '//updateContext']; + const updatePathsNgsi2 = ['/v2/op/update', '//op/update']; + const queryPathsNgsi1 = ['/v1/queryContext', '/NGSI10/queryContext', '//queryContext']; + const queryPathsNgsi2 = ['/v2/op/query', '//op/query']; + // In a more evolved implementation, more endpoints could be added to queryPathsNgsi2 + // according to http://fiware.github.io/specifications/ngsiv2/stable. logger.info(context, 'Loading NGSI Contect server routes'); - var i; + let i; if (config.checkNgsi2()) { for (i = 0; i < updatePathsNgsi2.length; i++) { router.post(updatePathsNgsi2[i], updateMiddlewaresNgsi2); diff --git a/lib/services/northBound/deviceGroupAdministrationServer.js b/lib/services/northBound/deviceGroupAdministrationServer.js index 85801399e..aaf62961b 100644 --- a/lib/services/northBound/deviceGroupAdministrationServer.js +++ b/lib/services/northBound/deviceGroupAdministrationServer.js @@ -22,40 +22,36 @@ * * Modified by: Daniel Calvo - ATOS Research & Innovation */ -'use strict'; - -var restUtils = require('./restUtils'), - groupService = require('./../groups/groupService'), - async = require('async'), - apply = async.apply, - templateGroup = require('../../templates/deviceGroup.json'), - configurationHandler, - removeConfigurationHandler, - configurationMiddleware = [], - _ = require('underscore'), - mandatoryHeaders = [ - 'fiware-service', - 'fiware-servicepath' - ], - mandatoryParameters = [ - 'resource', - 'apikey' - ], - apiToInternal = { - 'entity_type': 'type', - 'internal_attributes': 'internalAttributes', - 'static_attributes': 'staticAttributes' - }, - internalToApi = { - 'type': 'entity_type', - 'internalAttributes': 'internal_attributes', - 'staticAttributes': 'static_attributes' - }; + +/* eslint-disable no-prototype-builtins */ + +const restUtils = require('./restUtils'); +const groupService = require('./../groups/groupService'); +const async = require('async'); +const apply = async.apply; +const templateGroup = require('../../templates/deviceGroup.json'); +let configurationHandler; +let removeConfigurationHandler; +let configurationMiddleware = []; +const _ = require('underscore'); +const mandatoryHeaders = ['fiware-service', 'fiware-servicepath']; +const mandatoryParameters = ['resource', 'apikey']; + +const apiToInternal = { + entity_type: 'type', + internal_attributes: 'internalAttributes', + static_attributes: 'staticAttributes' +}; +const internalToApi = { + type: 'entity_type', + internalAttributes: 'internal_attributes', + staticAttributes: 'static_attributes' +}; function applyMap(translation, body) { - var newBody = _.clone(body); + const newBody = _.clone(body); - for (var i in newBody) { + for (const i in newBody) { if (newBody.hasOwnProperty(i) && translation[i]) { newBody[translation[i]] = newBody[i]; delete newBody[i]; @@ -82,7 +78,6 @@ function applyConfigurationHandler(newConfiguration, callback) { } } - /** * Apply the handler for configuration removal. * @@ -93,7 +88,7 @@ function applyRemoveConfigurationHandler(groupToDelete, callback) { removeConfigurationHandler(groupToDelete, callback); } else { callback(); - } + } } /** @@ -103,9 +98,9 @@ function applyRemoveConfigurationHandler(groupToDelete, callback) { */ function applyConfigurationMiddlewares(newConfiguration, callback) { if (configurationMiddleware.length > 0) { - var firstMiddleware = configurationMiddleware.slice(0, 1)[0], - rest = configurationMiddleware.slice(1), - executingMiddlewares = [apply(firstMiddleware, newConfiguration)]; + const firstMiddleware = configurationMiddleware.slice(0, 1)[0]; + const rest = configurationMiddleware.slice(1); + let executingMiddlewares = [apply(firstMiddleware, newConfiguration)]; executingMiddlewares = executingMiddlewares.concat(rest); @@ -115,7 +110,6 @@ function applyConfigurationMiddlewares(newConfiguration, callback) { } } - /** * Handle the device group creation requests, adding the header information to the device group body. * @@ -124,25 +118,26 @@ function applyConfigurationMiddlewares(newConfiguration, callback) { * @param {Function} next Invokes the next middleware in the chain. */ function handleCreateDeviceGroup(req, res, next) { - /*jshint sub:true */ - - for (var i = 0; i < req.body.services.length; i++) { + for (let i = 0; i < req.body.services.length; i++) { req.body.services[i] = applyMap(apiToInternal, req.body.services[i]); req.body.services[i].service = req.headers['fiware-service']; req.body.services[i].subservice = req.headers['fiware-servicepath']; } - async.series([ - apply(groupService.create, req.body), - apply(applyConfigurationMiddlewares, req.body), - apply(applyConfigurationHandler, req.body) - ], function(error) { - if (error) { - next(error); - } else { - res.status(201).send({}); + async.series( + [ + apply(groupService.create, req.body), + apply(applyConfigurationMiddlewares, req.body), + apply(applyConfigurationHandler, req.body) + ], + function(error) { + if (error) { + next(error); + } else { + res.status(201).send({}); + } } - }); + ); } /** @@ -155,11 +150,11 @@ function handleCreateDeviceGroup(req, res, next) { * @param {Function} next Invokes the next middleware in the chain. */ function handleListDeviceGroups(req, res, next) { - var listHandler = function(error, group) { + const listHandler = function(error, group) { if (error) { next(error); } else { - var translatedGroup = _.clone(group); + let translatedGroup = _.clone(group); if (group.services) { translatedGroup.services = group.services.map(applyMap.bind(null, internalToApi)); @@ -172,11 +167,7 @@ function handleListDeviceGroups(req, res, next) { }; if (req.headers['fiware-servicepath'] === '/*') { - groupService.list( - req.headers['fiware-service'], - req.query.limit, - req.query.offset, - listHandler); + groupService.list(req.headers['fiware-service'], req.query.limit, req.query.offset, listHandler); } else { groupService.find(req.headers['fiware-service'], req.headers['fiware-servicepath'], null, listHandler); } @@ -190,7 +181,6 @@ function handleListDeviceGroups(req, res, next) { * @param {Function} next Invokes the next middleware in the chain. */ function handleModifyDeviceGroups(req, res, next) { - /*jshint sub:true */ req.body = applyMap(apiToInternal, req.body); function addInformation(group, callback) { @@ -201,18 +191,27 @@ function handleModifyDeviceGroups(req, res, next) { callback(null, group); } - async.series([ - apply(groupService.update, req.headers['fiware-service'], req.headers['fiware-servicepath'], - req.query.resource, req.query.apikey, req.body), - apply(addInformation, req.body), - apply(applyConfigurationHandler, req.body) - ], function(error) { - if (error) { - next(error); - } else { - res.status(204).send({}); + async.series( + [ + apply( + groupService.update, + req.headers['fiware-service'], + req.headers['fiware-servicepath'], + req.query.resource, + req.query.apikey, + req.body + ), + apply(addInformation, req.body), + apply(applyConfigurationHandler, req.body) + ], + function(error) { + if (error) { + next(error); + } else { + res.status(204).send({}); + } } - }); + ); } /** @@ -224,38 +223,39 @@ function handleModifyDeviceGroups(req, res, next) { */ function handleDeleteDeviceGroups(req, res, next) { - - function getGroup (req, callback) { - groupService.get(req.query.resource, req.query.apikey, function (error, group){ + function getGroup(req, callback) { + groupService.get(req.query.resource, req.query.apikey, function(error, group) { if (error) { callback(error); - } else{ + } else { callback(null, group); - } + } }); } - function deleteGroup (req, groupToDelete, callback) { - groupService.remove(req.headers['fiware-service'], req.headers['fiware-servicepath'], - req.query.resource, req.query.apikey, req.query.device, function (error){ - if (error) { - callback(error); - } else{ - callback(null, groupToDelete); + function deleteGroup(req, groupToDelete, callback) { + groupService.remove( + req.headers['fiware-service'], + req.headers['fiware-servicepath'], + req.query.resource, + req.query.apikey, + req.query.device, + function(error) { + if (error) { + callback(error); + } else { + callback(null, groupToDelete); + } } - }); + ); } - async.waterfall([ - apply(getGroup, req), - apply(deleteGroup, req), - applyRemoveConfigurationHandler], - function(error) { - if (error) { - next(error); - } else { - res.status(204).send({}); - } - }); + async.waterfall([apply(getGroup, req), apply(deleteGroup, req), applyRemoveConfigurationHandler], function(error) { + if (error) { + next(error); + } else { + res.status(204).send({}); + } + }); } /** @@ -264,24 +264,28 @@ function handleDeleteDeviceGroups(req, res, next) { * @param {Object} router Express request router object. */ function loadContextRoutes(router) { - router.post('/iot/services', + router.post( + '/iot/services', restUtils.checkRequestAttributes('headers', mandatoryHeaders), restUtils.checkBody(templateGroup), - handleCreateDeviceGroup); + handleCreateDeviceGroup + ); - router.get('/iot/services', - restUtils.checkRequestAttributes('headers', mandatoryHeaders), - handleListDeviceGroups); + router.get('/iot/services', restUtils.checkRequestAttributes('headers', mandatoryHeaders), handleListDeviceGroups); - router.put('/iot/services', + router.put( + '/iot/services', restUtils.checkRequestAttributes('headers', mandatoryHeaders), restUtils.checkRequestAttributes('query', mandatoryParameters), - handleModifyDeviceGroups); + handleModifyDeviceGroups + ); - router.delete('/iot/services', + router.delete( + '/iot/services', restUtils.checkRequestAttributes('headers', mandatoryHeaders), restUtils.checkRequestAttributes('query', mandatoryParameters), - handleDeleteDeviceGroups); + handleDeleteDeviceGroups + ); } function setConfigurationHandler(newHandler) { diff --git a/lib/services/northBound/deviceProvisioningServer.js b/lib/services/northBound/deviceProvisioningServer.js index 751fc7557..34241602a 100644 --- a/lib/services/northBound/deviceProvisioningServer.js +++ b/lib/services/northBound/deviceProvisioningServer.js @@ -20,56 +20,50 @@ * For those usages not covered by the GNU Affero General Public License * please contact with::daniel.moranjimenez@telefonica.com */ -'use strict'; - -var async = require('async'), - restUtils = require('./restUtils'), - statsRegistry = require('./../stats/statsRegistry'), - deviceService = require('./../devices/deviceService'), - intoTrans = require('../common/domain').intoTrans, - logger = require('logops'), - errors = require('../../errors'), - _ = require('underscore'), - context = { - op: 'IoTAgentNGSI.DeviceProvisioning' - }, - apply = async.apply, - provisioningHandler, - removeDeviceHandler, - updateDeviceTemplate = require('../../templates/updateDevice.json'), - createDeviceTemplate = require('../../templates/createDevice.json'), - mandatoryHeaders = [ - 'fiware-service', - 'fiware-servicepath' - ], - provisioningMiddlewares = [], - provisioningAPITranslation = { - /* jshint camelcase:false */ - - name: 'id', - service: 'service', - service_path: 'subservice', - entity_name: 'name', - entity_type: 'type', - timezone: 'timezone', - timestamp: 'timestamp', - protocol: 'protocol', - transport: 'transport', - endpoint: 'endpoint', - attributes: 'active', - commands: 'commands', - lazy: 'lazy', - internal_attributes: 'internalAttributes', - static_attributes: 'staticAttributes', - autoprovision: 'autoprovision' - }; + +const async = require('async'); +const restUtils = require('./restUtils'); +const statsRegistry = require('./../stats/statsRegistry'); +const deviceService = require('./../devices/deviceService'); +const intoTrans = require('../common/domain').intoTrans; +const logger = require('logops'); +const errors = require('../../errors'); +const _ = require('underscore'); +const context = { + op: 'IoTAgentNGSI.DeviceProvisioning' +}; +const apply = async.apply; +let provisioningHandler; +let removeDeviceHandler; +const updateDeviceTemplate = require('../../templates/updateDevice.json'); +const createDeviceTemplate = require('../../templates/createDevice.json'); +const mandatoryHeaders = ['fiware-service', 'fiware-servicepath']; +let provisioningMiddlewares = []; +const provisioningAPITranslation = { + name: 'id', + service: 'service', + service_path: 'subservice', + entity_name: 'name', + entity_type: 'type', + timezone: 'timezone', + timestamp: 'timestamp', + protocol: 'protocol', + transport: 'transport', + endpoint: 'endpoint', + attributes: 'active', + commands: 'commands', + lazy: 'lazy', + internal_attributes: 'internalAttributes', + static_attributes: 'staticAttributes', + autoprovision: 'autoprovision' +}; /** * Express middleware to handle incoming device provisioning requests. Every request is validated and handled to the * NGSI Service for the registration. */ function handleProvision(req, res, next) { - + /* eslint-disable-next-line no-unused-vars */ function handleProvisioningFinish(error, results) { if (error) { logger.debug(context, 'Device provisioning failed due to the following error: ', error.message); @@ -90,9 +84,9 @@ function handleProvision(req, res, next) { function applyProvisioningMiddlewares(device, callback) { if (provisioningMiddlewares.length > 0) { - var firstMiddleware = provisioningMiddlewares.slice(0, 1)[0], - rest = provisioningMiddlewares.slice(1), - executingMiddlewares = [apply(firstMiddleware, device)]; + const firstMiddleware = provisioningMiddlewares.slice(0, 1)[0]; + const rest = provisioningMiddlewares.slice(1); + let executingMiddlewares = [apply(firstMiddleware, device)]; executingMiddlewares = executingMiddlewares.concat(rest); @@ -103,40 +97,40 @@ function handleProvision(req, res, next) { } function fillDeviceData(service, subservice, body, callback) { - /* jshint sub: true */ - callback(null, { - id: body['device_id'], - apikey: body['apikey'], - type: body['entity_type'], - name: body['entity_name'], - service: service, - subservice: subservice, - active: body['attributes'], - staticAttributes: body['static_attributes'], - lazy: body['lazy'], - commands: body['commands'], - timezone: body['timezone'], - timestamp: body['timestamp'], - endpoint: body['endpoint'], - internalAttributes: body['internal_attributes'], - protocol: body['protocol'], - transport: body['transport'], + id: body.device_id, + apikey: body.apikey, + type: body.entity_type, + name: body.entity_name, + service, + subservice, + active: body.attributes, + staticAttributes: body.static_attributes, + lazy: body.lazy, + commands: body.commands, + timezone: body.timezone, + timestamp: body.timestamp, + endpoint: body.endpoint, + internalAttributes: body.internal_attributes, + protocol: body.protocol, + transport: body.transport, internalId: null, - autoprovision: body['autoprovision'] + autoprovision: body.autoprovision }); } function provisionSingleDevice(device, callback) { - async.waterfall([ - apply(statsRegistry.add, 'deviceCreationRequests', 1), - apply(restUtils.checkMandatoryQueryParams, - ['device_id'], device), - apply(fillDeviceData, req.headers['fiware-service'], req.headers['fiware-servicepath']), - applyProvisioningMiddlewares, - applyProvisioningHandler, - deviceService.register - ], callback); + async.waterfall( + [ + apply(statsRegistry.add, 'deviceCreationRequests', 1), + apply(restUtils.checkMandatoryQueryParams, ['device_id'], device), + apply(fillDeviceData, req.headers['fiware-service'], req.headers['fiware-servicepath']), + applyProvisioningMiddlewares, + applyProvisioningHandler, + deviceService.register + ], + callback + ); } function extractDevices() { @@ -172,7 +166,6 @@ function attributeToProvisioningAPIFormat(attribute) { * @return {Object} Device object translated to Device Provisioning API format. */ function toProvisioningAPIFormat(device) { - /* jshint camelcase:false */ return { device_id: device.id, service: device.service, @@ -183,9 +176,9 @@ function toProvisioningAPIFormat(device) { timestamp: device.timestamp, endpoint: device.endpoint, transport: device.transport, - attributes: (device.active) ? device.active.map(attributeToProvisioningAPIFormat) : undefined, - lazy: (device.lazy) ? device.lazy.map(attributeToProvisioningAPIFormat) : undefined, - commands: (device.commands) ? device.commands.map(attributeToProvisioningAPIFormat) : undefined, + attributes: device.active ? device.active.map(attributeToProvisioningAPIFormat) : undefined, + lazy: device.lazy ? device.lazy.map(attributeToProvisioningAPIFormat) : undefined, + commands: device.commands ? device.commands.map(attributeToProvisioningAPIFormat) : undefined, static_attributes: device.staticAttributes, internal_attributes: device.internalAttributes, protocol: device.protocol, @@ -206,12 +199,13 @@ function handleListDevices(req, res, next) { if (error) { next(error); } else { - var response = deviceList; + const response = deviceList; response.devices = deviceList.devices.map(toProvisioningAPIFormat); res.status(200).json(response); } - }); + } + ); } /** @@ -219,7 +213,10 @@ function handleListDevices(req, res, next) { * JSON format. */ function handleGetDevice(req, res, next) { - deviceService.getDevice(req.params.deviceId, req.headers['fiware-service'], req.headers['fiware-servicepath'], + deviceService.getDevice( + req.params.deviceId, + req.headers['fiware-service'], + req.headers['fiware-servicepath'], function(error, device) { if (error) { next(error); @@ -228,25 +225,24 @@ function handleGetDevice(req, res, next) { } else { next(new errors.DeviceNotFound(req.params.deviceId)); } - }); + } + ); } /** * This middleware handles the removal of a particular device specified with the deviceId. */ function handleRemoveDevice(req, res, next) { - - function getDevice(deviceId, service, subservice, callback){ - deviceService.getDevice(deviceId, service, subservice, - function(error, device) { - if (error) { - callback(error); - } else if (device) { - callback(null, device); - } else { - callback(new errors.DeviceNotFound(deviceId)); - } - }); + function getDevice(deviceId, service, subservice, callback) { + deviceService.getDevice(deviceId, service, subservice, function(error, device) { + if (error) { + callback(error); + } else if (device) { + callback(null, device); + } else { + callback(new errors.DeviceNotFound(deviceId)); + } + }); } function applyRemoveDeviceHandler(device, callback) { @@ -261,20 +257,28 @@ function handleRemoveDevice(req, res, next) { return deviceService.unregister(deviceId, service, subservice, callback); } - async.waterfall([ - apply(statsRegistry.add, 'deviceRemovalRequests', 1), - apply(getDevice, req.params.deviceId, req.headers['fiware-service'], req.headers['fiware-servicepath']), - applyRemoveDeviceHandler, - apply(unregisterDevice, req.params.deviceId, - req.headers['fiware-service'], req.headers['fiware-servicepath'])], function (error) { - if (error && error.code !== 404) { - next(error); - } else if (error && error.code === 404) { - next(new errors.DeviceNotFound(req.params.deviceId)); - } else { - res.status(204).send(); + async.waterfall( + [ + apply(statsRegistry.add, 'deviceRemovalRequests', 1), + apply(getDevice, req.params.deviceId, req.headers['fiware-service'], req.headers['fiware-servicepath']), + applyRemoveDeviceHandler, + apply( + unregisterDevice, + req.params.deviceId, + req.headers['fiware-service'], + req.headers['fiware-servicepath'] + ) + ], + function(error) { + if (error && error.code !== 404) { + next(error); + } else if (error && error.code === 404) { + next(new errors.DeviceNotFound(req.params.deviceId)); + } else { + res.status(204).send(); + } } - }); + ); } /** @@ -282,17 +286,20 @@ function handleRemoveDevice(req, res, next) { */ function handleUpdateDevice(req, res, next) { if (req.body.deviceId) { - next(new errors.BadRequest('Can\'t change the ID of a preprovisioned device')); + next(new errors.BadRequest("Can't change the ID of a preprovisioned device")); } else { - deviceService.getDevice(req.params.deviceId, req.headers['fiware-service'], req.headers['fiware-servicepath'], + deviceService.getDevice( + req.params.deviceId, + req.headers['fiware-service'], + req.headers['fiware-servicepath'], function(error, device) { if (error) { next(error); } else if (device) { - var pairs = _.pairs(req.body), - newDevice = _.clone(device); + const pairs = _.pairs(req.body); + const newDevice = _.clone(device); - for (var i in pairs) { + for (const i in pairs) { newDevice[provisioningAPITranslation[pairs[i][0]]] = pairs[i][1]; } @@ -306,7 +313,8 @@ function handleUpdateDevice(req, res, next) { } else { next(new errors.DeviceNotFound(req.params.deviceId)); } - }); + } + ); } } @@ -316,29 +324,30 @@ function handleUpdateDevice(req, res, next) { * @param {Object} router Express request router object. */ function loadContextRoutes(router) { - router.post('/iot/devices', + router.post( + '/iot/devices', restUtils.checkRequestAttributes('headers', mandatoryHeaders), restUtils.checkBody(createDeviceTemplate), handleProvision ); - router.get('/iot/devices', - restUtils.checkRequestAttributes('headers', mandatoryHeaders), - handleListDevices - ); + router.get('/iot/devices', restUtils.checkRequestAttributes('headers', mandatoryHeaders), handleListDevices); - router.get('/iot/devices/:deviceId', + router.get( + '/iot/devices/:deviceId', restUtils.checkRequestAttributes('headers', mandatoryHeaders), handleGetDevice ); - router.put('/iot/devices/:deviceId', + router.put( + '/iot/devices/:deviceId', restUtils.checkRequestAttributes('headers', mandatoryHeaders), restUtils.checkBody(updateDeviceTemplate), handleUpdateDevice ); - router.delete('/iot/devices/:deviceId', + router.delete( + '/iot/devices/:deviceId', restUtils.checkRequestAttributes('headers', mandatoryHeaders), handleRemoveDevice ); diff --git a/lib/services/northBound/northboundServer.js b/lib/services/northBound/northboundServer.js index f40bab39d..caef5b07d 100644 --- a/lib/services/northBound/northboundServer.js +++ b/lib/services/northBound/northboundServer.js @@ -20,28 +20,26 @@ * For those usages not covered by the GNU Affero General Public License * please contact with::daniel.moranjimenez@telefonica.com */ -'use strict'; - -var http = require('http'), - async = require('async'), - express = require('express'), - packageInformation = require('../../../package.json'), - northboundServer, - contextServer = require('./contextServer'), - domainUtils = require('../common/domain'), - middlewares = require('../common/genericMiddleware'), - intoTrans = domainUtils.intoTrans, - deviceProvisioning = require('./deviceProvisioningServer'), - groupProvisioning = require('./deviceGroupAdministrationServer'), - logger = require('logops'), - context = { - op: 'IoTAgentNGSI.NorthboundServer' - }, - bodyParser = require('body-parser'); + +const http = require('http'); +const async = require('async'); +const express = require('express'); +const packageInformation = require('../../../package.json'); +let northboundServer; +const contextServer = require('./contextServer'); +const domainUtils = require('../common/domain'); +const middlewares = require('../common/genericMiddleware'); +const intoTrans = domainUtils.intoTrans; +const deviceProvisioning = require('./deviceProvisioningServer'); +const groupProvisioning = require('./deviceGroupAdministrationServer'); +const logger = require('logops'); +const context = { + op: 'IoTAgentNGSI.NorthboundServer' +}; +const bodyParser = require('body-parser'); function start(config, callback) { - var baseRoot = '/', - iotaInformation; + let baseRoot = '/'; northboundServer = { server: null, @@ -65,10 +63,10 @@ function start(config, callback) { baseRoot = config.server.baseRoot; } - iotaInformation = { + const iotaInformation = { libVersion: packageInformation.version, port: config.server.port, - baseRoot: baseRoot + baseRoot }; if (config.iotaVersion) { @@ -105,11 +103,7 @@ function stop(callback) { } function clear(callback) { - async.series([ - deviceProvisioning.clear, - groupProvisioning.clear, - contextServer.clear - ], callback); + async.series([deviceProvisioning.clear, groupProvisioning.clear, contextServer.clear], callback); } exports.setUpdateHandler = intoTrans(context, contextServer.setUpdateHandler); @@ -117,7 +111,7 @@ exports.setQueryHandler = intoTrans(context, contextServer.setQueryHandler); exports.setCommandHandler = intoTrans(context, contextServer.setCommandHandler); exports.setNotificationHandler = intoTrans(context, contextServer.setNotificationHandler); exports.setConfigurationHandler = intoTrans(context, groupProvisioning.setConfigurationHandler); -exports.setRemoveConfigurationHandler = intoTrans (context, groupProvisioning.setRemoveConfigurationHandler); +exports.setRemoveConfigurationHandler = intoTrans(context, groupProvisioning.setRemoveConfigurationHandler); exports.setProvisioningHandler = intoTrans(context, deviceProvisioning.setProvisioningHandler); exports.setRemoveDeviceHandler = intoTrans(context, deviceProvisioning.setRemoveDeviceHandler); exports.addDeviceProvisionMiddleware = deviceProvisioning.addDeviceProvisionMiddleware; diff --git a/lib/services/northBound/restUtils.js b/lib/services/northBound/restUtils.js index 7bcbfd35a..4ccca70f0 100644 --- a/lib/services/northBound/restUtils.js +++ b/lib/services/northBound/restUtils.js @@ -22,18 +22,19 @@ * * Modified by: Daniel Calvo - ATOS Research & Innovation */ -'use strict'; - -var logger = require('logops'), - errors = require('../../errors'), - constants = require('../../constants'), - intoTrans = require('../common/domain').intoTrans, - revalidator = require('revalidator'), - moment = require('moment'), - context = { - op: 'IoTAgentNGSI.RestUtils' - }, - _ = require('underscore'); + +/* eslint-disable no-prototype-builtins */ + +const logger = require('logops'); +const errors = require('../../errors'); +const constants = require('../../constants'); +const intoTrans = require('../common/domain').intoTrans; +const revalidator = require('revalidator'); +const moment = require('moment'); +const context = { + op: 'IoTAgentNGSI.RestUtils' +}; +const _ = require('underscore'); /** * Checks all the mandatory attributes in the selected array are present in the presented body object. @@ -42,12 +43,12 @@ var logger = require('logops'), * @param {Object} body Body whose attributes are going to be checked. */ function checkMandatoryQueryParams(mandatoryAttributes, body, callback) { - var missing = []; + const missing = []; - for (var p in mandatoryAttributes) { - var found = false; + for (const p in mandatoryAttributes) { + let found = false; - for (var i in body) { + for (const i in body) { if (body.hasOwnProperty(i)) { if (i === mandatoryAttributes[p]) { found = true; @@ -61,7 +62,7 @@ function checkMandatoryQueryParams(mandatoryAttributes, body, callback) { } if (missing.length !== 0) { - var error = new errors.MissingAttributes('Missing attributes: ' + JSON.stringify(missing)); + const error = new errors.MissingAttributes('Missing attributes: ' + JSON.stringify(missing)); error.code = '400'; callback(error); @@ -81,10 +82,10 @@ function checkMandatoryQueryParams(mandatoryAttributes, body, callback) { */ function checkRequestAttributes(attribute, mandatoryAttributes) { return function headerChecker(req, res, next) { - var headerKeys = _.keys(req[attribute]), - missing = []; + const headerKeys = _.keys(req[attribute]); + const missing = []; - for (var i = 0; i < mandatoryAttributes.length; i++) { + for (let i = 0; i < mandatoryAttributes.length; i++) { if (headerKeys.indexOf(mandatoryAttributes[i]) < 0) { missing.push(mandatoryAttributes[i]); } @@ -106,7 +107,7 @@ function checkRequestAttributes(attribute, mandatoryAttributes) { */ function checkBody(template) { return function bodyMiddleware(req, res, next) { - var errorList = revalidator.validate(req.body, template); + const errorList = revalidator.validate(req.body, template); if (errorList.valid) { next(); @@ -124,9 +125,11 @@ function checkBody(template) { * @return {Boolean} true if timestamp attributes are valid ISO8601. false if not. */ function IsValidTimestamped(payload) { - for (var i in payload.contextElements[0].attributes) { - if (payload.contextElements[0].attributes[i].name === constants.TIMESTAMP_ATTRIBUTE && - ! moment(payload.contextElements[0].attributes[i].value, moment.ISO_8601).isValid()) { + for (const i in payload.contextElements[0].attributes) { + if ( + payload.contextElements[0].attributes[i].name === constants.TIMESTAMP_ATTRIBUTE && + !moment(payload.contextElements[0].attributes[i].value, moment.ISO_8601).isValid() + ) { return false; } } @@ -142,10 +145,9 @@ function IsValidTimestamped(payload) { */ function IsValidTimestampedNgsi2(payload) { function isValidTimestampedNgsi2Entity(entity) { - for (var i in entity) { + for (const i in entity) { if (entity.hasOwnProperty(i)) { - if (i === constants.TIMESTAMP_ATTRIBUTE && - ! moment(entity[i].value, moment.ISO_8601).isValid()) { + if (i === constants.TIMESTAMP_ATTRIBUTE && !moment(entity[i].value, moment.ISO_8601).isValid()) { return false; } } @@ -155,16 +157,15 @@ function IsValidTimestampedNgsi2(payload) { } if (payload instanceof Array) { - for (var i = 0; i < payload.length; i++) { + for (let i = 0; i < payload.length; i++) { if (!isValidTimestampedNgsi2Entity(payload[i])) { return false; } } return true; - } else { - return isValidTimestampedNgsi2Entity(payload); } + return isValidTimestampedNgsi2Entity(payload); } /** @@ -174,7 +175,7 @@ function IsValidTimestampedNgsi2(payload) { * @return {Boolean} true if timestamp attributes are included. false if not. */ function isTimestamped(payload) { - for (var i in payload.contextElements[0].attributes) { + for (const i in payload.contextElements[0].attributes) { if (payload.contextElements[0].attributes[i].name === constants.TIMESTAMP_ATTRIBUTE) { return true; } @@ -190,9 +191,8 @@ function isTimestamped(payload) { * @return {Boolean} true if timestamp attributes are included. false if not. */ function isTimestampedNgsi2(payload) { - function isTimestampedNgsi2Entity(entity) { - for (var i in entity) { + for (const i in entity) { if (entity.hasOwnProperty(i)) { if (i === constants.TIMESTAMP_ATTRIBUTE) { return true; @@ -204,16 +204,15 @@ function isTimestampedNgsi2(payload) { } if (payload instanceof Array) { - for (var i = 0; i < payload.length; i++) { + for (let i = 0; i < payload.length; i++) { if (!isTimestampedNgsi2Entity(payload[i])) { return false; } } return true; - } else { - return isTimestampedNgsi2Entity(payload); } + return isTimestampedNgsi2Entity(payload); } exports.checkMandatoryQueryParams = intoTrans(context, checkMandatoryQueryParams); diff --git a/lib/services/stats/statsRegistry.js b/lib/services/stats/statsRegistry.js index 7577692f2..6900c9940 100644 --- a/lib/services/stats/statsRegistry.js +++ b/lib/services/stats/statsRegistry.js @@ -20,21 +20,22 @@ * For those usages not covered by the GNU Affero General Public License * please contact with::daniel.moranjimenez@telefonica.com */ -'use strict'; - -var async = require('async'), - _ = require('underscore'), - apply = async.apply, - logger = require('logops'), - config = require('../../commonConfig'), - dbService = require('../../model/dbConn'), - globalStats = {}, - currentStats = {}, - timerActions = [], - timerHandler, - statsContext = { - op: 'IoTAgentNGSI.TimedStats' - }; + +/* eslint-disable no-prototype-builtins */ + +const async = require('async'); +const _ = require('underscore'); +const apply = async.apply; +const logger = require('logops'); +const config = require('../../commonConfig'); +const dbService = require('../../model/dbConn'); +let globalStats = {}; +let currentStats = {}; +let timerActions = []; +let timerHandler; +const statsContext = { + op: 'IoTAgentNGSI.TimedStats' +}; /** * Add a new stat value to the specified key of the stats registry. The stat is added @@ -100,7 +101,7 @@ function globalLoad(values, callback) { globalStats = values; currentStats = {}; - for (var i in values) { + for (const i in values) { if (values.hasOwnProperty(i)) { currentStats[i] = 0; } @@ -113,7 +114,7 @@ function globalLoad(values, callback) { * Reset each of the current stats to value zero. */ function resetCurrent(callback) { - for (var i in currentStats) { + for (const i in currentStats) { if (currentStats.hasOwnProperty(i)) { currentStats[i] = 0; } @@ -176,7 +177,7 @@ function logStats(currentValues, globalValues, callback) { * @param {Object} globalValues Global stat values. */ function mongodbPersistence(currentValues, globalValues, callback) { - var statStamp = _.clone(globalValues); + const statStamp = _.clone(globalValues); statStamp.timestamp = new Date().toISOString(); dbService.db.collection('kpis').insertOne(statStamp, callback); diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 000000000..5e09b5dcb --- /dev/null +++ b/package-lock.json @@ -0,0 +1,5117 @@ +{ + "name": "iotagent-node-lib", + "version": "2.11.0-next", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@babel/code-frame": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.5.5.tgz", + "integrity": "sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw==", + "dev": true, + "requires": { + "@babel/highlight": "^7.0.0" + } + }, + "@babel/highlight": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.5.0.tgz", + "integrity": "sha512-7dV4eu9gBxoM0dAnj/BCFDW9LFU0zvTrkq0ugM7pnHEgguOEeOz1so2ZghEdzviYzQEED0r4EAgpsBChKy1TRQ==", + "dev": true, + "requires": { + "chalk": "^2.0.0", + "esutils": "^2.0.2", + "js-tokens": "^4.0.0" + }, + "dependencies": { + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true + } + } + }, + "@samverschueren/stream-to-observable": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@samverschueren/stream-to-observable/-/stream-to-observable-0.3.0.tgz", + "integrity": "sha512-MI4Xx6LHs4Webyvi6EbspgyAb4D2Q2VtnCQ1blOJcoLS6mVa8lNN2rkIy1CVxfTUpoyIbCTkXES1rLXztFD1lg==", + "dev": true, + "requires": { + "any-observable": "^0.3.0" + } + }, + "JSONSelect": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/JSONSelect/-/JSONSelect-0.4.0.tgz", + "integrity": "sha1-oI7cxn6z/L6Z7WMIVTRKDPKCu40=" + }, + "JSV": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/JSV/-/JSV-4.0.2.tgz", + "integrity": "sha1-0Hf2glVx+CEy+d/67Vh7QCn+/1c=" + }, + "abbrev": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz", + "integrity": "sha1-kbR5JYinc4wl813W9jdSovh3YTU=", + "dev": true + }, + "accepts": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz", + "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=", + "requires": { + "mime-types": "~2.1.18", + "negotiator": "0.6.1" + } + }, + "acorn": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.0.tgz", + "integrity": "sha512-gac8OEcQ2Li1dxIEWGZzsp2BitJxwkwcOm0zHAJLcPJaVvm58FRnk6RkuLRpU1EujipU2ZFODv2P9DLMfnV8mw==", + "dev": true + }, + "acorn-jsx": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.1.0.tgz", + "integrity": "sha512-tMUqwBWfLFbJbizRmEcWSLw6HnFzfdJs2sOJEOwwtVPMoH/0Ay+E703oZz78VSXZiiDcZrQ5XKjPIUQixhmgVw==", + "dev": true + }, + "ajv": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.7.0.tgz", + "integrity": "sha512-RZXPviBTtfmtka9n9sy1N5M5b82CbxWIR6HIis4s3WQTXDJamc/0gpCWNGz6EWdWp4DOfjzJfhz/AS9zVPjjWg==", + "requires": { + "fast-deep-equal": "^2.0.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "amdefine": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", + "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", + "optional": true + }, + "ansi-colors": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.3.tgz", + "integrity": "sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw==", + "dev": true + }, + "ansi-escapes": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", + "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", + "dev": true + }, + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "any-observable": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/any-observable/-/any-observable-0.3.0.tgz", + "integrity": "sha512-/FQM1EDkTsf63Ub2C6O7GuYFDsSXUwsaZDurV0np41ocwq0jthUAYCmhBX9f+KwlaCgIuWyr/4WlUQUBfKfZog==", + "dev": true + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", + "dev": true + }, + "arr-union": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", + "dev": true + }, + "array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "asn1": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", + "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", + "requires": { + "safer-buffer": "~2.1.0" + } + }, + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" + }, + "assertion-error": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", + "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", + "dev": true + }, + "assign-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", + "dev": true + }, + "astral-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", + "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", + "dev": true + }, + "async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.2.tgz", + "integrity": "sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg==", + "requires": { + "lodash": "^4.17.11" + } + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + }, + "atob": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", + "dev": true + }, + "aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" + }, + "aws4": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", + "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==" + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "base": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", + "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "dev": true, + "requires": { + "cache-base": "^1.0.1", + "class-utils": "^0.3.5", + "component-emitter": "^1.2.1", + "define-property": "^1.0.0", + "isobject": "^3.0.1", + "mixin-deep": "^1.2.0", + "pascalcase": "^0.1.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "requires": { + "tweetnacl": "^0.14.3" + } + }, + "bluebird": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz", + "integrity": "sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA==" + }, + "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" + }, + "dependencies": { + "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" + } + }, + "mime-db": { + "version": "1.40.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz", + "integrity": "sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA==" + }, + "mime-types": { + "version": "2.1.24", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz", + "integrity": "sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==", + "requires": { + "mime-db": "1.40.0" + } + }, + "qs": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", + "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==" + }, + "setprototypeof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" + }, + "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" + } + } + } + }, + "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": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "browser-stdout": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", + "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", + "dev": true + }, + "bson": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/bson/-/bson-1.1.1.tgz", + "integrity": "sha512-jCGVYLoYMHDkOsbwJZBCqwMHyH4c+wzgI9hG7Z6SZJRXWr+x58pdIbm2i9a/jFGCkRJqRUr8eoI7lDWa0hTkxg==" + }, + "bytes": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", + "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==" + }, + "cache-base": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", + "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", + "dev": true, + "requires": { + "collection-visit": "^1.0.0", + "component-emitter": "^1.2.1", + "get-value": "^2.0.6", + "has-value": "^1.0.0", + "isobject": "^3.0.1", + "set-value": "^2.0.0", + "to-object-path": "^0.3.0", + "union-value": "^1.0.0", + "unset-value": "^1.0.0" + } + }, + "caller-callsite": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/caller-callsite/-/caller-callsite-2.0.0.tgz", + "integrity": "sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ=", + "dev": true, + "requires": { + "callsites": "^2.0.0" + } + }, + "caller-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-2.0.0.tgz", + "integrity": "sha1-Ro+DBE42mrIBD6xfBs7uFbsssfQ=", + "dev": true, + "requires": { + "caller-callsite": "^2.0.0" + } + }, + "callsites": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz", + "integrity": "sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA=", + "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 + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" + }, + "chai": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.2.0.tgz", + "integrity": "sha512-XQU3bhBukrOsQCuwZndwGcCVQHyZi53fQ6Ys1Fym7E4olpIqqZZhhoFJoaKVvV17lWQoXYwgWN2nF5crA8J2jw==", + "dev": true, + "requires": { + "assertion-error": "^1.1.0", + "check-error": "^1.0.2", + "deep-eql": "^3.0.1", + "get-func-name": "^2.0.0", + "pathval": "^1.1.0", + "type-detect": "^4.0.5" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "dependencies": { + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "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" + } + } + } + }, + "chardet": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", + "dev": true + }, + "check-error": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", + "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", + "dev": true + }, + "ci-info": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-1.6.0.tgz", + "integrity": "sha512-vsGdkwSCDpWmP80ncATX7iea5DWQemg1UgCW5J8tqjU3lYw4FBYuj89J0CTVomA7BEfvSZd84GmHko+MxFQU2A==", + "dev": true + }, + "cjson": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/cjson/-/cjson-0.3.0.tgz", + "integrity": "sha1-5kObkHA9MS/24iJAl76pLOPQKhQ=", + "requires": { + "jsonlint": "1.6.0" + } + }, + "class-utils": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", + "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", + "dev": true, + "requires": { + "arr-union": "^3.1.0", + "define-property": "^0.2.5", + "isobject": "^3.0.0", + "static-extend": "^0.1.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + } + } + }, + "cli-cursor": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", + "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", + "dev": true, + "requires": { + "restore-cursor": "^2.0.0" + } + }, + "cli-truncate": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-0.2.1.tgz", + "integrity": "sha1-nxXPuwcFAFNpIWxiasfQWrkN1XQ=", + "dev": true, + "requires": { + "slice-ansi": "0.0.4", + "string-width": "^1.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + } + } + }, + "cli-width": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", + "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=", + "dev": true + }, + "cliui": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", + "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", + "dev": true, + "requires": { + "string-width": "^2.1.1", + "strip-ansi": "^4.0.0", + "wrap-ansi": "^2.0.0" + } + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", + "dev": true + }, + "collection-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", + "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", + "dev": true, + "requires": { + "map-visit": "^1.0.0", + "object-visit": "^1.0.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "colors": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/colors/-/colors-0.5.1.tgz", + "integrity": "sha1-fQAj6usVTo7p/Oddy5I9DtFmd3Q=" + }, + "combined-stream": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz", + "integrity": "sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w==", + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "command-shell-lib": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/command-shell-lib/-/command-shell-lib-1.0.0.tgz", + "integrity": "sha1-KWC3MJvpBwojAYYjcvvjjtL3+RA=", + "requires": { + "async": "*" + } + }, + "commander": { + "version": "2.20.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.0.tgz", + "integrity": "sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==", + "dev": true + }, + "component-emitter": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", + "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", + "dev": true + }, + "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 + }, + "content-disposition": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", + "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ=" + }, + "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.3.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", + "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=" + }, + "cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" + }, + "copy-descriptor": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", + "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "cosmiconfig": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.1.tgz", + "integrity": "sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==", + "dev": true, + "requires": { + "import-fresh": "^2.0.0", + "is-directory": "^0.3.1", + "js-yaml": "^3.13.1", + "parse-json": "^4.0.0" + } + }, + "coveralls": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/coveralls/-/coveralls-3.0.3.tgz", + "integrity": "sha512-viNfeGlda2zJr8Gj1zqXpDMRjw9uM54p7wzZdvLRyOgnAfCe974Dq4veZkjJdxQXbmdppu6flEajFYseHYaUhg==", + "dev": true, + "requires": { + "growl": "~> 1.10.0", + "js-yaml": "^3.11.0", + "lcov-parse": "^0.0.10", + "log-driver": "^1.2.7", + "minimist": "^1.2.0", + "request": "^2.86.0" + } + }, + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "requires": { + "assert-plus": "^1.0.0" + } + }, + "date-fns": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-1.30.1.tgz", + "integrity": "sha512-hBSVCvSmWC+QypYObzwGOd9wqdDpOt+0wl0KbU+R+uuZBS1jN8VsD1ss3irQDknRj5NvxiTF6oj/nDRnN/UQNw==", + "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" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true + }, + "decode-uri-component": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=" + }, + "dedent": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", + "integrity": "sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw=", + "dev": true + }, + "deep-eql": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", + "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", + "dev": true, + "requires": { + "type-detect": "^4.0.0" + } + }, + "deep-equal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz", + "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=", + "dev": true + }, + "deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", + "dev": true + }, + "define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dev": true, + "requires": { + "object-keys": "^1.0.12" + } + }, + "define-property": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", + "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "dev": true, + "requires": { + "is-descriptor": "^1.0.2", + "isobject": "^3.0.1" + }, + "dependencies": { + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" + }, + "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": "3.5.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", + "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", + "dev": true + }, + "doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + }, + "dependencies": { + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true + } + } + }, + "ebnf-parser": { + "version": "0.1.10", + "resolved": "https://registry.npmjs.org/ebnf-parser/-/ebnf-parser-0.1.10.tgz", + "integrity": "sha1-zR9rpHfFY4xAyX7ZtXLbW6tdgzE=" + }, + "ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", + "requires": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + }, + "elegant-spinner": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/elegant-spinner/-/elegant-spinner-1.0.1.tgz", + "integrity": "sha1-2wQ1IcldfjA/2PNFvtwzSc+wcp4=", + "dev": true + }, + "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.1", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", + "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", + "dev": true, + "requires": { + "once": "^1.4.0" + } + }, + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "es-abstract": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.13.0.tgz", + "integrity": "sha512-vDZfg/ykNxQVwup/8E1BZhVzFfBxs9NqMzGcvIJrqg5k2/5Za2bWo40dK2J1pgLngZ7c+Shh8lwYtLGyrwPutg==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.0", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "is-callable": "^1.1.4", + "is-regex": "^1.0.4", + "object-keys": "^1.0.12" + } + }, + "es-to-primitive": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz", + "integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==", + "dev": true, + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "escodegen": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.3.3.tgz", + "integrity": "sha1-8CQBb1qI4Eb9EgBQVek5gC5sXyM=", + "requires": { + "esprima": "~1.1.1", + "estraverse": "~1.5.0", + "esutils": "~1.0.0", + "source-map": "~0.1.33" + } + }, + "eslint": { + "version": "5.16.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-5.16.0.tgz", + "integrity": "sha512-S3Rz11i7c8AA5JPv7xAH+dOyq/Cu/VXHiHXBPOU1k/JAM5dXqQPt3qcrhpHSorXmrpu2g0gkIBVXAqCpzfoZIg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "ajv": "^6.9.1", + "chalk": "^2.1.0", + "cross-spawn": "^6.0.5", + "debug": "^4.0.1", + "doctrine": "^3.0.0", + "eslint-scope": "^4.0.3", + "eslint-utils": "^1.3.1", + "eslint-visitor-keys": "^1.0.0", + "espree": "^5.0.1", + "esquery": "^1.0.1", + "esutils": "^2.0.2", + "file-entry-cache": "^5.0.1", + "functional-red-black-tree": "^1.0.1", + "glob": "^7.1.2", + "globals": "^11.7.0", + "ignore": "^4.0.6", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "inquirer": "^6.2.2", + "js-yaml": "^3.13.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.3.0", + "lodash": "^4.17.11", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.1", + "natural-compare": "^1.4.0", + "optionator": "^0.8.2", + "path-is-inside": "^1.0.2", + "progress": "^2.0.0", + "regexpp": "^2.0.1", + "semver": "^5.5.1", + "strip-ansi": "^4.0.0", + "strip-json-comments": "^2.0.1", + "table": "^5.2.3", + "text-table": "^0.2.0" + }, + "dependencies": { + "ajv": { + "version": "6.10.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz", + "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==", + "dev": true, + "requires": { + "fast-deep-equal": "^2.0.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true + }, + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "import-fresh": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.1.tgz", + "integrity": "sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ==", + "dev": true, + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true + }, + "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 + } + } + }, + "eslint-config-tamia": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/eslint-config-tamia/-/eslint-config-tamia-6.2.1.tgz", + "integrity": "sha512-DZgK/08P1OshIwEWBzpGzRFYTL8wDQcuyBKPy16xR6dT1gg4Dapf7/5vWj88djwpW5XrzTvXv2G1yrIfH1ygkQ==", + "dev": true + }, + "eslint-plugin-prettier": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-3.1.1.tgz", + "integrity": "sha512-A+TZuHZ0KU0cnn56/9mfR7/KjUJ9QNVXUhwvRFSR7PGPe0zQR6PTkmyqg1AtUUEOzTqeRsUwyKFh0oVZKVCrtA==", + "dev": true, + "requires": { + "prettier-linter-helpers": "^1.0.0" + } + }, + "eslint-scope": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", + "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==", + "dev": true, + "requires": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + }, + "dependencies": { + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true + } + } + }, + "eslint-utils": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.3.tgz", + "integrity": "sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^1.1.0" + } + }, + "eslint-visitor-keys": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz", + "integrity": "sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A==", + "dev": true + }, + "espree": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-5.0.1.tgz", + "integrity": "sha512-qWAZcWh4XE/RwzLJejfcofscgMc9CamR6Tn1+XRXNzrvUSSbiAjGOI/fggztjIi7y9VLPqnICMIPiGyr8JaZ0A==", + "dev": true, + "requires": { + "acorn": "^6.0.7", + "acorn-jsx": "^5.0.0", + "eslint-visitor-keys": "^1.0.0" + } + }, + "esprima": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-1.1.1.tgz", + "integrity": "sha1-W28VR/TRAuZw4UDFCb5ncdautUk=" + }, + "esquery": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.1.tgz", + "integrity": "sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA==", + "dev": true, + "requires": { + "estraverse": "^4.0.0" + }, + "dependencies": { + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true + } + } + }, + "esrecurse": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", + "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", + "dev": true, + "requires": { + "estraverse": "^4.1.0" + }, + "dependencies": { + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true + } + } + }, + "estraverse": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.5.1.tgz", + "integrity": "sha1-hno+jlip+EYYr7bC3bzZFrfLr3E=" + }, + "esutils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-1.0.0.tgz", + "integrity": "sha1-gVHTWOIMisx/t0XnRywAJf5JZXA=" + }, + "etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" + }, + "exec-sh": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/exec-sh/-/exec-sh-0.2.2.tgz", + "integrity": "sha512-FIUCJz1RbuS0FKTdaAafAByGS0CPvU3R0MeHxgtl+djzCc//F8HakL8GzmVNZanasTbTAY/3DRFA0KpVqj/eAw==", + "dev": true, + "requires": { + "merge": "^1.2.0" + } + }, + "execa": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", + "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", + "dev": true, + "requires": { + "cross-spawn": "^6.0.0", + "get-stream": "^4.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "express": { + "version": "4.16.4", + "resolved": "https://registry.npmjs.org/express/-/express-4.16.4.tgz", + "integrity": "sha512-j12Uuyb4FMrd/qQAm6uCHAkPtO8FDTRJZBDd5D2KOL2eLaz1yUNdUB/NOIyq0iU4q4cFarsUCrnFDPBcnksuOg==", + "requires": { + "accepts": "~1.3.5", + "array-flatten": "1.1.1", + "body-parser": "1.18.3", + "content-disposition": "0.5.2", + "content-type": "~1.0.4", + "cookie": "0.3.1", + "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.1", + "fresh": "0.5.2", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "~2.3.0", + "parseurl": "~1.3.2", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.4", + "qs": "6.5.2", + "range-parser": "~1.2.0", + "safe-buffer": "5.1.2", + "send": "0.16.2", + "serve-static": "1.13.2", + "setprototypeof": "1.1.0", + "statuses": "~1.4.0", + "type-is": "~1.6.16", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "dependencies": { + "body-parser": { + "version": "1.18.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.3.tgz", + "integrity": "sha1-WykhmP/dVTs6DyDe0FkrlWlVyLQ=", + "requires": { + "bytes": "3.0.0", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "~1.1.2", + "http-errors": "~1.6.3", + "iconv-lite": "0.4.23", + "on-finished": "~2.3.0", + "qs": "6.5.2", + "raw-body": "2.3.3", + "type-is": "~1.6.16" + } + }, + "bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=" + }, + "iconv-lite": { + "version": "0.4.23", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", + "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "raw-body": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.3.tgz", + "integrity": "sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw==", + "requires": { + "bytes": "3.0.0", + "http-errors": "1.6.3", + "iconv-lite": "0.4.23", + "unpipe": "1.0.0" + } + }, + "statuses": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", + "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==" + } + } + }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "requires": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, + "external-editor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", + "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", + "dev": true, + "requires": { + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" + }, + "fast-deep-equal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=" + }, + "fast-diff": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz", + "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==", + "dev": true + }, + "fast-json-stable-stringify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true + }, + "figures": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", + "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.5", + "object-assign": "^4.1.0" + } + }, + "file-entry-cache": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz", + "integrity": "sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==", + "dev": true, + "requires": { + "flat-cache": "^2.0.1" + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "finalhandler": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz", + "integrity": "sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg==", + "requires": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.2", + "statuses": "~1.4.0", + "unpipe": "~1.0.0" + }, + "dependencies": { + "statuses": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", + "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==" + } + } + }, + "find-parent-dir": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/find-parent-dir/-/find-parent-dir-0.3.0.tgz", + "integrity": "sha1-M8RLQpqysvBkYpnF+fcY83b/jVQ=", + "dev": true + }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "flat": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/flat/-/flat-4.1.0.tgz", + "integrity": "sha512-Px/TiLIznH7gEDlPXcUD4KnBusa6kR6ayRUVcnEAbreRIuhkqow/mun59BuRXwoYk7ZQOLW1ZM05ilIvK38hFw==", + "dev": true, + "requires": { + "is-buffer": "~2.0.3" + } + }, + "flat-cache": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz", + "integrity": "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==", + "dev": true, + "requires": { + "flatted": "^2.0.0", + "rimraf": "2.6.3", + "write": "1.0.3" + } + }, + "flatted": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.1.tgz", + "integrity": "sha512-a1hQMktqW9Nmqr5aktAux3JMNqaucxGcjtjWnZLHX7yyPCmlSV3M54nGYbqT8K+0GhF3NBgmJCc3ma+WOgX8Jg==", + "dev": true + }, + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", + "dev": true + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" + }, + "form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "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=" + }, + "fragment-cache": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", + "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", + "dev": true, + "requires": { + "map-cache": "^0.2.2" + } + }, + "fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", + "dev": true + }, + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true + }, + "get-func-name": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", + "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", + "dev": true + }, + "get-own-enumerable-property-symbols": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.0.tgz", + "integrity": "sha512-CIJYJC4GGF06TakLg8z4GQKvDsx9EMspVxOYih7LerEL/WosUnFIww45CGfxfeKHqlg3twgUrYRT1O3WQqjGCg==", + "dev": true + }, + "get-stdin": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-6.0.0.tgz", + "integrity": "sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g==", + "dev": 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" + } + }, + "get-value": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", + "dev": true + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "requires": { + "assert-plus": "^1.0.0" + } + }, + "glob": { + "version": "5.0.15", + "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", + "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", + "dev": true, + "requires": { + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "2 || 3", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true + }, + "growl": { + "version": "1.10.5", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", + "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", + "dev": true + }, + "handlebars": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.1.2.tgz", + "integrity": "sha512-nvfrjqvt9xQ8Z/w0ijewdD/vvWDTOweBUm96NTr66Wfvo1mJenBLwcYmPs3TIBP5ruzYGD7Hx/DaM9RmhroGPw==", + "dev": true, + "requires": { + "neo-async": "^2.6.0", + "optimist": "^0.6.1", + "source-map": "^0.6.1", + "uglify-js": "^3.1.4" + }, + "dependencies": { + "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 + } + } + }, + "har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" + }, + "har-validator": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", + "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", + "requires": { + "ajv": "^6.5.5", + "har-schema": "^2.0.0" + } + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + } + } + }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "dev": true + }, + "has-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz", + "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=", + "dev": true + }, + "has-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", + "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", + "dev": true, + "requires": { + "get-value": "^2.0.6", + "has-values": "^1.0.0", + "isobject": "^3.0.0" + } + }, + "has-values": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", + "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", + "dev": true, + "requires": { + "is-number": "^3.0.0", + "kind-of": "^4.0.0" + }, + "dependencies": { + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true + }, + "hosted-git-info": { + "version": "2.8.4", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.4.tgz", + "integrity": "sha512-pzXIvANXEFrc5oFFXRMkbLPQ2rXRoDERwDLyrcUxGhaZhgP54BBSl9Oheh7Vv0T090cszWBxPjkQQ5Sq1PbBRQ==", + "dev": true + }, + "http-errors": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" + } + }, + "http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "requires": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + } + }, + "husky": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/husky/-/husky-1.1.4.tgz", + "integrity": "sha512-cZjGpS7qsaBSo3fOMUuR7erQloX3l5XzL1v/RkIqU6zrQImDdU70z5Re9fGDp7+kbYlM2EtS4aYMlahBeiCUGw==", + "dev": true, + "requires": { + "cosmiconfig": "^5.0.6", + "execa": "^1.0.0", + "find-up": "^3.0.0", + "get-stdin": "^6.0.0", + "is-ci": "^1.2.1", + "pkg-dir": "^3.0.0", + "please-upgrade-node": "^3.1.1", + "read-pkg": "^4.0.1", + "run-node": "^1.0.0", + "slash": "^2.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": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true + }, + "import-fresh": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz", + "integrity": "sha1-2BNVwVYS04bGH53dOSLUMEgipUY=", + "dev": true, + "requires": { + "caller-path": "^2.0.0", + "resolve-from": "^3.0.0" + }, + "dependencies": { + "resolve-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", + "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", + "dev": true + } + } + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true + }, + "indent-string": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-3.2.0.tgz", + "integrity": "sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok=", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "inquirer": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.5.2.tgz", + "integrity": "sha512-cntlB5ghuB0iuO65Ovoi8ogLHiWGs/5yNrtUcKjFhSSiVeAIVpD7koaSU9RM8mpXw5YDi9RdYXGQMaOURB7ycQ==", + "dev": true, + "requires": { + "ansi-escapes": "^3.2.0", + "chalk": "^2.4.2", + "cli-cursor": "^2.1.0", + "cli-width": "^2.0.0", + "external-editor": "^3.0.3", + "figures": "^2.0.0", + "lodash": "^4.17.12", + "mute-stream": "0.0.7", + "run-async": "^2.2.0", + "rxjs": "^6.4.0", + "string-width": "^2.1.0", + "strip-ansi": "^5.1.0", + "through": "^2.3.6" + }, + "dependencies": { + "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 + }, + "figures": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", + "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.5" + } + }, + "lodash": { + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", + "dev": true + }, + "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" + } + } + } + }, + "invert-kv": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz", + "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==", + "dev": true + }, + "ipaddr.js": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.8.0.tgz", + "integrity": "sha1-6qM9bd16zo9/b+DJygRA5wZzix4=" + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, + "is-buffer": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.3.tgz", + "integrity": "sha512-U15Q7MXTuZlrbymiz95PJpZxu8IlipAp4dtS3wOdgPXx3mqBnslrWU14kxfHB+Py/+2PVKSr37dMAgM2A4uArw==", + "dev": true + }, + "is-callable": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz", + "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==", + "dev": true + }, + "is-ci": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-1.2.1.tgz", + "integrity": "sha512-s6tfsaQaQi3JNciBH6shVqEDvhGut0SUXr31ag8Pd8BBbVVlcGfWhpPmEOoM6RJ5TFhbypvf5yyRw/VXW1IiWg==", + "dev": true, + "requires": { + "ci-info": "^1.5.0" + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-date-object": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", + "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=", + "dev": true + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "is-directory": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz", + "integrity": "sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE=", + "dev": true + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true + }, + "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-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", + "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=", + "dev": true + }, + "is-observable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-observable/-/is-observable-1.1.0.tgz", + "integrity": "sha512-NqCa4Sa2d+u7BWc6CukaObG3Fh+CU9bvixbpcXYhy2VvYS7vVGIdAgnIS5Ks3A/cqk4rebLJ9s8zBstT2aKnIA==", + "dev": true, + "requires": { + "symbol-observable": "^1.1.0" + } + }, + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "requires": { + "isobject": "^3.0.1" + } + }, + "is-promise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", + "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", + "dev": true + }, + "is-regex": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", + "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", + "dev": true, + "requires": { + "has": "^1.0.1" + } + }, + "is-regexp": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz", + "integrity": "sha1-/S2INUXEa6xaYz57mgnof6LLUGk=", + "dev": true + }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "dev": true + }, + "is-symbol": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz", + "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==", + "dev": true, + "requires": { + "has-symbols": "^1.0.0" + } + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" + }, + "is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "dev": true + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" + }, + "istanbul": { + "version": "0.4.5", + "resolved": "https://registry.npmjs.org/istanbul/-/istanbul-0.4.5.tgz", + "integrity": "sha1-ZcfXPUxNqE1POsMQuRj7C4Azczs=", + "dev": true, + "requires": { + "abbrev": "1.0.x", + "async": "1.x", + "escodegen": "1.8.x", + "esprima": "2.7.x", + "glob": "^5.0.15", + "handlebars": "^4.0.1", + "js-yaml": "3.x", + "mkdirp": "0.5.x", + "nopt": "3.x", + "once": "1.x", + "resolve": "1.1.x", + "supports-color": "^3.1.0", + "which": "^1.1.1", + "wordwrap": "^1.0.0" + }, + "dependencies": { + "async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", + "dev": true + }, + "escodegen": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.8.1.tgz", + "integrity": "sha1-WltTr0aTEQvrsIZ6o0MN07cKEBg=", + "dev": true, + "requires": { + "esprima": "^2.7.1", + "estraverse": "^1.9.1", + "esutils": "^2.0.2", + "optionator": "^0.8.1", + "source-map": "~0.2.0" + } + }, + "esprima": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", + "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", + "dev": true + }, + "estraverse": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.3.tgz", + "integrity": "sha1-r2fy3JIlgkFZUJJgkaQAXSnJu0Q=", + "dev": true + }, + "esutils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", + "dev": true + }, + "source-map": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz", + "integrity": "sha1-2rc/vPwrqBm03gO9b26qSBZLP50=", + "dev": true, + "optional": true, + "requires": { + "amdefine": ">=0.0.4" + } + } + } + }, + "jest-get-type": { + "version": "22.4.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-22.4.3.tgz", + "integrity": "sha512-/jsz0Y+V29w1chdXVygEKSz2nBoHoYqNShPe+QgxSNjAuP1i8+k4LbQNrfoliKej0P45sivkSCh7yiD6ubHS3w==", + "dev": true + }, + "jest-validate": { + "version": "23.6.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-23.6.0.tgz", + "integrity": "sha512-OFKapYxe72yz7agrDAWi8v2WL8GIfVqcbKRCLbRG9PAxtzF9b1SEDdTpytNDN12z2fJynoBwpMpvj2R39plI2A==", + "dev": true, + "requires": { + "chalk": "^2.0.1", + "jest-get-type": "^22.1.0", + "leven": "^2.1.0", + "pretty-format": "^23.6.0" + } + }, + "jison": { + "version": "0.4.18", + "resolved": "https://registry.npmjs.org/jison/-/jison-0.4.18.tgz", + "integrity": "sha512-FKkCiJvozgC7VTHhMJ00a0/IApSxhlGsFIshLW6trWJ8ONX2TQJBBz6DlcO1Gffy4w9LT+uL+PA+CVnUSJMF7w==", + "requires": { + "JSONSelect": "0.4.0", + "cjson": "0.3.0", + "ebnf-parser": "0.1.10", + "escodegen": "1.3.x", + "esprima": "1.1.x", + "jison-lex": "0.3.x", + "lex-parser": "~0.1.3", + "nomnom": "1.5.2" + } + }, + "jison-lex": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/jison-lex/-/jison-lex-0.3.4.tgz", + "integrity": "sha1-gcoo2E+ESZ36jFlNzePYo/Jux6U=", + "requires": { + "lex-parser": "0.1.x", + "nomnom": "1.5.2" + } + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "js-yaml": { + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", + "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "dependencies": { + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true + } + } + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" + }, + "json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", + "dev": true + }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "dev": true + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" + }, + "jsonlint": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/jsonlint/-/jsonlint-1.6.0.tgz", + "integrity": "sha1-iKpGvCiaesk7tGyuLVihh6m7SUo=", + "requires": { + "JSV": ">= 4.0.x", + "nomnom": ">= 1.5.x" + } + }, + "jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "kareem": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/kareem/-/kareem-2.3.1.tgz", + "integrity": "sha512-l3hLhffs9zqoDe8zjmb/mAN4B8VT3L56EUvKNqLFVs9YlFA+zx7ke1DO8STAdDyYNkeSo1nKmjuvQeI12So8Xw==" + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + }, + "lcid": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz", + "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==", + "dev": true, + "requires": { + "invert-kv": "^2.0.0" + } + }, + "lcov-parse": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/lcov-parse/-/lcov-parse-0.0.10.tgz", + "integrity": "sha1-GwuP+ayceIklBYK3C3ExXZ2m2aM=", + "dev": true + }, + "leven": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz", + "integrity": "sha1-wuep93IJTe6dNCAq6KzORoeHVYA=", + "dev": true + }, + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "dev": true, + "requires": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + } + }, + "lex-parser": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/lex-parser/-/lex-parser-0.1.4.tgz", + "integrity": "sha1-ZMTwJfF/1Tv7RXY/rrFvAVp0dVA=" + }, + "lint-staged": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-7.3.0.tgz", + "integrity": "sha512-AXk40M9DAiPi7f4tdJggwuKIViUplYtVj1os1MVEteW7qOkU50EOehayCfO9TsoGK24o/EsWb41yrEgfJDDjCw==", + "dev": true, + "requires": { + "chalk": "^2.3.1", + "commander": "^2.14.1", + "cosmiconfig": "^5.0.2", + "debug": "^3.1.0", + "dedent": "^0.7.0", + "execa": "^0.9.0", + "find-parent-dir": "^0.3.0", + "is-glob": "^4.0.0", + "is-windows": "^1.0.2", + "jest-validate": "^23.5.0", + "listr": "^0.14.1", + "lodash": "^4.17.5", + "log-symbols": "^2.2.0", + "micromatch": "^3.1.8", + "npm-which": "^3.0.1", + "p-map": "^1.1.1", + "path-is-inside": "^1.0.2", + "pify": "^3.0.0", + "please-upgrade-node": "^3.0.2", + "staged-git-files": "1.1.1", + "string-argv": "^0.0.2", + "stringify-object": "^3.2.2" + }, + "dependencies": { + "cross-spawn": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", + "dev": true, + "requires": { + "lru-cache": "^4.0.1", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "execa": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.9.0.tgz", + "integrity": "sha512-BbUMBiX4hqiHZUA5+JujIjNb6TyAlp2D5KLheMjMluwOuzcnylDL4AxZYLLn1n2AGB49eSWwyKvvEQoRpnAtmA==", + "dev": true, + "requires": { + "cross-spawn": "^5.0.1", + "get-stream": "^3.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, + "get-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", + "dev": true + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, + "listr": { + "version": "0.14.3", + "resolved": "https://registry.npmjs.org/listr/-/listr-0.14.3.tgz", + "integrity": "sha512-RmAl7su35BFd/xoMamRjpIE4j3v+L28o8CT5YhAXQJm1fD+1l9ngXY8JAQRJ+tFK2i5njvi0iRUKV09vPwA0iA==", + "dev": true, + "requires": { + "@samverschueren/stream-to-observable": "^0.3.0", + "is-observable": "^1.1.0", + "is-promise": "^2.1.0", + "is-stream": "^1.1.0", + "listr-silent-renderer": "^1.1.1", + "listr-update-renderer": "^0.5.0", + "listr-verbose-renderer": "^0.5.0", + "p-map": "^2.0.0", + "rxjs": "^6.3.3" + }, + "dependencies": { + "p-map": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", + "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", + "dev": true + } + } + }, + "listr-silent-renderer": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/listr-silent-renderer/-/listr-silent-renderer-1.1.1.tgz", + "integrity": "sha1-kktaN1cVN3C/Go4/v3S4u/P5JC4=", + "dev": true + }, + "listr-update-renderer": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/listr-update-renderer/-/listr-update-renderer-0.5.0.tgz", + "integrity": "sha512-tKRsZpKz8GSGqoI/+caPmfrypiaq+OQCbd+CovEC24uk1h952lVj5sC7SqyFUm+OaJ5HN/a1YLt5cit2FMNsFA==", + "dev": true, + "requires": { + "chalk": "^1.1.3", + "cli-truncate": "^0.2.1", + "elegant-spinner": "^1.0.1", + "figures": "^1.7.0", + "indent-string": "^3.0.0", + "log-symbols": "^1.0.2", + "log-update": "^2.3.0", + "strip-ansi": "^3.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "log-symbols": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-1.0.2.tgz", + "integrity": "sha1-N2/3tY6jCGoPCfrMdGF+ylAeGhg=", + "dev": true, + "requires": { + "chalk": "^1.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "listr-verbose-renderer": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/listr-verbose-renderer/-/listr-verbose-renderer-0.5.0.tgz", + "integrity": "sha512-04PDPqSlsqIOaaaGZ+41vq5FejI9auqTInicFRndCBgE3bXG8D6W1I+mWhk+1nqbHmyhla/6BUrd5OSiHwKRXw==", + "dev": true, + "requires": { + "chalk": "^2.4.1", + "cli-cursor": "^2.1.0", + "date-fns": "^1.27.2", + "figures": "^2.0.0" + }, + "dependencies": { + "figures": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", + "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.5" + } + } + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "lodash": { + "version": "4.17.11", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", + "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==" + }, + "log-driver": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/log-driver/-/log-driver-1.2.7.tgz", + "integrity": "sha512-U7KCmLdqsGHBLeWqYlFA0V0Sl6P08EE1ZrmA9cxjUE0WVqT9qnyVDPz1kzpFEP0jdJuFnasWIfSd7fsaNXkpbg==", + "dev": true + }, + "log-symbols": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", + "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", + "dev": true, + "requires": { + "chalk": "^2.0.1" + } + }, + "log-update": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-2.3.0.tgz", + "integrity": "sha1-iDKP19HOeTiykoN0bwsbwSayRwg=", + "dev": true, + "requires": { + "ansi-escapes": "^3.0.0", + "cli-cursor": "^2.0.0", + "wrap-ansi": "^3.0.1" + }, + "dependencies": { + "wrap-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-3.0.1.tgz", + "integrity": "sha1-KIoE2H7aXChuBg3+jxNc6NAH+Lo=", + "dev": true, + "requires": { + "string-width": "^2.1.1", + "strip-ansi": "^4.0.0" + } + } + } + }, + "logops": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/logops/-/logops-2.1.0.tgz", + "integrity": "sha1-mHIkVNeHG9KqR2j7QWZvFCuVNc8=", + "requires": { + "colors": "^1.1.2", + "lodash": "^4.1.0", + "safe-json-stringify": "^1.0.4", + "serr": "^1.0.0" + }, + "dependencies": { + "colors": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.3.3.tgz", + "integrity": "sha512-mmGt/1pZqYRjMxB1axhTo16/snVZ5krrKkcmMeVKxzECMMXoCgnvTPp10QgHfcbQZw8Dq2jMNG6je4JlWU0gWg==" + } + } + }, + "lru-cache": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "dev": true, + "requires": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "map-age-cleaner": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz", + "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==", + "dev": true, + "requires": { + "p-defer": "^1.0.0" + } + }, + "map-cache": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", + "dev": true + }, + "map-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", + "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", + "dev": true, + "requires": { + "object-visit": "^1.0.0" + } + }, + "media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" + }, + "mem": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/mem/-/mem-4.3.0.tgz", + "integrity": "sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==", + "dev": true, + "requires": { + "map-age-cleaner": "^0.1.1", + "mimic-fn": "^2.0.0", + "p-is-promise": "^2.0.0" + } + }, + "memory-pager": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz", + "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==", + "optional": true + }, + "merge": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/merge/-/merge-1.2.1.tgz", + "integrity": "sha512-VjFo4P5Whtj4vsLzsYBu5ayHhoHJ0UqNm7ibvShmbmoz7tGi0vXaoJbGdB+GmDMLUdg8DpQXEIeVDAe8MaABvQ==", + "dev": true + }, + "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=" + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "mime": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz", + "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==" + }, + "mime-db": { + "version": "1.37.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.37.0.tgz", + "integrity": "sha512-R3C4db6bgQhlIhPU48fUtdVmKnflq+hRdad7IyKhtFj06VPNVdk2RhiYL3UjQIlso8L+YxAtFkobT0VK+S/ybg==" + }, + "mime-types": { + "version": "2.1.21", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.21.tgz", + "integrity": "sha512-3iL6DbwpyLzjR3xHSFNFeb9Nz/M8WDkX33t1GFQnFOllWk8pOrh/LSrB5OXlnlW5P9LH73X6loW/eogc+F5lJg==", + "requires": { + "mime-db": "~1.37.0" + } + }, + "mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "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.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, + "mixin-deep": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", + "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", + "dev": true, + "requires": { + "for-in": "^1.0.2", + "is-extendable": "^1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "dev": true, + "requires": { + "minimist": "0.0.8" + }, + "dependencies": { + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true + } + } + }, + "mocha": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-6.1.4.tgz", + "integrity": "sha512-PN8CIy4RXsIoxoFJzS4QNnCH4psUCPWc4/rPrst/ecSJJbLBkubMiyGCP2Kj/9YnWbotFqAoeXyXMucj7gwCFg==", + "dev": true, + "requires": { + "ansi-colors": "3.2.3", + "browser-stdout": "1.3.1", + "debug": "3.2.6", + "diff": "3.5.0", + "escape-string-regexp": "1.0.5", + "find-up": "3.0.0", + "glob": "7.1.3", + "growl": "1.10.5", + "he": "1.2.0", + "js-yaml": "3.13.1", + "log-symbols": "2.2.0", + "minimatch": "3.0.4", + "mkdirp": "0.5.1", + "ms": "2.1.1", + "node-environment-flags": "1.0.5", + "object.assign": "4.1.0", + "strip-json-comments": "2.0.1", + "supports-color": "6.0.0", + "which": "1.3.1", + "wide-align": "1.1.3", + "yargs": "13.2.2", + "yargs-parser": "13.0.0", + "yargs-unparser": "1.5.0" + }, + "dependencies": { + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "glob": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "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==", + "dev": true + }, + "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": "6.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.0.0.tgz", + "integrity": "sha512-on9Kwidc1IUQo+bQdhi8+Tijpo0e1SS6RoGo2guUwn5vdaxw8RXOF9Vb2ws+ihWOmh4JnCJOvaziZWP1VABaLg==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "moment": { + "version": "2.24.0", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.24.0.tgz", + "integrity": "sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg==" + }, + "moment-timezone": { + "version": "0.5.25", + "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.25.tgz", + "integrity": "sha512-DgEaTyN/z0HFaVcVbSyVCUU6HeFdnNC3vE4c9cgu2dgMTvjBUBdBzWfasTBmAW45u5OIMeCJtU8yNjM22DHucw==", + "requires": { + "moment": ">= 2.9.0" + } + }, + "mongodb": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.2.3.tgz", + "integrity": "sha512-jw8UyPsq4QleZ9z+t/pIVy3L++51vKdaJ2Q/XXeYxk/3cnKioAH8H6f5tkkDivrQL4PUgUOHe9uZzkpRFH1XtQ==", + "requires": { + "mongodb-core": "^3.2.3", + "safe-buffer": "^5.1.2" + } + }, + "mongodb-core": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/mongodb-core/-/mongodb-core-3.2.3.tgz", + "integrity": "sha512-UyI0rmvPPkjOJV8XGWa9VCTq7R4hBVipimhnAXeSXnuAPjuTqbyfA5Ec9RcYJ1Hhu+ISnc8bJ1KfGZd4ZkYARQ==", + "requires": { + "bson": "^1.1.1", + "require_optional": "^1.0.1", + "safe-buffer": "^5.1.2", + "saslprep": "^1.0.0" + } + }, + "mongoose": { + "version": "5.7.5", + "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-5.7.5.tgz", + "integrity": "sha512-BZ4FxtnbTurc/wcm/hLltLdI4IDxo4nsE0D9q58YymTdZwreNzwO62CcjVtaHhmr8HmJtOInp2W/T12FZaMf8g==", + "requires": { + "bson": "~1.1.1", + "kareem": "2.3.1", + "mongodb": "3.3.2", + "mongoose-legacy-pluralize": "1.0.2", + "mpath": "0.6.0", + "mquery": "3.2.2", + "ms": "2.1.2", + "regexp-clone": "1.0.0", + "safe-buffer": "5.1.2", + "sift": "7.0.1", + "sliced": "1.0.1" + }, + "dependencies": { + "mongodb": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.3.2.tgz", + "integrity": "sha512-fqJt3iywelk4yKu/lfwQg163Bjpo5zDKhXiohycvon4iQHbrfflSAz9AIlRE6496Pm/dQKQK5bMigdVo2s6gBg==", + "requires": { + "bson": "^1.1.1", + "require_optional": "^1.0.1", + "safe-buffer": "^5.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + } + } + }, + "mongoose-legacy-pluralize": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/mongoose-legacy-pluralize/-/mongoose-legacy-pluralize-1.0.2.tgz", + "integrity": "sha512-Yo/7qQU4/EyIS8YDFSeenIvXxZN+ld7YdV9LqFVQJzTLye8unujAWPZ4NWKfFA+RNjh+wvTWKY9Z3E5XM6ZZiQ==" + }, + "mpath": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.6.0.tgz", + "integrity": "sha512-i75qh79MJ5Xo/sbhxrDrPSEG0H/mr1kcZXJ8dH6URU5jD/knFxCVqVC/gVSW7GIXL/9hHWlT9haLbCXWOll3qw==" + }, + "mquery": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/mquery/-/mquery-3.2.2.tgz", + "integrity": "sha512-XB52992COp0KP230I3qloVUbkLUxJIu328HBP2t2EsxSFtf4W1HPSOBWOXf1bqxK4Xbb66lfMJ+Bpfd9/yZE1Q==", + "requires": { + "bluebird": "3.5.1", + "debug": "3.1.0", + "regexp-clone": "^1.0.0", + "safe-buffer": "5.1.2", + "sliced": "1.0.1" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "requires": { + "ms": "2.0.0" + } + } + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "mu2": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/mu2/-/mu2-0.5.21.tgz", + "integrity": "sha1-iIqPD9kOsc/anbgUdvbhmcyeWNM=" + }, + "mute-stream": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", + "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", + "dev": true + }, + "nanomatch": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", + "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "fragment-cache": "^0.2.1", + "is-windows": "^1.0.2", + "kind-of": "^6.0.2", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + } + }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "dev": true + }, + "negotiator": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", + "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=" + }, + "neo-async": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.0.tgz", + "integrity": "sha512-MFh0d/Wa7vkKO3Y3LlacqAEeHK0mckVqzDieUKTT+KGxi+zIpeVsFxymkIiRpbpDziHc290Xr9A1O4Om7otoRA==", + "dev": true + }, + "nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", + "dev": true + }, + "nock": { + "version": "10.0.6", + "resolved": "https://registry.npmjs.org/nock/-/nock-10.0.6.tgz", + "integrity": "sha512-b47OWj1qf/LqSQYnmokNWM8D88KvUl2y7jT0567NB3ZBAZFz2bWp2PC81Xn7u8F2/vJxzkzNZybnemeFa7AZ2w==", + "dev": true, + "requires": { + "chai": "^4.1.2", + "debug": "^4.1.0", + "deep-equal": "^1.0.0", + "json-stringify-safe": "^5.0.1", + "lodash": "^4.17.5", + "mkdirp": "^0.5.0", + "propagate": "^1.0.0", + "qs": "^6.5.1", + "semver": "^5.5.0" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "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==", + "dev": true + } + } + }, + "node-environment-flags": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/node-environment-flags/-/node-environment-flags-1.0.5.tgz", + "integrity": "sha512-VNYPRfGfmZLx0Ye20jWzHUjyTW/c+6Wq+iLhDzUI4XmhrDd9l/FozXV3F2xOaXjvp0co0+v1YSR3CMP6g+VvLQ==", + "dev": true, + "requires": { + "object.getownpropertydescriptors": "^2.0.3", + "semver": "^5.7.0" + } + }, + "nomnom": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/nomnom/-/nomnom-1.5.2.tgz", + "integrity": "sha1-9DRUSKhTz71cDSYyDyR3qwUm/i8=", + "requires": { + "colors": "0.5.x", + "underscore": "1.1.x" + }, + "dependencies": { + "underscore": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.1.7.tgz", + "integrity": "sha1-QLq4S60Z0jAJbo1u9ii/8FXYPbA=" + } + } + }, + "nopt": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", + "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", + "dev": true, + "requires": { + "abbrev": "1" + } + }, + "normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "requires": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + }, + "dependencies": { + "resolve": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.12.0.tgz", + "integrity": "sha512-B/dOmuoAik5bKcD6s6nXDCjzUKnaDvdkRyAk6rsmsKLipWj4797iothd7jmmUhWTfinVMU+wc56rYKsit2Qy4w==", + "dev": true, + "requires": { + "path-parse": "^1.0.6" + } + } + } + }, + "npm-path": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/npm-path/-/npm-path-2.0.4.tgz", + "integrity": "sha512-IFsj0R9C7ZdR5cP+ET342q77uSRdtWOlWpih5eC+lu29tIDbNEgDbzgVJ5UFvYHWhxDZ5TFkJafFioO0pPQjCw==", + "dev": true, + "requires": { + "which": "^1.2.10" + } + }, + "npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "dev": true, + "requires": { + "path-key": "^2.0.0" + } + }, + "npm-which": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/npm-which/-/npm-which-3.0.1.tgz", + "integrity": "sha1-kiXybsOihcIJyuZ8OxGmtKtxQKo=", + "dev": true, + "requires": { + "commander": "^2.9.0", + "npm-path": "^2.0.2", + "which": "^1.2.10" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "dev": true + }, + "oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + }, + "object-copy": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", + "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", + "dev": true, + "requires": { + "copy-descriptor": "^0.1.0", + "define-property": "^0.2.5", + "kind-of": "^3.0.3" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true + }, + "object-visit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", + "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", + "dev": true, + "requires": { + "isobject": "^3.0.0" + } + }, + "object.assign": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", + "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "function-bind": "^1.1.1", + "has-symbols": "^1.0.0", + "object-keys": "^1.0.11" + } + }, + "object.getownpropertydescriptors": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz", + "integrity": "sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY=", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "es-abstract": "^1.5.1" + } + }, + "object.pick": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", + "dev": true, + "requires": { + "isobject": "^3.0.1" + } + }, + "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" + } + }, + "onetime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", + "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", + "dev": true, + "requires": { + "mimic-fn": "^1.0.0" + }, + "dependencies": { + "mimic-fn": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", + "dev": true + } + } + }, + "optimist": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", + "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", + "dev": true, + "requires": { + "minimist": "~0.0.1", + "wordwrap": "~0.0.2" + }, + "dependencies": { + "minimist": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", + "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=", + "dev": true + }, + "wordwrap": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", + "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", + "dev": true + } + } + }, + "optionator": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", + "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", + "dev": true, + "requires": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.4", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "wordwrap": "~1.0.0" + } + }, + "os-locale": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz", + "integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==", + "dev": true, + "requires": { + "execa": "^1.0.0", + "lcid": "^2.0.0", + "mem": "^4.0.0" + } + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "dev": true + }, + "p-defer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz", + "integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=", + "dev": true + }, + "p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", + "dev": true + }, + "p-is-promise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-2.1.0.tgz", + "integrity": "sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg==", + "dev": true + }, + "p-limit": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.0.tgz", + "integrity": "sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-map": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-1.2.0.tgz", + "integrity": "sha512-r6zKACMNhjPJMTl8KcFH4li//gkrXWfbD6feV8l6doRHlzljFWGJ2AP6iKaCJXyZmAUMOPtvbW7EXkbWO/pLEA==", + "dev": true + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, + "parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "requires": { + "callsites": "^3.0.0" + }, + "dependencies": { + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true + } + } + }, + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "dev": true, + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + }, + "parseurl": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", + "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=" + }, + "pascalcase": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", + "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", + "dev": true + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", + "dev": true + }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "dev": true + }, + "path-parse": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", + "dev": true + }, + "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=" + }, + "pathval": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.0.tgz", + "integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA=", + "dev": true + }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + }, + "pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "dev": true, + "requires": { + "find-up": "^3.0.0" + } + }, + "please-upgrade-node": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/please-upgrade-node/-/please-upgrade-node-3.2.0.tgz", + "integrity": "sha512-gQR3WpIgNIKwBMVLkpMUeR3e1/E1y42bqDQZfql+kDeXd8COYfM8PQA4X6y7a8u9Ua9FHmsrrmirW2vHs45hWg==", + "dev": true, + "requires": { + "semver-compare": "^1.0.0" + } + }, + "posix-character-classes": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", + "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", + "dev": true + }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", + "dev": true + }, + "prettier": { + "version": "1.14.3", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.14.3.tgz", + "integrity": "sha512-qZDVnCrnpsRJJq5nSsiHCE3BYMED2OtsI+cmzIzF1QIfqm5ALf8tEJcO27zV1gKNKRPdhjO0dNWnrzssDQ1tFg==", + "dev": true + }, + "prettier-linter-helpers": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", + "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", + "dev": true, + "requires": { + "fast-diff": "^1.1.2" + } + }, + "pretty-format": { + "version": "23.6.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-23.6.0.tgz", + "integrity": "sha512-zf9NV1NSlDLDjycnwm6hpFATCGl/K1lt0R/GdkAK2O5LN/rwJoB+Mh93gGJjut4YbmecbfgLWVGSTCr0Ewvvbw==", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0", + "ansi-styles": "^3.2.0" + } + }, + "progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true + }, + "propagate": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/propagate/-/propagate-1.0.0.tgz", + "integrity": "sha1-AMLa7t2iDofjeCs0Stuhzd1q1wk=", + "dev": true + }, + "proxy-addr": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.4.tgz", + "integrity": "sha512-5erio2h9jp5CHGwcybmxmVqHmnCBZeewlfJ0pex+UW7Qny7OOZXTtH56TGNyBizkgiOwhJtMKrVzDTeKcySZwA==", + "requires": { + "forwarded": "~0.1.2", + "ipaddr.js": "1.8.0" + } + }, + "pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", + "dev": true + }, + "psl": { + "version": "1.1.31", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.31.tgz", + "integrity": "sha512-/6pt4+C+T+wZUieKR620OpzN/LlnNKuWjy1iFLQ/UG35JqHlR/89MP1d96dUfkf6Dne3TuLQzOYEYshJ+Hx8mw==" + }, + "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" + } + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" + }, + "qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" + }, + "query-string": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/query-string/-/query-string-6.5.0.tgz", + "integrity": "sha512-TYC4hDjZSvVxLMEucDMySkuAS9UIzSbAiYGyA9GWCjLKB8fQpviFbjd20fD7uejCDxZS+ftSdBKE6DS+xucJFg==", + "requires": { + "decode-uri-component": "^0.2.0", + "split-on-first": "^1.0.0", + "strict-uri-encode": "^2.0.0" + } + }, + "range-parser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", + "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=" + }, + "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" + }, + "dependencies": { + "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" + } + }, + "setprototypeof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" + } + } + }, + "read-pkg": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-4.0.1.tgz", + "integrity": "sha1-ljYlN48+HE1IyFhytabsfV0JMjc=", + "dev": true, + "requires": { + "normalize-package-data": "^2.3.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0" + } + }, + "regex-not": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", + "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", + "dev": true, + "requires": { + "extend-shallow": "^3.0.2", + "safe-regex": "^1.1.0" + } + }, + "regexp-clone": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/regexp-clone/-/regexp-clone-1.0.0.tgz", + "integrity": "sha512-TuAasHQNamyyJ2hb97IuBEif4qBHGjPHBS64sZwytpLEqtBQ1gPJTnOaQ6qmpET16cK14kkjbazl6+p0RRv0yw==" + }, + "regexpp": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz", + "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==", + "dev": true + }, + "repeat-element": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", + "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==", + "dev": true + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", + "dev": true + }, + "request": { + "version": "2.88.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", + "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", + "requires": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.0", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.4.3", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + }, + "dependencies": { + "uuid": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", + "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==" + } + } + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true + }, + "require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "dev": true + }, + "require_optional": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/require_optional/-/require_optional-1.0.1.tgz", + "integrity": "sha512-qhM/y57enGWHAe3v/NcwML6a3/vfESLe/sGM2dII+gEO0BpKRUkWZow/tyloNqJyN6kXSl3RyyM8Ll5D/sJP8g==", + "requires": { + "resolve-from": "^2.0.0", + "semver": "^5.1.0" + } + }, + "resolve": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", + "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", + "dev": true + }, + "resolve-from": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-2.0.0.tgz", + "integrity": "sha1-lICrIOlP+h2egKgEx+oUdhGWa1c=" + }, + "resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", + "dev": true + }, + "restore-cursor": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", + "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", + "dev": true, + "requires": { + "onetime": "^2.0.0", + "signal-exit": "^3.0.2" + } + }, + "ret": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", + "dev": true + }, + "revalidator": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/revalidator/-/revalidator-0.3.1.tgz", + "integrity": "sha1-/yzEz3zHxjhaxxAXgnbm280Ddi8=" + }, + "rimraf": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + }, + "dependencies": { + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + } + } + }, + "run-async": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", + "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", + "dev": true, + "requires": { + "is-promise": "^2.1.0" + } + }, + "run-node": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/run-node/-/run-node-1.0.0.tgz", + "integrity": "sha512-kc120TBlQ3mih1LSzdAJXo4xn/GWS2ec0l3S+syHDXP9uRr0JAT8Qd3mdMuyjqCzeZktgP3try92cEgf9Nks8A==", + "dev": true + }, + "rxjs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.2.tgz", + "integrity": "sha512-HUb7j3kvb7p7eCUHE3FqjoDsC1xfZQ4AHFWfTKSpZ+sAhhz5X1WX0ZuUqWbzB2QhSLp3DoLUG+hMdEDKqWo2Zg==", + "dev": true, + "requires": { + "tslib": "^1.9.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==" + }, + "safe-json-stringify": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/safe-json-stringify/-/safe-json-stringify-1.2.0.tgz", + "integrity": "sha512-gH8eh2nZudPQO6TytOvbxnuhYBOvDBBLW52tz5q6X58lJcd/tkmqFR+5Z9adS8aJtURSXWThWy/xJtJwixErvg==" + }, + "safe-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", + "dev": true, + "requires": { + "ret": "~0.1.10" + } + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "saslprep": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/saslprep/-/saslprep-1.0.2.tgz", + "integrity": "sha512-4cDsYuAjXssUSjxHKRe4DTZC0agDwsCqcMqtJAQPzC74nJ7LfAJflAtC1Zed5hMzEQKj82d3tuzqdGNRsLJ4Gw==", + "optional": true, + "requires": { + "sparse-bitfield": "^3.0.3" + } + }, + "semver": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz", + "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==" + }, + "semver-compare": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", + "integrity": "sha1-De4hahyUGrN+nvsXiPavxf9VN/w=", + "dev": true + }, + "send": { + "version": "0.16.2", + "resolved": "https://registry.npmjs.org/send/-/send-0.16.2.tgz", + "integrity": "sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw==", + "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.6.2", + "mime": "1.4.1", + "ms": "2.0.0", + "on-finished": "~2.3.0", + "range-parser": "~1.2.0", + "statuses": "~1.4.0" + }, + "dependencies": { + "statuses": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", + "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==" + } + } + }, + "serr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/serr/-/serr-1.0.1.tgz", + "integrity": "sha1-dKW55/rdW1X4qF5+crwApBm25II=", + "requires": { + "lodash": "^4.0.0" + } + }, + "serve-static": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.2.tgz", + "integrity": "sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw==", + "requires": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.2", + "send": "0.16.2" + } + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "dev": true + }, + "set-value": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", + "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.3", + "split-string": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" + }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "dev": true, + "requires": { + "shebang-regex": "^1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "dev": true + }, + "should": { + "version": "13.2.3", + "resolved": "https://registry.npmjs.org/should/-/should-13.2.3.tgz", + "integrity": "sha512-ggLesLtu2xp+ZxI+ysJTmNjh2U0TsC+rQ/pfED9bUZZ4DKefP27D+7YJVVTvKsmjLpIi9jAa7itwDGkDDmt1GQ==", + "dev": true, + "requires": { + "should-equal": "^2.0.0", + "should-format": "^3.0.3", + "should-type": "^1.4.0", + "should-type-adaptors": "^1.0.1", + "should-util": "^1.0.0" + } + }, + "should-equal": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/should-equal/-/should-equal-2.0.0.tgz", + "integrity": "sha512-ZP36TMrK9euEuWQYBig9W55WPC7uo37qzAEmbjHz4gfyuXrEUgF8cUvQVO+w+d3OMfPvSRQJ22lSm8MQJ43LTA==", + "dev": true, + "requires": { + "should-type": "^1.4.0" + } + }, + "should-format": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/should-format/-/should-format-3.0.3.tgz", + "integrity": "sha1-m/yPdPo5IFxT04w01xcwPidxJPE=", + "dev": true, + "requires": { + "should-type": "^1.3.0", + "should-type-adaptors": "^1.0.1" + } + }, + "should-type": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/should-type/-/should-type-1.4.0.tgz", + "integrity": "sha1-B1bYzoRt/QmEOmlHcZ36DUz/XPM=", + "dev": true + }, + "should-type-adaptors": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/should-type-adaptors/-/should-type-adaptors-1.1.0.tgz", + "integrity": "sha512-JA4hdoLnN+kebEp2Vs8eBe9g7uy0zbRo+RMcU0EsNy+R+k049Ki+N5tT5Jagst2g7EAja+euFuoXFCa8vIklfA==", + "dev": true, + "requires": { + "should-type": "^1.3.0", + "should-util": "^1.0.0" + } + }, + "should-util": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/should-util/-/should-util-1.0.0.tgz", + "integrity": "sha1-yYzaN0qmsZDfi6h8mInCtNtiAGM=", + "dev": true + }, + "sift": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/sift/-/sift-7.0.1.tgz", + "integrity": "sha512-oqD7PMJ+uO6jV9EQCl0LrRw1OwsiPsiFQR5AR30heR+4Dl7jBBbDLnNvWiak20tzZlSE1H7RB30SX/1j/YYT7g==" + }, + "signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", + "dev": true + }, + "slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "dev": true + }, + "slice-ansi": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz", + "integrity": "sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU=", + "dev": true + }, + "sliced": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sliced/-/sliced-1.0.1.tgz", + "integrity": "sha1-CzpmK10Ewxd7GSa+qCsD+Dei70E=" + }, + "snapdragon": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", + "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", + "dev": true, + "requires": { + "base": "^0.11.1", + "debug": "^2.2.0", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "map-cache": "^0.2.2", + "source-map": "^0.5.6", + "source-map-resolve": "^0.5.0", + "use": "^3.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "snapdragon-node": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", + "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", + "dev": true, + "requires": { + "define-property": "^1.0.0", + "isobject": "^3.0.0", + "snapdragon-util": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "snapdragon-util": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", + "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", + "dev": true, + "requires": { + "kind-of": "^3.2.0" + }, + "dependencies": { + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "source-map": { + "version": "0.1.43", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", + "integrity": "sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y=", + "optional": true, + "requires": { + "amdefine": ">=0.0.4" + } + }, + "source-map-resolve": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz", + "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==", + "dev": true, + "requires": { + "atob": "^2.1.1", + "decode-uri-component": "^0.2.0", + "resolve-url": "^0.2.1", + "source-map-url": "^0.4.0", + "urix": "^0.1.0" + } + }, + "source-map-url": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", + "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", + "dev": true + }, + "sparse-bitfield": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", + "integrity": "sha1-/0rm5oZWBWuks+eSqzM004JzyhE=", + "optional": true, + "requires": { + "memory-pager": "^1.0.2" + } + }, + "spdx-correct": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz", + "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==", + "dev": true, + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", + "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==", + "dev": true + }, + "spdx-expression-parse": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", + "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", + "dev": true, + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz", + "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==", + "dev": true + }, + "split-on-first": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/split-on-first/-/split-on-first-1.1.0.tgz", + "integrity": "sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw==" + }, + "split-string": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", + "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", + "dev": true, + "requires": { + "extend-shallow": "^3.0.0" + } + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "sshpk": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", + "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", + "requires": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + } + }, + "staged-git-files": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/staged-git-files/-/staged-git-files-1.1.1.tgz", + "integrity": "sha512-H89UNKr1rQJvI1c/PIR3kiAMBV23yvR7LItZiV74HWZwzt7f3YHuujJ9nJZlt58WlFox7XQsOahexwk7nTe69A==", + "dev": true + }, + "static-extend": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", + "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", + "dev": true, + "requires": { + "define-property": "^0.2.5", + "object-copy": "^0.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + } + } + }, + "statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" + }, + "strict-uri-encode": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz", + "integrity": "sha1-ucczDHBChi9rFC3CdLvMWGbONUY=" + }, + "string-argv": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.0.2.tgz", + "integrity": "sha1-2sMECGkMIfPDYwo/86BYd73L1zY=", + "dev": true + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + } + }, + "stringify-object": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/stringify-object/-/stringify-object-3.3.0.tgz", + "integrity": "sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw==", + "dev": true, + "requires": { + "get-own-enumerable-property-symbols": "^3.0.0", + "is-obj": "^1.0.1", + "is-regexp": "^1.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + }, + "strip-eof": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", + "dev": true + }, + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "dev": true, + "requires": { + "has-flag": "^1.0.0" + } + }, + "symbol-observable": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz", + "integrity": "sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==", + "dev": true + }, + "table": { + "version": "5.4.6", + "resolved": "https://registry.npmjs.org/table/-/table-5.4.6.tgz", + "integrity": "sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug==", + "dev": true, + "requires": { + "ajv": "^6.10.2", + "lodash": "^4.17.14", + "slice-ansi": "^2.1.0", + "string-width": "^3.0.0" + }, + "dependencies": { + "ajv": { + "version": "6.10.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz", + "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==", + "dev": true, + "requires": { + "fast-deep-equal": "^2.0.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "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 + }, + "lodash": { + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", + "dev": true + }, + "slice-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz", + "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.0", + "astral-regex": "^1.0.0", + "is-fullwidth-code-point": "^2.0.0" + } + }, + "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" + } + }, + "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" + } + } + } + }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "dev": true + }, + "timekeeper": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/timekeeper/-/timekeeper-2.2.0.tgz", + "integrity": "sha512-W3AmPTJWZkRwu+iSNxPIsLZ2ByADsOLbbLxe46UJyWj3mlYLlwucKiq+/dPm0l9wTzqoF3/2PH0AGFCebjq23A==", + "dev": true + }, + "tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dev": true, + "requires": { + "os-tmpdir": "~1.0.2" + } + }, + "to-object-path": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", + "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "to-regex": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", + "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", + "dev": true, + "requires": { + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "regex-not": "^1.0.2", + "safe-regex": "^1.1.0" + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dev": true, + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + } + }, + "toidentifier": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", + "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==" + }, + "tough-cookie": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", + "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", + "requires": { + "psl": "^1.1.24", + "punycode": "^1.4.1" + }, + "dependencies": { + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" + } + } + }, + "tslib": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", + "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==", + "dev": true + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" + }, + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "dev": true, + "requires": { + "prelude-ls": "~1.1.2" + } + }, + "type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true + }, + "type-is": { + "version": "1.6.16", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz", + "integrity": "sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q==", + "requires": { + "media-typer": "0.3.0", + "mime-types": "~2.1.18" + } + }, + "uglify-js": { + "version": "3.5.9", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.5.9.tgz", + "integrity": "sha512-WpT0RqsDtAWPNJK955DEnb6xjymR8Fn0OlK4TT4pS0ASYsVPqr5ELhgwOwLCP5J5vHeJ4xmMmz3DEgdqC10JeQ==", + "dev": true, + "optional": true, + "requires": { + "commander": "~2.20.0", + "source-map": "~0.6.1" + }, + "dependencies": { + "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, + "optional": true + } + } + }, + "underscore": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.9.1.tgz", + "integrity": "sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg==" + }, + "union-value": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", + "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", + "dev": true, + "requires": { + "arr-union": "^3.1.0", + "get-value": "^2.0.6", + "is-extendable": "^0.1.1", + "set-value": "^2.0.1" + } + }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" + }, + "unset-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", + "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", + "dev": true, + "requires": { + "has-value": "^0.3.1", + "isobject": "^3.0.0" + }, + "dependencies": { + "has-value": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", + "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", + "dev": true, + "requires": { + "get-value": "^2.0.3", + "has-values": "^0.1.4", + "isobject": "^2.0.0" + }, + "dependencies": { + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "requires": { + "isarray": "1.0.0" + } + } + } + }, + "has-values": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", + "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + } + } + }, + "uri-js": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", + "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", + "requires": { + "punycode": "^2.1.0" + } + }, + "urix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", + "dev": true + }, + "use": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", + "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", + "dev": true + }, + "utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" + }, + "uuid": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", + "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==" + }, + "validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "requires": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "watch": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/watch/-/watch-1.0.2.tgz", + "integrity": "sha1-NApxe952Vyb6CqB9ch4BR6VR3ww=", + "dev": true, + "requires": { + "exec-sh": "^0.2.0", + "minimist": "^1.2.0" + } + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", + "dev": true + }, + "wide-align": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", + "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", + "dev": true, + "requires": { + "string-width": "^1.0.2 || 2" + } + }, + "wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", + "dev": true + }, + "wrap-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "dev": true, + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + } + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "write": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/write/-/write-1.0.3.tgz", + "integrity": "sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==", + "dev": true, + "requires": { + "mkdirp": "^0.5.1" + } + }, + "y18n": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", + "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", + "dev": true + }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", + "dev": true + }, + "yargs": { + "version": "13.2.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.2.2.tgz", + "integrity": "sha512-WyEoxgyTD3w5XRpAQNYUB9ycVH/PQrToaTXdYXRdOXvEy1l19br+VJsc0vcO8PTGg5ro/l/GY7F/JMEBmI0BxA==", + "dev": true, + "requires": { + "cliui": "^4.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "os-locale": "^3.1.0", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.0.0" + }, + "dependencies": { + "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 + }, + "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" + } + }, + "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" + } + } + } + }, + "yargs-parser": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.0.0.tgz", + "integrity": "sha512-w2LXjoL8oRdRQN+hOyppuXs+V/fVAYtpcrRxZuF7Kt/Oc+Jr2uAcVntaUTNT6w5ihoWfFDpNY8CPx1QskxZ/pw==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + }, + "yargs-unparser": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-1.5.0.tgz", + "integrity": "sha512-HK25qidFTCVuj/D1VfNiEndpLIeJN78aqgR23nL3y4N0U/91cOAzqfHlF8n2BvoNDcZmJKin3ddNSvOxSr8flw==", + "dev": true, + "requires": { + "flat": "^4.1.0", + "lodash": "^4.17.11", + "yargs": "^12.0.5" + }, + "dependencies": { + "get-caller-file": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", + "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", + "dev": true + }, + "require-main-filename": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", + "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", + "dev": true + }, + "yargs": { + "version": "12.0.5", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.5.tgz", + "integrity": "sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw==", + "dev": true, + "requires": { + "cliui": "^4.0.0", + "decamelize": "^1.2.0", + "find-up": "^3.0.0", + "get-caller-file": "^1.0.1", + "os-locale": "^3.0.0", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^2.0.0", + "which-module": "^2.0.0", + "y18n": "^3.2.1 || ^4.0.0", + "yargs-parser": "^11.1.1" + } + }, + "yargs-parser": { + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-11.1.1.tgz", + "integrity": "sha512-C6kB/WJDiaxONLJQnF8ccx9SEeoTTLek8RVbaOIsrAUS8VrBEXfmeSnCZxygc+XC2sNMBIwOOnfcxiynjHsVSQ==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + } + } + } + } +} diff --git a/package.json b/package.json index 7c5f5d93a..d3143e9b7 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,6 @@ { "name": "iotagent-node-lib", + "license": "AGPL-3.0-only", "description": "IoT Agent library to interface with NGSI Context Broker", "version": "2.11.0-next", "homepage": "https://github.com/telefonicaid/iotagent-node-lib", @@ -32,7 +33,8 @@ "clean": "rm -rf package-lock.json && rm -rf node_modules && rm -rf coverage", "test": "mocha --recursive 'test/**/*.js' --reporter spec --timeout 3000 --ui bdd --exit", "test:watch": "npm run test -- -w ./lib", - "lint": "jshint lib/ --config .jshintrc && jshint test/ --config test/.jshintrc", + "lint": "eslint lib/ bin/ test/ --cache --fix", + "prettier": "prettier --config .prettierrc.json --write '**/**/**/**/*.js' '**/**/**/*.js' '**/**/*.js' '**/*.js' '*.js'", "test:coverage": "istanbul cover _mocha -- --recursive 'test/**/*.js' --reporter spec --exit", "test:coveralls": "npm run test:coverage && cat ./coverage/lcov.info | coveralls && rm -rf ./coverage", "watch": "watch 'npm test && npm run lint' ./lib ./test" @@ -57,12 +59,28 @@ }, "devDependencies": { "coveralls": "~3.0.3", + "husky": "~1.1.0", "istanbul": "~0.4.5", - "jshint": "~2.10.2", + "eslint": "~5.16.0", + "eslint-config-tamia": "~6.2.1", + "eslint-plugin-prettier": "~3.1.0", + "lint-staged": "~7.3.0", "mocha": "6.1.4", "nock": "10.0.6", + "prettier": "~1.14.2", "should": "13.2.3", "timekeeper": "2.2.0", "watch": "~1.0.2" + }, + "husky": { + "hooks": { + "pre-commit": "lint-staged" + } + }, + "lint-staged": { + "*.js": [ + "prettier --config .prettierrc.json --write", + "git add" + ] } } diff --git a/test/.jshintrc b/test/.jshintrc deleted file mode 100644 index 2cbeefda0..000000000 --- a/test/.jshintrc +++ /dev/null @@ -1,35 +0,0 @@ -{ - "curly": true, - "eqeqeq": true, - "immed": true, - "latedef": true, - "newcap": true, - "noarg": true, - "noempty": true, - "quotmark": "single", - "undef": true, - "unused": true, - "trailing": true, - "maxparams": 6, - "maxdepth": 4, - "camelcase": true, - "maxlen": 120, - "node": true, - "expr": true, - "unused": "vars", - "esversion": 6, - "globals": { - "describe":true, - "it": true, - "expect": true, - "before": true, - "after": true, - "beforeEach": true, - "afterEach": true, - "mock": true - }, - "predef": - [ - "describe", "beforeEach", "afterEach", "it" - ] -} \ No newline at end of file diff --git a/test/tools/utils.js b/test/tools/utils.js index 52313f0d1..1dd591436 100644 --- a/test/tools/utils.js +++ b/test/tools/utils.js @@ -21,18 +21,15 @@ * please contact with::[daniel.moranjimenez@telefonica.com] */ -'use strict'; - -var fs = require('fs'); +const fs = require('fs'); function readExampleFile(name, raw) { - var text = fs.readFileSync(name, 'UTF8'); + const text = fs.readFileSync(name, 'UTF8'); if (raw) { return text; - } else { - return JSON.parse(text); } + return JSON.parse(text); } exports.readExampleFile = readExampleFile; diff --git a/test/unit/expressions/expression-test.js b/test/unit/expressions/expression-test.js index 2bd6ddcb4..944f2ff03 100644 --- a/test/unit/expressions/expression-test.js +++ b/test/unit/expressions/expression-test.js @@ -20,23 +20,23 @@ * For those usages not covered by the GNU Affero General Public License * please contact with::[contacto@tid.es] */ -'use strict'; -var should = require('should'), - expressionParser = require('../../../lib/plugins/expressionParser'); +/* eslint-disable no-unused-vars */ + +const should = require('should'); +const expressionParser = require('../../../lib/plugins/expressionParser'); describe('Expression interpreter', function() { - var arithmetic, - scope = { - value: 6, - other: 3, - theString: '12.6, -19.4', - spaces: '5 a b c d 5', - big: 2000, - number: 145, - number2: 155, - number3inside: 200 - }; + const scope = { + value: 6, + other: 3, + theString: '12.6, -19.4', + spaces: '5 a b c d 5', + big: 2000, + number: 145, + number2: 155, + number3inside: 200 + }; describe('When a expression with a single value is parsed', function() { it('should return that value', function(done) { @@ -48,7 +48,7 @@ describe('Expression interpreter', function() { }); }); - arithmetic = [ + const arithmetic = [ ['5 * @value', 30], ['(6 + @value) * 3', 36], ['@value / 12 + 1', 1.5], @@ -70,7 +70,7 @@ describe('Expression interpreter', function() { }); } - for (var i = 0; i < arithmetic.length; i++) { + for (let i = 0; i < arithmetic.length; i++) { arithmeticUseCase(arithmetic[i]); } @@ -87,21 +87,21 @@ describe('Expression interpreter', function() { describe('When string transformation functions are executed', function() { it('should return the appropriate piece of the string', function(done) { expressionParser.parse( - 'trim(substr(@theString, indexOf(@theString, \",\") + 1, length(@theString)))', + 'trim(substr(@theString, indexOf(@theString, ",") + 1, length(@theString)))', scope, 'String', function(error, result) { should.not.exist(error); result.should.equal('-19.4'); done(); - }); + } + ); }); }); describe('When an expression contains variables with numbers', function() { it('should return the appropriate result', function(done) { - expressionParser.parse('@number + @number2 + @number3inside', - scope, 'String', function(error, result) { + expressionParser.parse('@number + @number2 + @number3inside', scope, 'String', function(error, result) { should.not.exist(error); result.should.equal(500); done(); @@ -111,26 +111,21 @@ describe('Expression interpreter', function() { describe('When an expression contains multiple parenthesis', function() { it('should return the appropriate result', function(done) { - expressionParser.parse('((@number) * (@number2))', - scope, 'String', function(error, result) { - should.not.exist(error); - result.should.equal(22475); - done(); - }); + expressionParser.parse('((@number) * (@number2))', scope, 'String', function(error, result) { + should.not.exist(error); + result.should.equal(22475); + done(); + }); }); }); describe('When trim() function is executed', function() { it('should return the appropriate piece of the string', function(done) { - expressionParser.parse( - 'trim(@spaces)', - scope, - 'String', - function(error, result) { - should.not.exist(error); - result.should.equal('5 a b c d 5'); - done(); - }); + expressionParser.parse('trim(@spaces)', scope, 'String', function(error, result) { + should.not.exist(error); + result.should.equal('5 a b c d 5'); + done(); + }); }); }); @@ -146,11 +141,17 @@ describe('Expression interpreter', function() { describe('When an expression with strings with single quotation marks is parsed', function() { it('should accept the strings', function(done) { - expressionParser.parse('\'Pruebas \' # \'De Strings\'', scope, 'String', function(error, result) { - should.not.exist(error); - result.should.equal('Pruebas De Strings'); - done(); - }); + expressionParser.parse( + "'Pruebas ' # 'De Strings'", + + scope, + 'String', + function(error, result) { + should.not.exist(error); + result.should.equal('Pruebas De Strings'); + done(); + } + ); }); }); @@ -193,5 +194,4 @@ describe('Expression interpreter', function() { }); }); }); - }); diff --git a/test/unit/expressions/expressionBasedTransformations-test.js b/test/unit/expressions/expressionBasedTransformations-test.js index cc350bad3..8e2a15e30 100644 --- a/test/unit/expressions/expressionBasedTransformations-test.js +++ b/test/unit/expressions/expressionBasedTransformations-test.js @@ -20,103 +20,100 @@ * For those usages not covered by the GNU Affero General Public License * please contact with::[contacto@tid.es] */ -'use strict'; -/* jshint camelcase: false */ - -var iotAgentLib = require('../../../lib/fiware-iotagent-lib'), - utils = require('../../tools/utils'), - should = require('should'), - logger = require('logops'), - nock = require('nock'), - contextBrokerMock, - iotAgentConfig = { - contextBroker: { - host: '192.168.1.1', - port: '1026' +const iotAgentLib = require('../../../lib/fiware-iotagent-lib'); +const utils = require('../../tools/utils'); +const should = require('should'); +const logger = require('logops'); +const nock = require('nock'); +let contextBrokerMock; +const iotAgentConfig = { + contextBroker: { + host: '192.168.1.1', + port: '1026' + }, + server: { + port: 4041 + }, + types: { + Light: { + commands: [], + type: 'Light', + lazy: [], + active: [ + { + object_id: 'p', + name: 'pressure', + type: 'Hgmm', + expression: '${@pressure * 20}' + } + ] }, - server: { - port: 4041 + LightError: { + commands: [], + type: 'Light', + lazy: [], + active: [ + { + object_id: 'p', + name: 'pressure', + type: 'Hgmm', + expression: '${@pressure * / 20}' + } + ] }, - types: { - 'Light': { - commands: [], - type: 'Light', - lazy: [], - active: [ - { - object_id: 'p', - name: 'pressure', - type: 'Hgmm', - expression: '${@pressure * 20}' - } - ] - }, - 'LightError': { - commands: [], - type: 'Light', - lazy: [], - active: [ - { - object_id: 'p', - name: 'pressure', - type: 'Hgmm', - expression: '${@pressure * / 20}' - } - ] - }, - 'WeatherStation': { - commands: [], - type: 'WeatherStation', - lazy: [], - active: [ - { - object_id: 'p', - name: 'pressure', - type: 'Hgmm', - expression: '${@pressure * 20}' - }, - { - object_id: 'h', - name: 'humidity', - type: 'Percentage' - }, - { - name: 'weather', - type: 'Summary', - expression: 'Humidity ${@humidity / 2} and pressure ${@pressure * 20}' - } - ] - }, - 'WeatherStationMultiple': { - commands: [], - type: 'WeatherStation', - lazy: [], - active: [ - { - object_id: 'p', - name: 'pressure25', - type: 'Hgmm', - expression: '${@pressure * 20}' - }, - { - object_id: 'h', - name: 'humidity12', - type: 'Percentage' - }, - { - name: 'weather', - type: 'Summary', - expression: 'Humidity ${@humidity12 / 2} and pressure ${@pressure25 * 20}' - } - ] - } + WeatherStation: { + commands: [], + type: 'WeatherStation', + lazy: [], + active: [ + { + object_id: 'p', + name: 'pressure', + type: 'Hgmm', + expression: '${@pressure * 20}' + }, + { + object_id: 'h', + name: 'humidity', + type: 'Percentage' + }, + { + name: 'weather', + type: 'Summary', + expression: 'Humidity ${@humidity / 2} and pressure ${@pressure * 20}' + } + ] }, - service: 'smartGondor', - subservice: 'gardens', - providerUrl: 'http://smartGondor.com', - deviceRegistrationDuration: 'P1M' - }; + WeatherStationMultiple: { + commands: [], + type: 'WeatherStation', + lazy: [], + active: [ + { + object_id: 'p', + name: 'pressure25', + type: 'Hgmm', + expression: '${@pressure * 20}' + }, + { + object_id: 'h', + name: 'humidity12', + type: 'Percentage' + }, + { + name: 'weather', + type: 'Summary', + expression: 'Humidity ${@humidity12 / 2} and pressure ${@pressure25 * 20}' + } + ] + } + }, + service: 'smartGondor', + subservice: 'gardens', + providerUrl: 'http://smartGondor.com', + deviceRegistrationDuration: 'P1M' +}; describe('Expression-based transformations plugin', function() { beforeEach(function(done) { @@ -139,7 +136,7 @@ describe('Expression-based transformations plugin', function() { }); describe('When an update comes for attributes with expressions', function() { - var values = [ + const values = [ { name: 'p', type: 'centigrades', @@ -153,10 +150,16 @@ describe('Expression-based transformations plugin', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v1/updateContext', utils.readExampleFile( - './test/unit/examples/contextRequests/updateContextExpressionPlugin1.json')) - .reply(200, utils.readExampleFile( - './test/unit/examples/contextResponses/updateContextExpressionPlugin1Success.json')); + .post( + '/v1/updateContext', + utils.readExampleFile('./test/unit/examples/contextRequests/updateContextExpressionPlugin1.json') + ) + .reply( + 200, + utils.readExampleFile( + './test/unit/examples/contextResponses/updateContextExpressionPlugin1Success.json' + ) + ); }); it('should apply the expression before sending the values', function(done) { @@ -169,7 +172,7 @@ describe('Expression-based transformations plugin', function() { }); describe('When an update comes for expressions with syntax errors', function() { - var values = [ + const values = [ { name: 'p', type: 'centigrades', @@ -183,10 +186,16 @@ describe('Expression-based transformations plugin', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v1/updateContext', utils.readExampleFile( - './test/unit/examples/contextRequests/updateContextExpressionPlugin4.json')) - .reply(200, utils.readExampleFile( - './test/unit/examples/contextResponses/updateContextExpressionPlugin1Success.json')); + .post( + '/v1/updateContext', + utils.readExampleFile('./test/unit/examples/contextRequests/updateContextExpressionPlugin4.json') + ) + .reply( + 200, + utils.readExampleFile( + './test/unit/examples/contextResponses/updateContextExpressionPlugin1Success.json' + ) + ); }); it('should apply the expression before sending the values', function(done) { @@ -200,7 +209,7 @@ describe('Expression-based transformations plugin', function() { }); describe('When there are expression attributes that are just calculated (not sent by the device)', function() { - var values = [ + const values = [ { name: 'p', type: 'centigrades', @@ -219,10 +228,16 @@ describe('Expression-based transformations plugin', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v1/updateContext', utils.readExampleFile( - './test/unit/examples/contextRequests/updateContextExpressionPlugin2.json')) - .reply(200, utils.readExampleFile( - './test/unit/examples/contextResponses/updateContextExpressionPlugin2Success.json')); + .post( + '/v1/updateContext', + utils.readExampleFile('./test/unit/examples/contextRequests/updateContextExpressionPlugin2.json') + ) + .reply( + 200, + utils.readExampleFile( + './test/unit/examples/contextResponses/updateContextExpressionPlugin2Success.json' + ) + ); }); it('should calculate them and add them to the payload', function(done) { @@ -235,7 +250,7 @@ describe('Expression-based transformations plugin', function() { }); describe('When an expression with multiple variables with numbers arrive', function() { - var values = [ + const values = [ { name: 'p', type: 'centigrades', @@ -254,10 +269,16 @@ describe('Expression-based transformations plugin', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v1/updateContext', utils.readExampleFile( - './test/unit/examples/contextRequests/updateContextExpressionPlugin5.json')) - .reply(200, utils.readExampleFile( - './test/unit/examples/contextResponses/updateContextExpressionPlugin5Success.json')); + .post( + '/v1/updateContext', + utils.readExampleFile('./test/unit/examples/contextRequests/updateContextExpressionPlugin5.json') + ) + .reply( + 200, + utils.readExampleFile( + './test/unit/examples/contextResponses/updateContextExpressionPlugin5Success.json' + ) + ); }); it('should calculate it and add it to the payload', function(done) { @@ -270,7 +291,7 @@ describe('Expression-based transformations plugin', function() { }); describe('When a measure arrives and there is not enough information to calculate an expression', function() { - var values = [ + const values = [ { name: 'p', type: 'centigrades', @@ -284,10 +305,16 @@ describe('Expression-based transformations plugin', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v1/updateContext', utils.readExampleFile( - './test/unit/examples/contextRequests/updateContextExpressionPlugin3.json')) - .reply(200, utils.readExampleFile( - './test/unit/examples/contextResponses/updateContextExpressionPlugin3Success.json')); + .post( + '/v1/updateContext', + utils.readExampleFile('./test/unit/examples/contextRequests/updateContextExpressionPlugin3.json') + ) + .reply( + 200, + utils.readExampleFile( + './test/unit/examples/contextResponses/updateContextExpressionPlugin3Success.json' + ) + ); }); it('should not calculate the expression', function(done) { diff --git a/test/unit/general/alarmManagement-test.js b/test/unit/general/alarmManagement-test.js index 8579070df..952c252ae 100644 --- a/test/unit/general/alarmManagement-test.js +++ b/test/unit/general/alarmManagement-test.js @@ -20,16 +20,13 @@ * For those usages not covered by the GNU Affero General Public License * please contact with::[contacto@tid.es] */ -'use strict'; -var iotagentLib = require('../../../lib/fiware-iotagent-lib'), - alarmManagement = iotagentLib.alarms, - logger = require('logops'), - should = require('should'); +const iotagentLib = require('../../../lib/fiware-iotagent-lib'); +const alarmManagement = iotagentLib.alarms; +const logger = require('logops'); +const should = require('should'); describe('Alarm management system', function() { - /* jshint sub:true */ - beforeEach(function() { logger.setLevel('FATAL'); @@ -42,27 +39,23 @@ describe('Alarm management system', function() { describe('When a new alarm is raised', function() { it('should add it to the list of risen alarms', function() { - var alarmList; - alarmManagement.raise('TEST_ALARM', 'Test description'); - alarmList = alarmManagement.list(); + const alarmList = alarmManagement.list(); - should.exist(alarmList['TEST_ALARM']); - alarmList['TEST_ALARM'].name.should.equal('TEST_ALARM'); - alarmList['TEST_ALARM'].description.should.equal('Test description'); + should.exist(alarmList.TEST_ALARM); + alarmList.TEST_ALARM.name.should.equal('TEST_ALARM'); + alarmList.TEST_ALARM.description.should.equal('Test description'); }); }); describe('When a new alarm is raised multiple times', function() { it('should only add it once to the risen alarms list', function() { - var alarmList; - alarmManagement.raise('TEST_ALARM', 'Test description'); alarmManagement.raise('TEST_ALARM', 'Test description'); alarmManagement.raise('TEST_ALARM', 'Test description'); alarmManagement.raise('TEST_ALARM', 'Test description'); alarmManagement.raise('TEST_ALARM', 'Test description'); - alarmList = alarmManagement.list(); + const alarmList = alarmManagement.list(); Object.keys(alarmList).length.should.equal(1); }); @@ -79,22 +72,22 @@ describe('Alarm management system', function() { }); it('should disappear from the alarms list', function() { - var alarmList = alarmManagement.list(); + const alarmList = alarmManagement.list(); - should.not.exist(alarmList['TEST_ALARM3']); + should.not.exist(alarmList.TEST_ALARM3); }); it('should not affect other alarms', function() { - var alarmList = alarmManagement.list(); + const alarmList = alarmManagement.list(); - should.exist(alarmList['TEST_ALARM1']); - should.exist(alarmList['TEST_ALARM2']); - should.exist(alarmList['TEST_ALARM4']); + should.exist(alarmList.TEST_ALARM1); + should.exist(alarmList.TEST_ALARM2); + should.exist(alarmList.TEST_ALARM4); }); }); describe('When the alarm instrumentation function is used on a function', function() { - var interceptedFn; + let interceptedFn; function mockFunction(raiseError, callback) { if (raiseError) { @@ -112,18 +105,18 @@ describe('Alarm management system', function() { alarmManagement.raise('TEST_INTERCEPT', 'Test description'); interceptedFn(false, function() { - var alarmList = alarmManagement.list(); + const alarmList = alarmManagement.list(); - should.not.exist(alarmList['TEST_INTERCEPT']); + should.not.exist(alarmList.TEST_INTERCEPT); done(); }); }); it('should raise the alarm if the funciton returns an error result', function(done) { interceptedFn(true, function() { - var alarmList = alarmManagement.list(); + const alarmList = alarmManagement.list(); - should.exist(alarmList['TEST_INTERCEPT']); + should.exist(alarmList.TEST_INTERCEPT); done(); }); @@ -131,7 +124,7 @@ describe('Alarm management system', function() { }); describe('When an instrumented function calls the callback with a null value', function() { - var interceptedFn; + let interceptedFn; function mockFunction(raiseError, callback) { if (raiseError) { @@ -147,9 +140,9 @@ describe('Alarm management system', function() { it('should not raise the alarm', function(done) { interceptedFn(false, function() { - var alarmList = alarmManagement.list(); + const alarmList = alarmManagement.list(); - should.not.exist(alarmList['TEST_INTERCEPT']); + should.not.exist(alarmList.TEST_INTERCEPT); done(); }); diff --git a/test/unit/general/config-multi-core-test.js b/test/unit/general/config-multi-core-test.js index 251fc3d30..6c49a9603 100644 --- a/test/unit/general/config-multi-core-test.js +++ b/test/unit/general/config-multi-core-test.js @@ -23,45 +23,42 @@ * Modified by: Fernando López - FIWARE Foundation, e.V. * */ -'use strict'; - -let config = require('../../../lib/commonConfig'), - iotAgentConfig = { - logLevel: 'FATAL', - contextBroker: { - host: '192.168.1.1', - port: '1026', - }, - server: { - port: 4041 - }, - types: { - 'Light': { - commands: [], - type: 'Light', - lazy: [ - { - name: 'temperature', - type: 'centigrades' - } - ], - attributes: [ - { - name: 'pressure', - type: 'Hgmm' - } - ] - } - }, - providerUrl: 'http://smartGondor.com', - deviceRegistrationDuration: 'P1M', - throttling: 'PT5S', - }; +const config = require('../../../lib/commonConfig'); +const iotAgentConfig = { + logLevel: 'FATAL', + contextBroker: { + host: '192.168.1.1', + port: '1026' + }, + server: { + port: 4041 + }, + types: { + Light: { + commands: [], + type: 'Light', + lazy: [ + { + name: 'temperature', + type: 'centigrades' + } + ], + attributes: [ + { + name: 'pressure', + type: 'Hgmm' + } + ] + } + }, + providerUrl: 'http://smartGondor.com', + deviceRegistrationDuration: 'P1M', + throttling: 'PT5S' +}; describe('Startup Multi-Core tests', function() { - - describe('When the IoT Agent is started with Multi-Core environment variable with value \'true\'', function() { + describe('When the IoT Agent is started with Multi-Core environment variable with value=true', function() { beforeEach(function() { process.env.IOTA_MULTI_CORE = 'true'; iotAgentConfig.multiCore = false; @@ -71,15 +68,14 @@ describe('Startup Multi-Core tests', function() { delete process.env.IOTA_MULTI_CORE; }); - it('should load the correct configuration parameter with value \'true\'', function(done) { + it('should load the correct configuration parameter with value=true', function(done) { config.setConfig(iotAgentConfig); config.getConfig().multiCore.should.equal(true); done(); }); - }); - describe('When the IoT Agent is started with Multi-Core environment variable with value \'false\'', function() { + describe('When the IoT Agent is started with Multi-Core environment variable with value=false', function() { beforeEach(function() { process.env.IOTA_MULTI_CORE = 'false'; iotAgentConfig.multiCore = true; @@ -89,31 +85,33 @@ describe('Startup Multi-Core tests', function() { delete process.env.IOTA_MULTI_CORE; }); - it('should load the correct configuration parameter with value \'false\'', function(done) { + it('should load the correct configuration parameter with value=false', function(done) { config.setConfig(iotAgentConfig); config.getConfig().multiCore.should.equal(false); done(); }); }); - - describe('When the IoT Agent is started with Multi-Core environment variable with any other value except ' + - '\'true\' or \'false\'', function() { - beforeEach(function() { - process.env.IOTA_MULTI_CORE = 'foo'; - iotAgentConfig.multiCore = true; - }); - - afterEach(function() { - delete process.env.IOTA_MULTI_CORE; - }); - - it('should load the correct configuration parameter with value \'false\'', function(done) { - config.setConfig(iotAgentConfig); - config.getConfig().multiCore.should.equal(false); - done(); - }); - }); + describe( + 'When the IoT Agent is started with Multi-Core environment variable with any other value except ' + + 'true or false', + function() { + beforeEach(function() { + process.env.IOTA_MULTI_CORE = 'foo'; + iotAgentConfig.multiCore = true; + }); + + afterEach(function() { + delete process.env.IOTA_MULTI_CORE; + }); + + it('should load the correct configuration parameter with value=false', function(done) { + config.setConfig(iotAgentConfig); + config.getConfig().multiCore.should.equal(false); + done(); + }); + } + ); describe('When the IoT Agent is started with Multi-Core environment variable with a numeric value', function() { beforeEach(function() { @@ -125,93 +123,103 @@ describe('Startup Multi-Core tests', function() { delete process.env.IOTA_MULTI_CORE; }); - it('should load the correct configuration parameter with value \'false\'', function(done) { - config.setConfig(iotAgentConfig); - config.getConfig().multiCore.should.equal(false); - done(); - }); - }); - - describe('When the IoT Agent is either started with Multi-Core environment variable nor it is ' + - 'configured', function() { - beforeEach(function() { - }); - - afterEach(function() { - delete process.env.IOTA_MULTI_CORE; - }); - - it('should load the correct configuration parameter with value \'false\'', function(done) { - config.setConfig(iotAgentConfig); - config.getConfig().multiCore.should.equal(false); - done(); - }); - }); - - describe('When the IoT Agent is not started with Multi-Core environment variable and it is configured with ' + - 'value \'true\'', function() { - beforeEach(function() { - iotAgentConfig.multiCore = true; - }); - - afterEach(function() { - delete process.env.IOTA_MULTI_CORE; - }); - - it('should load the correct configuration parameter with value \'true\'', function(done) { - config.setConfig(iotAgentConfig); - config.getConfig().multiCore.should.equal(true); - done(); - }); - }); - - describe('When the IoT Agent is not started with Multi-Core environment variable and it is configured with ' + - 'value \'false\'', function() { - beforeEach(function() { - iotAgentConfig.multiCore = false; - }); - - afterEach(function() { - delete process.env.IOTA_MULTI_CORE; - }); - - it('should load the correct configuration parameter with value \'false\'', function(done) { + it('should load the correct configuration parameter with value=false', function(done) { config.setConfig(iotAgentConfig); config.getConfig().multiCore.should.equal(false); done(); }); }); - describe('When the IoT Agent is not started with Multi-Core environment variable and it is configured with ' + - 'any other value except \'true\' or \'false\'', function() { - beforeEach(function() { - iotAgentConfig.multiCore = 'foo'; - }); + describe('When the IoT Agent is either started with Multi-Core environment variable nor it is configured', function() { + beforeEach(function() {}); afterEach(function() { delete process.env.IOTA_MULTI_CORE; }); - it('should load the correct configuration parameter with value \'false\'', function(done) { + it('should load the correct configuration parameter with value=false', function(done) { config.setConfig(iotAgentConfig); config.getConfig().multiCore.should.equal(false); done(); }); }); - describe('When the IoT Agent is not started with Multi-Core environment variable and it is configured with ' + - 'a numeric value', function() { - beforeEach(function() { - iotAgentConfig.multiCore = 123; - }); - - afterEach(function() { - delete process.env.IOTA_MULTI_CORE; - }); - it('should load the correct configuration parameter with value \'false\'', function(done) { - config.setConfig(iotAgentConfig); - config.getConfig().multiCore.should.equal(false); - done(); - }); - }); + describe( + 'When the IoT Agent is not started with Multi-Core environment variable and it is configured with ' + + 'value=true', + function() { + beforeEach(function() { + iotAgentConfig.multiCore = true; + }); + + afterEach(function() { + delete process.env.IOTA_MULTI_CORE; + }); + + it('should load the correct configuration parameter with value=true', function(done) { + config.setConfig(iotAgentConfig); + config.getConfig().multiCore.should.equal(true); + done(); + }); + } + ); + + describe( + 'When the IoT Agent is not started with Multi-Core environment variable and it is configured with ' + + 'value=false', + function() { + beforeEach(function() { + iotAgentConfig.multiCore = false; + }); + + afterEach(function() { + delete process.env.IOTA_MULTI_CORE; + }); + + it('should load the correct configuration parameter with value=false', function(done) { + config.setConfig(iotAgentConfig); + config.getConfig().multiCore.should.equal(false); + done(); + }); + } + ); + + describe( + 'When the IoT Agent is not started with Multi-Core environment variable and it is configured with ' + + 'any other value except true or false', + function() { + beforeEach(function() { + iotAgentConfig.multiCore = 'foo'; + }); + + afterEach(function() { + delete process.env.IOTA_MULTI_CORE; + }); + + it('should load the correct configuration parameter with value=false', function(done) { + config.setConfig(iotAgentConfig); + config.getConfig().multiCore.should.equal(false); + done(); + }); + } + ); + + describe( + 'When the IoT Agent is not started with Multi-Core environment variable and it is configured with ' + + 'a numeric value', + function() { + beforeEach(function() { + iotAgentConfig.multiCore = 123; + }); + + afterEach(function() { + delete process.env.IOTA_MULTI_CORE; + }); + it('should load the correct configuration parameter with value=false', function(done) { + config.setConfig(iotAgentConfig); + config.getConfig().multiCore.should.equal(false); + done(); + }); + } + ); }); diff --git a/test/unit/general/contextBrokerKeystoneSecurityAccess-test.js b/test/unit/general/contextBrokerKeystoneSecurityAccess-test.js index 66414be2e..64fc368f5 100644 --- a/test/unit/general/contextBrokerKeystoneSecurityAccess-test.js +++ b/test/unit/general/contextBrokerKeystoneSecurityAccess-test.js @@ -20,75 +20,75 @@ * For those usages not covered by the GNU Affero General Public License * please contact with::[contacto@tid.es] */ -'use strict'; - -var iotAgentLib = require('../../../lib/fiware-iotagent-lib'), - utils = require('../../tools/utils'), - should = require('should'), - logger = require('logops'), - nock = require('nock'), - request = require('request'), - contextBrokerMock, - keystoneMock, - iotAgentConfig = { - contextBroker: { - host: '192.168.1.1', - port: '1026' - }, - server: { - port: 4041 - }, - authentication: { - // Next line is syntactically correct from a configuration point of - // view, but we comment it in order to ensure backward compability - // type: keystone, - host: '128.16.109.11', - port: '5000', - user: 'iotagent', - password: 'iotagent', - enabled: true - }, - types: { - 'Light': { - service: 'smartGondor', - subservice: 'electricity', - trust: 'BBBB987654321', - type: 'Light', - commands: [], - lazy: [ - { - name: 'temperature', - type: 'centigrades' - } - ], - active: [ - { - name: 'pressure', - type: 'Hgmm' - } - ] - }, - 'Termometer': { - commands: [], - type: 'Termometer', - lazy: [ - { - name: 'temp', - type: 'kelvin' - } - ], - active: [ - ] - } + +/* eslint-disable no-unused-vars */ + +const iotAgentLib = require('../../../lib/fiware-iotagent-lib'); +const utils = require('../../tools/utils'); +const should = require('should'); +const logger = require('logops'); +const nock = require('nock'); +const request = require('request'); +let contextBrokerMock; +let keystoneMock; +const iotAgentConfig = { + contextBroker: { + host: '192.168.1.1', + port: '1026' + }, + server: { + port: 4041 + }, + authentication: { + // Next line is syntactically correct from a configuration point of + // view, but we comment it in order to ensure backward compability + // type: keystone, + host: '128.16.109.11', + port: '5000', + user: 'iotagent', + password: 'iotagent', + enabled: true + }, + types: { + Light: { + service: 'smartGondor', + subservice: 'electricity', + trust: 'BBBB987654321', + type: 'Light', + commands: [], + lazy: [ + { + name: 'temperature', + type: 'centigrades' + } + ], + active: [ + { + name: 'pressure', + type: 'Hgmm' + } + ] }, - service: 'smartGondor', - subservice: 'gardens', - providerUrl: 'http://smartGondor.com', - deviceRegistrationDuration: 'P1M' - }; + Termometer: { + commands: [], + type: 'Termometer', + lazy: [ + { + name: 'temp', + type: 'kelvin' + } + ], + active: [] + } + }, + service: 'smartGondor', + subservice: 'gardens', + providerUrl: 'http://smartGondor.com', + deviceRegistrationDuration: 'P1M' +}; describe('Secured access to the Context Broker with Keystone', function() { - var values = [ + const values = [ { name: 'state', type: 'Boolean', @@ -115,24 +115,23 @@ describe('Secured access to the Context Broker with Keystone', function() { nock.cleanAll(); keystoneMock = nock('http://128.16.109.11:5000') - .post('/v3/auth/tokens', - utils.readExampleFile('./test/unit/examples/keystoneRequests/getTokenFromTrust.json')) - .reply( - 201, - utils.readExampleFile('./test/unit/examples/keystoneResponses/tokenFromTrust.json'), - { - 'X-Subject-Token': '12345679ABCDEF' - }); + .post( + '/v3/auth/tokens', + utils.readExampleFile('./test/unit/examples/keystoneRequests/getTokenFromTrust.json') + ) + .reply(201, utils.readExampleFile('./test/unit/examples/keystoneResponses/tokenFromTrust.json'), { + 'X-Subject-Token': '12345679ABCDEF' + }); contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'electricity') .matchHeader('X-Auth-Token', '12345679ABCDEF') - .post('/v1/updateContext', - utils.readExampleFile('./test/unit/examples/contextRequests/updateContext1.json')) - .reply( - 200, - utils.readExampleFile('./test/unit/examples/contextResponses/updateContext1Success.json')); + .post( + '/v1/updateContext', + utils.readExampleFile('./test/unit/examples/contextRequests/updateContext1.json') + ) + .reply(200, utils.readExampleFile('./test/unit/examples/contextResponses/updateContext1Success.json')); iotAgentLib.activate(iotAgentConfig, done); }); @@ -157,12 +156,11 @@ describe('Secured access to the Context Broker with Keystone', function() { nock.cleanAll(); keystoneMock = nock('http://128.16.109.11:5000') - .post('/v3/auth/tokens', - utils.readExampleFile('./test/unit/examples/keystoneRequests/getTokenFromTrust.json')) - .reply( - 201, - utils.readExampleFile('./test/unit/examples/keystoneResponses/tokenFromTrust.json'), - { + .post( + '/v3/auth/tokens', + utils.readExampleFile('./test/unit/examples/keystoneRequests/getTokenFromTrust.json') + ) + .reply(201, utils.readExampleFile('./test/unit/examples/keystoneResponses/tokenFromTrust.json'), { 'X-Subject-Token': '12345679ABCDEF' }); @@ -170,11 +168,11 @@ describe('Secured access to the Context Broker with Keystone', function() { .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'electricity') .matchHeader('X-Auth-Token', '12345679ABCDEF') - .post('/v1/updateContext', - utils.readExampleFile('./test/unit/examples/contextRequests/updateContext1.json')) - .reply( - 403, - utils.readExampleFile('./test/unit/examples/contextResponses/updateContext1Success.json')); + .post( + '/v1/updateContext', + utils.readExampleFile('./test/unit/examples/contextRequests/updateContext1.json') + ) + .reply(403, utils.readExampleFile('./test/unit/examples/contextResponses/updateContext1Success.json')); iotAgentLib.activate(iotAgentConfig, done); }); @@ -192,21 +190,24 @@ describe('Secured access to the Context Broker with Keystone', function() { nock.cleanAll(); keystoneMock = nock('http://128.16.109.11:5000') - .post('/v3/auth/tokens', - utils.readExampleFile('./test/unit/examples/keystoneRequests/getTokenFromTrust.json')) + .post( + '/v3/auth/tokens', + utils.readExampleFile('./test/unit/examples/keystoneRequests/getTokenFromTrust.json') + ) .reply( - 401, - utils.readExampleFile('./test/unit/examples/keystoneResponses/tokenFromTrustUnauthorized.json')); + 401, + utils.readExampleFile('./test/unit/examples/keystoneResponses/tokenFromTrustUnauthorized.json') + ); contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'electricity') .matchHeader('X-Auth-Token', '12345679ABCDEF') - .post('/v1/updateContext', - utils.readExampleFile('./test/unit/examples/contextRequests/updateContext1.json')) - .reply( - 200, - utils.readExampleFile('./test/unit/examples/contextResponses/updateContext1Success.json')); + .post( + '/v1/updateContext', + utils.readExampleFile('./test/unit/examples/contextRequests/updateContext1.json') + ) + .reply(200, utils.readExampleFile('./test/unit/examples/contextResponses/updateContext1Success.json')); iotAgentLib.activate(iotAgentConfig, done); }); @@ -221,21 +222,17 @@ describe('Secured access to the Context Broker with Keystone', function() { }); describe('When the user requests information about a device in a protected CB', function() { - var attributes = [ - 'state', - 'dimming' - ]; + const attributes = ['state', 'dimming']; beforeEach(function(done) { nock.cleanAll(); keystoneMock = nock('http://128.16.109.11:5000') - .post('/v3/auth/tokens', - utils.readExampleFile('./test/unit/examples/keystoneRequests/getTokenFromTrust.json')) - .reply( - 201, - utils.readExampleFile('./test/unit/examples/keystoneResponses/tokenFromTrust.json'), - { + .post( + '/v3/auth/tokens', + utils.readExampleFile('./test/unit/examples/keystoneRequests/getTokenFromTrust.json') + ) + .reply(201, utils.readExampleFile('./test/unit/examples/keystoneResponses/tokenFromTrust.json'), { 'X-Subject-Token': '12345679ABCDEF' }); @@ -243,10 +240,11 @@ describe('Secured access to the Context Broker with Keystone', function() { .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'electricity') .matchHeader('X-Auth-Token', '12345679ABCDEF') - .post('/v1/queryContext', - utils.readExampleFile('./test/unit/examples/contextRequests/queryContext1.json')) - .reply(200, - utils.readExampleFile('./test/unit/examples/contextResponses/queryContext1Success.json')); + .post( + '/v1/queryContext', + utils.readExampleFile('./test/unit/examples/contextRequests/queryContext1.json') + ) + .reply(200, utils.readExampleFile('./test/unit/examples/contextResponses/queryContext1Success.json')); iotAgentLib.activate(iotAgentConfig, done); }); @@ -261,64 +259,76 @@ describe('Secured access to the Context Broker with Keystone', function() { }); describe('When subscriptions are used on a protected Context Broker', function() { - beforeEach(function(done) { - - var optionsProvision = { + beforeEach(function(done) { + const optionsProvision = { url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices', method: 'POST', json: utils.readExampleFile( - './test/unit/examples/deviceProvisioningRequests/provisionMinimumDevice3.json'), + './test/unit/examples/deviceProvisioningRequests/provisionMinimumDevice3.json' + ), headers: { 'fiware-service': 'smartGondor', 'fiware-servicepath': 'electricity' } }; - + nock.cleanAll(); - + iotAgentLib.activate(iotAgentConfig, function() { keystoneMock = nock('http://128.16.109.11:5000') - .post('/v3/auth/tokens', - utils.readExampleFile( - './test/unit/examples/keystoneRequests/getTokenFromTrust.json')) + .post( + '/v3/auth/tokens', + utils.readExampleFile('./test/unit/examples/keystoneRequests/getTokenFromTrust.json') + ) .times(3) - .reply( - 201, - utils.readExampleFile('./test/unit/examples/keystoneResponses/tokenFromTrust.json'), - { + .reply(201, utils.readExampleFile('./test/unit/examples/keystoneResponses/tokenFromTrust.json'), { 'X-Subject-Token': '12345679ABCDEF' }); - contextBrokerMock = nock('http://192.168.1.1:1026'); contextBrokerMock .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'electricity') .matchHeader('X-Auth-Token', '12345679ABCDEF') - .post('/v1/updateContext', - utils.readExampleFile('./test/unit/examples/contextRequests/updateContext5.json')) + .post( + '/v1/updateContext', + utils.readExampleFile('./test/unit/examples/contextRequests/updateContext5.json') + ) .reply( - 200, - utils.readExampleFile('./test/unit/examples/contextResponses/updateContext1Success.json')); + 200, + utils.readExampleFile('./test/unit/examples/contextResponses/updateContext1Success.json') + ); contextBrokerMock - .post('/NGSI9/registerContext', - utils.readExampleFile('./test/unit/examples/contextAvailabilityRequests/registerNewDevice1.json')) + .post( + '/NGSI9/registerContext', + utils.readExampleFile( + './test/unit/examples/contextAvailabilityRequests/registerNewDevice1.json' + ) + ) .reply( - 200, - utils.readExampleFile( - './test/unit/examples/contextAvailabilityResponses/registerNewDevice1Success.json')); + 200, + utils.readExampleFile( + './test/unit/examples/contextAvailabilityResponses/registerNewDevice1Success.json' + ) + ); contextBrokerMock - .post('/v1/subscribeContext', + .post( + '/v1/subscribeContext', utils.readExampleFile( - './test/unit/examples/subscriptionRequests/simpleSubscriptionRequest1.json')) + './test/unit/examples/subscriptionRequests/simpleSubscriptionRequest1.json' + ) + ) .matchHeader('X-Auth-Token', '12345679ABCDEF') - .reply(200, + .reply( + 200, utils.readExampleFile( - './test/unit/examples/subscriptionResponses/simpleSubscriptionSuccess.json')); - + './test/unit/examples/subscriptionResponses/simpleSubscriptionSuccess.json' + ) + ); + iotAgentLib.clearAll(function() { request(optionsProvision, function(error, result, body) { done(); @@ -340,23 +350,25 @@ describe('Secured access to the Context Broker with Keystone', function() { }); it('unsubscribe requests use auth header', function(done) { + keystoneMock + .post( + '/v3/auth/tokens', + utils.readExampleFile('./test/unit/examples/keystoneRequests/getTokenFromTrust.json') + ) + .reply(201, utils.readExampleFile('./test/unit/examples/keystoneResponses/tokenFromTrust.json'), { + 'X-Subject-Token': '12345679ABCDEF' + }); - keystoneMock - .post('/v3/auth/tokens', - utils.readExampleFile('./test/unit/examples/keystoneRequests/getTokenFromTrust.json')) - .reply( - 201, - utils.readExampleFile('./test/unit/examples/keystoneResponses/tokenFromTrust.json'), - { - 'X-Subject-Token': '12345679ABCDEF' - }); - - contextBrokerMock = nock('http://192.168.1.1:1026') - .post('/v1/unsubscribeContext', - utils.readExampleFile('./test/unit/examples/subscriptionRequests/simpleSubscriptionRemove.json')) - .matchHeader('X-Auth-Token', '12345679ABCDEF') - .reply(200, - utils.readExampleFile('./test/unit/examples/subscriptionResponses/simpleSubscriptionSuccess.json')); + contextBrokerMock = nock('http://192.168.1.1:1026') + .post( + '/v1/unsubscribeContext', + utils.readExampleFile('./test/unit/examples/subscriptionRequests/simpleSubscriptionRemove.json') + ) + .matchHeader('X-Auth-Token', '12345679ABCDEF') + .reply( + 200, + utils.readExampleFile('./test/unit/examples/subscriptionResponses/simpleSubscriptionSuccess.json') + ); iotAgentLib.getDevice('Light1', 'smartGondor', 'electricity', function(error, device) { iotAgentLib.subscribe(device, ['dimming'], null, function(error) { @@ -367,6 +379,5 @@ describe('Secured access to the Context Broker with Keystone', function() { }); }); }); - }); }); diff --git a/test/unit/general/contextBrokerOAuthSecurityAccess-test.js b/test/unit/general/contextBrokerOAuthSecurityAccess-test.js index 112b50bf5..cd2fb9b56 100644 --- a/test/unit/general/contextBrokerOAuthSecurityAccess-test.js +++ b/test/unit/general/contextBrokerOAuthSecurityAccess-test.js @@ -22,74 +22,74 @@ * * Modified by: Daniel Calvo - ATOS Research & Innovation */ -'use strict'; - -var iotAgentLib = require('../../../lib/fiware-iotagent-lib'), - utils = require('../../tools/utils'), - should = require('should'), - logger = require('logops'), - nock = require('nock'), - request = require('request'), - contextBrokerMock, - oauth2Mock, - iotAgentConfig = { - contextBroker: { - host: '192.168.1.1', - port: '1026' - }, - server: { - port: 4041 - }, - authentication: { - type: 'oauth2', - url: 'http://192.168.1.1:3000', - header: 'Authorization', - clientId: 'context-broker', - clientSecret: 'c8d58d16-0a42-400e-9765-f32e154a5a9e', - tokenPath: '/auth/realms/default/protocol/openid-connect/token', - enabled: true - }, - types: { - 'Light': { - service: 'smartGondor', - subservice: 'electricity', - trust: 'eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJ3cHdWclJ3', - type: 'Light', - commands: [], - lazy: [ - { - name: 'temperature', - type: 'centigrades' - } - ], - active: [ - { - name: 'pressure', - type: 'Hgmm' - } - ] - }, - 'Termometer': { - commands: [], - type: 'Termometer', - lazy: [ - { - name: 'temp', - type: 'kelvin' - } - ], - active: [ - ] - } + +/* eslint-disable no-unused-vars */ + +const iotAgentLib = require('../../../lib/fiware-iotagent-lib'); +const utils = require('../../tools/utils'); +const should = require('should'); +const logger = require('logops'); +const nock = require('nock'); +const request = require('request'); +let contextBrokerMock; +let oauth2Mock; +const iotAgentConfig = { + contextBroker: { + host: '192.168.1.1', + port: '1026' + }, + server: { + port: 4041 + }, + authentication: { + type: 'oauth2', + url: 'http://192.168.1.1:3000', + header: 'Authorization', + clientId: 'context-broker', + clientSecret: 'c8d58d16-0a42-400e-9765-f32e154a5a9e', + tokenPath: '/auth/realms/default/protocol/openid-connect/token', + enabled: true + }, + types: { + Light: { + service: 'smartGondor', + subservice: 'electricity', + trust: 'eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJ3cHdWclJ3', + type: 'Light', + commands: [], + lazy: [ + { + name: 'temperature', + type: 'centigrades' + } + ], + active: [ + { + name: 'pressure', + type: 'Hgmm' + } + ] }, - service: 'smartGondor', - subservice: 'gardens', - providerUrl: 'http://smartGondor.com', - deviceRegistrationDuration: 'P1M' - }; + Termometer: { + commands: [], + type: 'Termometer', + lazy: [ + { + name: 'temp', + type: 'kelvin' + } + ], + active: [] + } + }, + service: 'smartGondor', + subservice: 'gardens', + providerUrl: 'http://smartGondor.com', + deviceRegistrationDuration: 'P1M' +}; describe('Secured access to the Context Broker with OAuth2 provider', function() { - var values = [ + const values = [ { name: 'state', type: 'Boolean', @@ -116,22 +116,21 @@ describe('Secured access to the Context Broker with OAuth2 provider', function() nock.cleanAll(); oauth2Mock = nock('http://192.168.1.1:3000') - .post('/auth/realms/default/protocol/openid-connect/token', - utils.readExampleFile('./test/unit/examples/oauthRequests/getTokenFromTrust.json', true)) - .reply( - 201, - utils.readExampleFile('./test/unit/examples/oauthResponses/tokenFromTrust.json'), - {}); + .post( + '/auth/realms/default/protocol/openid-connect/token', + utils.readExampleFile('./test/unit/examples/oauthRequests/getTokenFromTrust.json', true) + ) + .reply(201, utils.readExampleFile('./test/unit/examples/oauthResponses/tokenFromTrust.json'), {}); contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'electricity') .matchHeader('Authorization', 'Bearer eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJ3cHdWclJ3') - .post('/v1/updateContext', - utils.readExampleFile('./test/unit/examples/contextRequests/updateContext1.json')) - .reply( - 200, - utils.readExampleFile('./test/unit/examples/contextResponses/updateContext1Success.json')); + .post( + '/v1/updateContext', + utils.readExampleFile('./test/unit/examples/contextRequests/updateContext1.json') + ) + .reply(200, utils.readExampleFile('./test/unit/examples/contextResponses/updateContext1Success.json')); iotAgentLib.activate(iotAgentConfig, done); }); @@ -156,22 +155,21 @@ describe('Secured access to the Context Broker with OAuth2 provider', function() nock.cleanAll(); oauth2Mock = nock('http://192.168.1.1:3000') - .post('/auth/realms/default/protocol/openid-connect/token', - utils.readExampleFile('./test/unit/examples/oauthRequests/getTokenFromTrust.json', true)) - .reply( - 201, - utils.readExampleFile('./test/unit/examples/oauthResponses/tokenFromTrust.json'), - {}); + .post( + '/auth/realms/default/protocol/openid-connect/token', + utils.readExampleFile('./test/unit/examples/oauthRequests/getTokenFromTrust.json', true) + ) + .reply(201, utils.readExampleFile('./test/unit/examples/oauthResponses/tokenFromTrust.json'), {}); contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'electricity') .matchHeader('Authorization', 'Bearer eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJ3cHdWclJ3') - .post('/v1/updateContext', - utils.readExampleFile('./test/unit/examples/contextRequests/updateContext1.json')) - .reply( - 403, - utils.readExampleFile('./test/unit/examples/contextResponses/updateContext1Success.json')); + .post( + '/v1/updateContext', + utils.readExampleFile('./test/unit/examples/contextRequests/updateContext1.json') + ) + .reply(403, utils.readExampleFile('./test/unit/examples/contextResponses/updateContext1Success.json')); iotAgentLib.activate(iotAgentConfig, done); }); @@ -188,22 +186,25 @@ describe('Secured access to the Context Broker with OAuth2 provider', function() beforeEach(function(done) { nock.cleanAll(); - oauth2Mock = nock('http://192.168.1.1:3000') - .post('/auth/realms/default/protocol/openid-connect/token', - utils.readExampleFile('./test/unit/examples/oauthRequests/getTokenFromTrust.json', true)) + oauth2Mock = nock('http://192.168.1.1:3000') + .post( + '/auth/realms/default/protocol/openid-connect/token', + utils.readExampleFile('./test/unit/examples/oauthRequests/getTokenFromTrust.json', true) + ) .reply( - 400, - utils.readExampleFile('./test/unit/examples/oauthResponses/tokenFromTrustUnauthorized.json')); + 400, + utils.readExampleFile('./test/unit/examples/oauthResponses/tokenFromTrustUnauthorized.json') + ); contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'electricity') .matchHeader('Authorization', 'Bearer eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJ3cHdWclJ3') - .post('/v1/updateContext', - utils.readExampleFile('./test/unit/examples/contextRequests/updateContext1.json')) - .reply( - 200, - utils.readExampleFile('./test/unit/examples/contextResponses/updateContext1Success.json')); + .post( + '/v1/updateContext', + utils.readExampleFile('./test/unit/examples/contextRequests/updateContext1.json') + ) + .reply(200, utils.readExampleFile('./test/unit/examples/contextResponses/updateContext1Success.json')); iotAgentLib.activate(iotAgentConfig, done); }); @@ -218,30 +219,27 @@ describe('Secured access to the Context Broker with OAuth2 provider', function() }); describe('When the user requests information about a device in a protected CB', function() { - var attributes = [ - 'state', - 'dimming' - ]; + const attributes = ['state', 'dimming']; beforeEach(function(done) { nock.cleanAll(); oauth2Mock = nock('http://192.168.1.1:3000') - .post('/auth/realms/default/protocol/openid-connect/token', - utils.readExampleFile('./test/unit/examples/oauthRequests/getTokenFromTrust.json', true)) - .reply( - 201, - utils.readExampleFile('./test/unit/examples/oauthResponses/tokenFromTrust.json'), - {}); + .post( + '/auth/realms/default/protocol/openid-connect/token', + utils.readExampleFile('./test/unit/examples/oauthRequests/getTokenFromTrust.json', true) + ) + .reply(201, utils.readExampleFile('./test/unit/examples/oauthResponses/tokenFromTrust.json'), {}); contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'electricity') .matchHeader('Authorization', 'Bearer eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJ3cHdWclJ3') - .post('/v1/queryContext', - utils.readExampleFile('./test/unit/examples/contextRequests/queryContext1.json')) - .reply(200, - utils.readExampleFile('./test/unit/examples/contextResponses/queryContext1Success.json')); + .post( + '/v1/queryContext', + utils.readExampleFile('./test/unit/examples/contextRequests/queryContext1.json') + ) + .reply(200, utils.readExampleFile('./test/unit/examples/contextResponses/queryContext1Success.json')); iotAgentLib.activate(iotAgentConfig, done); }); @@ -256,31 +254,29 @@ describe('Secured access to the Context Broker with OAuth2 provider', function() }); describe('When subscriptions are used on a protected Context Broker', function() { - beforeEach(function(done) { - - var optionsProvision = { + beforeEach(function(done) { + const optionsProvision = { url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices', method: 'POST', json: utils.readExampleFile( - './test/unit/examples/deviceProvisioningRequests/provisionMinimumDevice3.json'), + './test/unit/examples/deviceProvisioningRequests/provisionMinimumDevice3.json' + ), headers: { 'fiware-service': 'smartGondor', 'fiware-servicepath': 'electricity' } }; - + nock.cleanAll(); - + iotAgentLib.activate(iotAgentConfig, function() { oauth2Mock = nock('http://192.168.1.1:3000') - .post('/auth/realms/default/protocol/openid-connect/token', - utils.readExampleFile('./test/unit/examples/oauthRequests/getTokenFromTrust.json', true)) + .post( + '/auth/realms/default/protocol/openid-connect/token', + utils.readExampleFile('./test/unit/examples/oauthRequests/getTokenFromTrust.json', true) + ) .times(3) - .reply( - 201, - utils.readExampleFile('./test/unit/examples/oauthResponses/tokenFromTrust.json'), - {}); - + .reply(201, utils.readExampleFile('./test/unit/examples/oauthResponses/tokenFromTrust.json'), {}); contextBrokerMock = nock('http://192.168.1.1:1026'); @@ -288,30 +284,44 @@ describe('Secured access to the Context Broker with OAuth2 provider', function() .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'electricity') .matchHeader('Authorization', 'Bearer eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJ3cHdWclJ3') - .post('/v1/updateContext', - utils.readExampleFile('./test/unit/examples/contextRequests/updateContext5.json')) + .post( + '/v1/updateContext', + utils.readExampleFile('./test/unit/examples/contextRequests/updateContext5.json') + ) .reply( - 200, - utils.readExampleFile('./test/unit/examples/contextResponses/updateContext1Success.json')); + 200, + utils.readExampleFile('./test/unit/examples/contextResponses/updateContext1Success.json') + ); contextBrokerMock - .post('/NGSI9/registerContext', - utils.readExampleFile( - './test/unit/examples/contextAvailabilityRequests/registerNewDevice1.json')) + .post( + '/NGSI9/registerContext', + utils.readExampleFile( + './test/unit/examples/contextAvailabilityRequests/registerNewDevice1.json' + ) + ) .reply( - 200, - utils.readExampleFile( - './test/unit/examples/contextAvailabilityResponses/registerNewDevice1Success.json')); + 200, + utils.readExampleFile( + './test/unit/examples/contextAvailabilityResponses/registerNewDevice1Success.json' + ) + ); contextBrokerMock - .post('/v1/subscribeContext', + .post( + '/v1/subscribeContext', utils.readExampleFile( - './test/unit/examples/subscriptionRequests/simpleSubscriptionRequest1.json')) + './test/unit/examples/subscriptionRequests/simpleSubscriptionRequest1.json' + ) + ) .matchHeader('Authorization', 'Bearer eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJ3cHdWclJ3') - .reply(200, + .reply( + 200, utils.readExampleFile( - './test/unit/examples/subscriptionResponses/simpleSubscriptionSuccess.json')); - + './test/unit/examples/subscriptionResponses/simpleSubscriptionSuccess.json' + ) + ); + iotAgentLib.clearAll(function() { request(optionsProvision, function(error, result, body) { done(); @@ -333,21 +343,23 @@ describe('Secured access to the Context Broker with OAuth2 provider', function() }); it('unsubscribe requests use auth header', function(done) { + oauth2Mock + .post( + '/auth/realms/default/protocol/openid-connect/token', + utils.readExampleFile('./test/unit/examples/oauthRequests/getTokenFromTrust.json', true) + ) + .reply(201, utils.readExampleFile('./test/unit/examples/oauthResponses/tokenFromTrust.json'), {}); - oauth2Mock - .post('/auth/realms/default/protocol/openid-connect/token', - utils.readExampleFile('./test/unit/examples/oauthRequests/getTokenFromTrust.json', true)) - .reply( - 201, - utils.readExampleFile('./test/unit/examples/oauthResponses/tokenFromTrust.json'), - {}); - - contextBrokerMock = nock('http://192.168.1.1:1026') - .post('/v1/unsubscribeContext', - utils.readExampleFile('./test/unit/examples/subscriptionRequests/simpleSubscriptionRemove.json')) - .matchHeader('Authorization', 'Bearer eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJ3cHdWclJ3') - .reply(200, - utils.readExampleFile('./test/unit/examples/subscriptionResponses/simpleSubscriptionSuccess.json')); + contextBrokerMock = nock('http://192.168.1.1:1026') + .post( + '/v1/unsubscribeContext', + utils.readExampleFile('./test/unit/examples/subscriptionRequests/simpleSubscriptionRemove.json') + ) + .matchHeader('Authorization', 'Bearer eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJ3cHdWclJ3') + .reply( + 200, + utils.readExampleFile('./test/unit/examples/subscriptionResponses/simpleSubscriptionSuccess.json') + ); iotAgentLib.getDevice('Light1', 'smartGondor', 'electricity', function(error, device) { iotAgentLib.subscribe(device, ['dimming'], null, function(error) { @@ -358,13 +370,11 @@ describe('Secured access to the Context Broker with OAuth2 provider', function() }); }); }); - }); }); describe('Secured access to the Context Broker with OAuth2 provider (FIWARE Keyrock IDM)', function() { - - var values = [ + const values = [ { name: 'state', type: 'Boolean', @@ -391,22 +401,25 @@ describe('Secured access to the Context Broker with OAuth2 provider (FIWARE Keyr nock.cleanAll(); oauth2Mock = nock('http://192.168.1.1:3000') - .post('/oauth2/token', - utils.readExampleFile('./test/unit/examples/oauthRequests/getTokenFromTrust.json', true)) + .post( + '/oauth2/token', + utils.readExampleFile('./test/unit/examples/oauthRequests/getTokenFromTrust.json', true) + ) .reply( 200, utils.readExampleFile('./test/unit/examples/oauthResponses/tokenFromTrustKeyrock.json'), - {}); + {} + ); contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'electricity') .matchHeader('Authorization', 'Bearer c1b752e377680acd1349a3ed59db855a1db07605') - .post('/v1/updateContext', - utils.readExampleFile('./test/unit/examples/contextRequests/updateContext1.json')) - .reply( - 200, - utils.readExampleFile('./test/unit/examples/contextResponses/updateContext1Success.json')); + .post( + '/v1/updateContext', + utils.readExampleFile('./test/unit/examples/contextRequests/updateContext1.json') + ) + .reply(200, utils.readExampleFile('./test/unit/examples/contextResponses/updateContext1Success.json')); iotAgentConfig.authentication.tokenPath = '/oauth2/token'; iotAgentLib.activate(iotAgentConfig, done); @@ -429,30 +442,31 @@ describe('Secured access to the Context Broker with OAuth2 provider (FIWARE Keyr }); describe('When the user requests information about a device in a protected CB', function() { - var attributes = [ - 'state', - 'dimming' - ]; + const attributes = ['state', 'dimming']; beforeEach(function(done) { nock.cleanAll(); oauth2Mock = nock('http://192.168.1.1:3000') - .post('/oauth2/token', - utils.readExampleFile('./test/unit/examples/oauthRequests/getTokenFromTrust.json', true)) + .post( + '/oauth2/token', + utils.readExampleFile('./test/unit/examples/oauthRequests/getTokenFromTrust.json', true) + ) .reply( 200, utils.readExampleFile('./test/unit/examples/oauthResponses/tokenFromTrustKeyrock.json'), - {}); + {} + ); contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'electricity') .matchHeader('Authorization', 'Bearer c1b752e377680acd1349a3ed59db855a1db07605') - .post('/v1/queryContext', - utils.readExampleFile('./test/unit/examples/contextRequests/queryContext1.json')) - .reply(200, - utils.readExampleFile('./test/unit/examples/contextResponses/queryContext1Success.json')); + .post( + '/v1/queryContext', + utils.readExampleFile('./test/unit/examples/contextRequests/queryContext1.json') + ) + .reply(200, utils.readExampleFile('./test/unit/examples/contextResponses/queryContext1Success.json')); iotAgentLib.activate(iotAgentConfig, done); }); @@ -471,11 +485,14 @@ describe('Secured access to the Context Broker with OAuth2 provider (FIWARE Keyr nock.cleanAll(); oauth2Mock = nock('http://192.168.1.1:3000') - .post('/oauth2/token', - utils.readExampleFile('./test/unit/examples/oauthRequests/getTokenFromTrust.json', true)) + .post( + '/oauth2/token', + utils.readExampleFile('./test/unit/examples/oauthRequests/getTokenFromTrust.json', true) + ) .reply( - 400, - utils.readExampleFile('./test/unit/examples/oauthResponses/tokenFromTrustUnauthorizedKeyrock.json')); + 400, + utils.readExampleFile('./test/unit/examples/oauthResponses/tokenFromTrustUnauthorizedKeyrock.json') + ); iotAgentLib.activate(iotAgentConfig, done); }); @@ -494,12 +511,17 @@ describe('Secured access to the Context Broker with OAuth2 provider (FIWARE Keyr nock.cleanAll(); oauth2Mock = nock('http://192.168.1.1:3000') - .post('/oauth2/token', - utils.readExampleFile('./test/unit/examples/oauthRequests/getTokenFromTrust.json', true)) + .post( + '/oauth2/token', + utils.readExampleFile('./test/unit/examples/oauthRequests/getTokenFromTrust.json', true) + ) .reply( - 400, - utils.readExampleFile('./test/unit/examples/oauthResponses/' + - 'tokenFromTrustInvalidCredentialsKeyrock.json'), {}); + 400, + utils.readExampleFile( + './test/unit/examples/oauthResponses/tokenFromTrustInvalidCredentialsKeyrock.json' + ), + {} + ); iotAgentLib.activate(iotAgentConfig, done); }); @@ -518,22 +540,25 @@ describe('Secured access to the Context Broker with OAuth2 provider (FIWARE Keyr nock.cleanAll(); oauth2Mock = nock('http://192.168.1.1:3000') - .post('/oauth2/token', - utils.readExampleFile('./test/unit/examples/oauthRequests/getTokenFromTrust.json', true)) + .post( + '/oauth2/token', + utils.readExampleFile('./test/unit/examples/oauthRequests/getTokenFromTrust.json', true) + ) .reply( 200, utils.readExampleFile('./test/unit/examples/oauthResponses/tokenFromTrustKeyrock.json'), - {}); + {} + ); contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'electricity') .matchHeader('Authorization', 'Bearer c1b752e377680acd1349a3ed59db855a1db07605') - .post('/v1/updateContext', - utils.readExampleFile('./test/unit/examples/contextRequests/updateContext1.json')) - .reply( - 401, - 'Auth-token not found in request header'); + .post( + '/v1/updateContext', + utils.readExampleFile('./test/unit/examples/contextRequests/updateContext1.json') + ) + .reply(401, 'Auth-token not found in request header'); iotAgentLib.activate(iotAgentConfig, done); }); @@ -548,266 +573,330 @@ describe('Secured access to the Context Broker with OAuth2 provider (FIWARE Keyr }); }); -describe('Secured access to the Context Broker with OAuth2 provider (FIWARE Keyrock IDM)' + - 'configured through group provisioning', function() { - var groupCreation = { - url: 'http://localhost:4041/iot/services', - method: 'POST', - json: utils.readExampleFile('./test/unit/examples/groupProvisioningRequests/provisionFullGroup.json'), - headers: { - 'fiware-service': 'TestService', - 'fiware-servicepath': '/testingPath' - } - }; - - var values = [ - { - name: 'status', - type: 'String', - value: 'STARTING' - } - ]; +describe( + 'Secured access to the Context Broker with OAuth2 provider (FIWARE Keyrock IDM)' + + 'configured through group provisioning', + function() { + const groupCreation = { + url: 'http://localhost:4041/iot/services', + method: 'POST', + json: utils.readExampleFile('./test/unit/examples/groupProvisioningRequests/provisionFullGroup.json'), + headers: { + 'fiware-service': 'TestService', + 'fiware-servicepath': '/testingPath' + } + }; - beforeEach(function() { - logger.setLevel('FATAL'); - }); + const values = [ + { + name: 'status', + type: 'String', + value: 'STARTING' + } + ]; - afterEach(function(done) { - iotAgentLib.deactivate(done); - nock.cleanAll(); - }); + beforeEach(function() { + logger.setLevel('FATAL'); + }); - describe('When a measure is sent to the Context Broker via an Update Context operation', function() { - var oauth2Mock2; - var contextBrokerMock2; - beforeEach(function(done) { + afterEach(function(done) { + iotAgentLib.deactivate(done); nock.cleanAll(); - oauth2Mock = nock('http://192.168.1.1:3000') - .post('/oauth2/token', - utils.readExampleFile('./test/unit/examples/oauthRequests/getTokenFromTrustKeyrockGroup.json', true)) - .reply( - 200, - utils.readExampleFile('./test/unit/examples/oauthResponses/tokenFromTrustKeyrock.json'), - {}); + }); - oauth2Mock2 = nock('http://192.168.1.1:3000') - .post('/oauth2/token', - utils.readExampleFile('./test/unit/examples/oauthRequests/getTokenFromTrustKeyrockGroup2.json', true)) - .reply( - 200, - utils.readExampleFile('./test/unit/examples/oauthResponses/tokenFromTrustKeyrock2.json'), - {}); + describe('When a measure is sent to the Context Broker via an Update Context operation', function() { + let oauth2Mock2; + let contextBrokerMock2; + beforeEach(function(done) { + nock.cleanAll(); + oauth2Mock = nock('http://192.168.1.1:3000') + .post( + '/oauth2/token', + utils.readExampleFile( + './test/unit/examples/oauthRequests/getTokenFromTrustKeyrockGroup.json', + true + ) + ) + .reply( + 200, + utils.readExampleFile('./test/unit/examples/oauthResponses/tokenFromTrustKeyrock.json'), + {} + ); + + oauth2Mock2 = nock('http://192.168.1.1:3000') + .post( + '/oauth2/token', + utils.readExampleFile( + './test/unit/examples/oauthRequests/getTokenFromTrustKeyrockGroup2.json', + true + ) + ) + .reply( + 200, + utils.readExampleFile('./test/unit/examples/oauthResponses/tokenFromTrustKeyrock2.json'), + {} + ); + + contextBrokerMock = nock('http://unexistentHost:1026') + .matchHeader('fiware-service', 'TestService') + .matchHeader('fiware-servicepath', '/testingPath') + .matchHeader('Authorization', 'Bearer c1b752e377680acd1349a3ed59db855a1db07605') + .post( + '/v1/updateContext', + utils.readExampleFile('./test/unit/examples/contextRequests/updateContext3WithStatic.json') + ) + .reply( + 200, + utils.readExampleFile('./test/unit/examples/contextResponses/updateContext1Success.json') + ); + + contextBrokerMock2 = nock('http://unexistentHost:1026') + .matchHeader('fiware-service', 'TestService') + .matchHeader('fiware-servicepath', '/testingPath') + .matchHeader('Authorization', 'Bearer bbb752e377680acd1349a3ed59db855a1db076aa') + .post( + '/v1/updateContext', + utils.readExampleFile('./test/unit/examples/contextRequests/updateContext3WithStatic.json') + ) + .reply( + 200, + utils.readExampleFile('./test/unit/examples/contextResponses/updateContext1Success.json') + ); + iotAgentConfig.authentication.tokenPath = '/oauth2/token'; + iotAgentLib.activate(iotAgentConfig, function() { + request(groupCreation, function(error, response, body) { + done(); + }); + }); + }); + it( + 'should ask OAuth2 provider for a token based on the' + + 'trust token and send the generated token in the auth header', + function(done) { + iotAgentLib.update('machine1', 'SensorMachine', '', values, function(error) { + should.not.exist(error); + oauth2Mock.done(); + contextBrokerMock.done(); + done(); + }); + } + ); - contextBrokerMock = nock('http://unexistentHost:1026') - .matchHeader('fiware-service', 'TestService') - .matchHeader('fiware-servicepath', '/testingPath') - .matchHeader('Authorization', 'Bearer c1b752e377680acd1349a3ed59db855a1db07605') - .post('/v1/updateContext', - utils.readExampleFile('./test/unit/examples/contextRequests/updateContext3WithStatic.json')) - .reply(200, - utils.readExampleFile('./test/unit/examples/contextResponses/updateContext1Success.json')); - - contextBrokerMock2 = nock('http://unexistentHost:1026') - .matchHeader('fiware-service', 'TestService') - .matchHeader('fiware-servicepath', '/testingPath') - .matchHeader('Authorization', 'Bearer bbb752e377680acd1349a3ed59db855a1db076aa') - .post('/v1/updateContext', - utils.readExampleFile('./test/unit/examples/contextRequests/updateContext3WithStatic.json')) - .reply(200, - utils.readExampleFile('./test/unit/examples/contextResponses/updateContext1Success.json')); - iotAgentConfig.authentication.tokenPath = '/oauth2/token'; - iotAgentLib.activate(iotAgentConfig, function() { - request(groupCreation, function(error, response, body) { + it('should use the updated trust token in the following requests', function(done) { + iotAgentLib.update('machine1', 'SensorMachine', '', values, function(error) { + should.not.exist(error); + oauth2Mock2.done(); + contextBrokerMock2.done(); done(); }); }); }); - it('should ask OAuth2 provider for a token based on the' + - 'trust token and send the generated token in the auth header', function(done) { - iotAgentLib.update('machine1', 'SensorMachine', '', values, function(error) { - should.not.exist(error); - oauth2Mock.done(); - contextBrokerMock.done(); - done(); + + describe('When a device is provisioned for a configuration contains an OAuth2 trust token', function() { + const values = [ + { + name: 'status', + type: 'String', + value: 'STARTING' + } + ]; + const deviceCreation = { + url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices', + method: 'POST', + json: utils.readExampleFile('./test/unit/examples/deviceProvisioningRequests/provisionNewDevice2.json'), + headers: { + 'fiware-service': 'TestService', + 'fiware-servicepath': '/testingPath' + } + }; + let contextBrokerMock2; + let contextBrokerMock3; + beforeEach(function(done) { + nock.cleanAll(); + + oauth2Mock = nock('http://192.168.1.1:3000') + .post( + '/oauth2/token', + utils.readExampleFile( + './test/unit/examples/oauthRequests/getTokenFromTrustKeyrockGroup3.json', + true + ) + ) + .reply( + 200, + utils.readExampleFile('./test/unit/examples/oauthResponses/tokenFromTrustKeyrock3.json'), + {} + ) + .post( + '/oauth2/token', + utils.readExampleFile( + './test/unit/examples/oauthRequests/getTokenFromTrustKeyrockGroup4.json', + true + ) + ) + .reply( + 200, + utils.readExampleFile('./test/unit/examples/oauthResponses/tokenFromTrustKeyrock4.json'), + {} + ) + .post( + '/oauth2/token', + utils.readExampleFile( + './test/unit/examples/oauthRequests/getTokenFromTrustKeyrockGroup5.json', + true + ) + ) + .reply( + 200, + utils.readExampleFile('./test/unit/examples/oauthResponses/tokenFromTrustKeyrock5.json'), + {} + ); + + contextBrokerMock = nock('http://unexistenthost:1026') + .matchHeader('fiware-service', 'TestService') + .matchHeader('fiware-servicepath', '/testingPath') + .matchHeader('Authorization', 'Bearer asd752e377680acd1349a3ed59db855a1db07ere') + .post( + '/NGSI9/registerContext', + utils.readExampleFile( + './test/unit/examples/contextAvailabilityRequests/registerProvisionedDeviceWithGroup2.json' + ) + ) + .reply( + 200, + utils.readExampleFile( + './test/unit/examples/contextAvailabilityResponses/registerProvisionedDeviceSuccess.json' + ) + ); + + contextBrokerMock2 = nock('http://unexistenthost:1026') + .matchHeader('fiware-service', 'TestService') + .matchHeader('fiware-servicepath', '/testingPath') + .matchHeader('authorization', 'Bearer bea752e377680acd1349a3ed59db855a1db07zxc') + .post( + '/v1/updateContext', + utils.readExampleFile( + './test/unit/examples/contextRequests/createProvisionedDeviceWithGroupAndStatic2.json' + ) + ) + .reply( + 200, + utils.readExampleFile( + './test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json' + ) + ); + + contextBrokerMock3 = nock('http://unexistentHost:1026') + .matchHeader('fiware-service', 'TestService') + .matchHeader('fiware-servicepath', '/testingPath') + .matchHeader('authorization', 'Bearer zzz752e377680acd1349a3ed59db855a1db07bbb') + .post( + '/v1/updateContext', + utils.readExampleFile('./test/unit/examples/contextRequests/updateContext4.json') + ) + .reply( + 200, + utils.readExampleFile('./test/unit/examples/contextResponses/updateContext1Success.json') + ); + + iotAgentConfig.authentication.tokenPath = '/oauth2/token'; + iotAgentLib.activate(iotAgentConfig, function() { + done(); + }); }); - }); - it('should use the updated trust token in the following requests', function(done) { - iotAgentLib.update('machine1', 'SensorMachine', '', values, function(error) { - should.not.exist(error); - oauth2Mock2.done(); - contextBrokerMock2.done(); - done(); + it('should not raise any error', function(done) { + request(deviceCreation, function(error, response, body) { + should.not.exist(error); + response.statusCode.should.equal(201); + contextBrokerMock.done(); + contextBrokerMock2.done(); + done(); + }); }); - }); - }); + it('should send the mixed data to the Context Broker', function(done) { + iotAgentLib.update('Light1', 'SensorMachine', '', values, function(error) { + should.not.exist(error); + contextBrokerMock3.done(); + done(); + }); + }); + }); + } +); - describe('When a device is provisioned for a configuration contains an OAuth2 trust token', function() { - var values = [ - { - name: 'status', - type: 'String', - value: 'STARTING' - } - ]; - var deviceCreation = { - url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices', +describe( + 'Secured access to the Context Broker with OAuth2 provider (FIWARE Keyrock IDM)' + + 'configured through group provisioning. Permanent token', + function() { + const groupCreation = { + url: 'http://localhost:4041/iot/services', method: 'POST', - json: utils.readExampleFile('./test/unit/examples/deviceProvisioningRequests/provisionNewDevice2.json'), + json: utils.readExampleFile('./test/unit/examples/groupProvisioningRequests/provisionFullGroup.json'), headers: { 'fiware-service': 'TestService', 'fiware-servicepath': '/testingPath' } }; - var contextBrokerMock2; - var contextBrokerMock3; - beforeEach(function(done) { - nock.cleanAll(); - - oauth2Mock = nock('http://192.168.1.1:3000') - .post('/oauth2/token', - utils.readExampleFile('./test/unit/examples/oauthRequests/getTokenFromTrustKeyrockGroup3.json', true)) - .reply( - 200, - utils.readExampleFile('./test/unit/examples/oauthResponses/tokenFromTrustKeyrock3.json'), - {}) - .post('/oauth2/token', - utils.readExampleFile('./test/unit/examples/oauthRequests/getTokenFromTrustKeyrockGroup4.json', true)) - .reply( - 200, - utils.readExampleFile('./test/unit/examples/oauthResponses/tokenFromTrustKeyrock4.json'), - {}) - .post('/oauth2/token', - utils.readExampleFile('./test/unit/examples/oauthRequests/getTokenFromTrustKeyrockGroup5.json', true)) - .reply( - 200, - utils.readExampleFile('./test/unit/examples/oauthResponses/tokenFromTrustKeyrock5.json'), - {}); - - - contextBrokerMock = nock('http://unexistenthost:1026') - .matchHeader('fiware-service', 'TestService') - .matchHeader('fiware-servicepath', '/testingPath') - .matchHeader('Authorization', 'Bearer asd752e377680acd1349a3ed59db855a1db07ere') - .post('/NGSI9/registerContext', utils.readExampleFile( - './test/unit/examples/contextAvailabilityRequests/registerProvisionedDeviceWithGroup2.json')) - .reply(200, utils.readExampleFile( - './test/unit/examples/contextAvailabilityResponses/registerProvisionedDeviceSuccess.json')); - - contextBrokerMock2 = nock('http://unexistenthost:1026') - .matchHeader('fiware-service', 'TestService') - .matchHeader('fiware-servicepath', '/testingPath') - .matchHeader('authorization', 'Bearer bea752e377680acd1349a3ed59db855a1db07zxc') - .post('/v1/updateContext', utils.readExampleFile( - './test/unit/examples/contextRequests/createProvisionedDeviceWithGroupAndStatic2.json')) - .reply(200, utils.readExampleFile( - './test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json')); - - contextBrokerMock3 = nock('http://unexistentHost:1026') - - .matchHeader('fiware-service', 'TestService') - .matchHeader('fiware-servicepath', '/testingPath') - .matchHeader('authorization', 'Bearer zzz752e377680acd1349a3ed59db855a1db07bbb') - .post('/v1/updateContext', - utils.readExampleFile('./test/unit/examples/contextRequests/updateContext4.json')) - .reply(200, - utils.readExampleFile('./test/unit/examples/contextResponses/updateContext1Success.json')); - - - iotAgentConfig.authentication.tokenPath = '/oauth2/token'; - iotAgentLib.activate(iotAgentConfig, function() { - done(); - }); - }); - it('should not raise any error', function(done) { - request(deviceCreation, function(error, response, body) { - should.not.exist(error); - response.statusCode.should.equal(201); - contextBrokerMock.done(); - contextBrokerMock2.done(); - done(); - }); - }); + const values = [ + { + name: 'status', + type: 'String', + value: 'STARTING' + } + ]; - it('should send the mixed data to the Context Broker', function(done) { - iotAgentLib.update('Light1', 'SensorMachine', '', values, function(error) { - should.not.exist(error); - contextBrokerMock3.done(); - done(); - }); + beforeEach(function() { + logger.setLevel('FATAL'); + iotAgentConfig.authentication.permanentToken = true; }); - }); -}); - -describe('Secured access to the Context Broker with OAuth2 provider (FIWARE Keyrock IDM)' + - 'configured through group provisioning. Permanent token', function() { - var groupCreation = { - url: 'http://localhost:4041/iot/services', - method: 'POST', - json: utils.readExampleFile('./test/unit/examples/groupProvisioningRequests/provisionFullGroup.json'), - headers: { - 'fiware-service': 'TestService', - 'fiware-servicepath': '/testingPath' - } - }; - - var values = [ - { - name: 'status', - type: 'String', - value: 'STARTING' - } - ]; - - beforeEach(function() { - logger.setLevel('FATAL'); - iotAgentConfig.authentication.permanentToken = true; - }); - - afterEach(function(done) { - iotAgentLib.deactivate(done); - nock.cleanAll(); - }); - - describe('When a measure is sent to the Context Broker via an Update Context operation', function() { - beforeEach(function(done) { + afterEach(function(done) { + iotAgentLib.deactivate(done); nock.cleanAll(); + }); - contextBrokerMock = nock('http://unexistentHost:1026') - .matchHeader('fiware-service', 'TestService') - .matchHeader('fiware-servicepath', '/testingPath') - .matchHeader('Authorization', 'Bearer 999210dacf913772606c95dd0b895d5506cbc988') - .post('/v1/updateContext', - utils.readExampleFile('./test/unit/examples/contextRequests/updateContext3WithStatic.json')) - .reply(200, - utils.readExampleFile('./test/unit/examples/contextResponses/updateContext1Success.json')); + describe('When a measure is sent to the Context Broker via an Update Context operation', function() { + beforeEach(function(done) { + nock.cleanAll(); + contextBrokerMock = nock('http://unexistentHost:1026') + .matchHeader('fiware-service', 'TestService') + .matchHeader('fiware-servicepath', '/testingPath') + .matchHeader('Authorization', 'Bearer 999210dacf913772606c95dd0b895d5506cbc988') + .post( + '/v1/updateContext', + utils.readExampleFile('./test/unit/examples/contextRequests/updateContext3WithStatic.json') + ) + .reply( + 200, + utils.readExampleFile('./test/unit/examples/contextResponses/updateContext1Success.json') + ); - iotAgentConfig.authentication.tokenPath = '/oauth2/token'; - iotAgentLib.activate(iotAgentConfig, function() { - request(groupCreation, function(error, response, body) { - done(); + iotAgentConfig.authentication.tokenPath = '/oauth2/token'; + iotAgentLib.activate(iotAgentConfig, function() { + request(groupCreation, function(error, response, body) { + done(); + }); }); }); - }); - it('should send the permanent token in the auth header', function(done) { - iotAgentLib.update('machine1', 'SensorMachine', '', values, function(error) { - should.not.exist(error); - contextBrokerMock.done(); - done(); + it('should send the permanent token in the auth header', function(done) { + iotAgentLib.update('machine1', 'SensorMachine', '', values, function(error) { + should.not.exist(error); + contextBrokerMock.done(); + done(); + }); }); - }); - it('should use the permanent trust token in the following requests', function(done) { - iotAgentLib.update('machine1', 'SensorMachine', '', values, function(error) { - should.not.exist(error); - contextBrokerMock.done(); - done(); + it('should use the permanent trust token in the following requests', function(done) { + iotAgentLib.update('machine1', 'SensorMachine', '', values, function(error) { + should.not.exist(error); + contextBrokerMock.done(); + done(); + }); }); }); - }); -}); - + } +); diff --git a/test/unit/general/deviceService-test.js b/test/unit/general/deviceService-test.js index 65b87f220..e9a58ede9 100644 --- a/test/unit/general/deviceService-test.js +++ b/test/unit/general/deviceService-test.js @@ -20,154 +20,150 @@ * For those usages not covered by the GNU Affero General Public License * please contact with::[contacto@tid.es] */ -'use strict'; -/* jshint camelcase: false */ +/* eslint-disable no-unused-vars */ -var iotAgentLib = require('../../../lib/fiware-iotagent-lib'), - utils = require('../../tools/utils'), - should = require('should'), - nock = require('nock'), - request = require('request'), - logger = require('logops'), - async = require('async'), - iotAgentConfig = { - contextBroker: { - host: '192.168.1.1', - port: '1026' - }, - server: { - port: 4041 +const iotAgentLib = require('../../../lib/fiware-iotagent-lib'); +const utils = require('../../tools/utils'); +const should = require('should'); +const nock = require('nock'); +const request = require('request'); +const logger = require('logops'); +const async = require('async'); +const iotAgentConfig = { + contextBroker: { + host: '192.168.1.1', + port: '1026' + }, + server: { + port: 4041 + }, + types: { + Light: { + commands: [], + type: 'Light', + lazy: [ + { + name: 'temperature', + type: 'centigrades' + } + ], + active: [ + { + name: 'pressure', + type: 'Hgmm' + } + ] }, - types: { - 'Light': { - commands: [], - type: 'Light', - lazy: [ - { - name: 'temperature', - type: 'centigrades' - } - ], - active: [ - { - name: 'pressure', - type: 'Hgmm' - } - ] - }, - 'BrokenLight': { - commands: [], - lazy: [ - { - name: 'temperature', - type: 'centigrades' - } - ], - active: [ - { - name: 'pressure', - type: 'Hgmm' - } - ] - }, - 'Termometer': { - type: 'Termometer', - commands: [], - lazy: [ - { - name: 'temp', - type: 'kelvin' - } - ], - active: [ - ] - }, - 'Humidity': { - type: 'Humidity', - cbHost: 'http://192.168.1.1:3024', - commands: [], - lazy: [], - active: [ - { - name: 'humidity', - type: 'percentage' - } - ] - }, - 'Motion': { - type: 'Motion', - commands: [], - lazy: [], - staticAttributes: [ - { - 'name': 'location', - 'type': 'Vector', - 'value': '(123,523)' - } - ], - active: [ - { - name: 'humidity', - type: 'percentage' - } - ] - } + BrokenLight: { + commands: [], + lazy: [ + { + name: 'temperature', + type: 'centigrades' + } + ], + active: [ + { + name: 'pressure', + type: 'Hgmm' + } + ] }, - iotManager: { - host: 'localhost', - port: 8082, - path: '/protocols', - protocol: 'MQTT_UL', - description: 'MQTT Ultralight 2.0 IoT Agent (Node.js version)' + Termometer: { + type: 'Termometer', + commands: [], + lazy: [ + { + name: 'temp', + type: 'kelvin' + } + ], + active: [] }, - service: 'smartGondor', - subservice: 'gardens', - providerUrl: 'http://smartGondor.com', - deviceRegistrationDuration: 'P1M' - }, - groupCreation = { - url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/services', - method: 'POST', - json: { - services: [ + Humidity: { + type: 'Humidity', + cbHost: 'http://192.168.1.1:3024', + commands: [], + lazy: [], + active: [ { - resource: '', - apikey: '801230BJKL23Y9090DSFL123HJK09H324HV8732', - entity_type: 'TheLightType', - trust: '8970A9078A803H3BL98PINEQRW8342HBAMS', - cbHost: 'http://unexistentHost:1026', - commands: [], - lazy: [], - attributes: [ - { - name: 'status', - type: 'Boolean' - } - ], - static_attributes: [] + name: 'humidity', + type: 'percentage' } ] }, - headers: { - 'fiware-service': 'TestService', - 'fiware-servicepath': '/testingPath' + Motion: { + type: 'Motion', + commands: [], + lazy: [], + staticAttributes: [ + { + name: 'location', + type: 'Vector', + value: '(123,523)' + } + ], + active: [ + { + name: 'humidity', + type: 'percentage' + } + ] } }, - deviceCreation = { - url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices', - method: 'POST', - json: utils.readExampleFile('./test/unit/examples/deviceProvisioningRequests/provisionNewDevice.json'), - headers: { - 'fiware-service': 'TestService', - 'fiware-servicepath': '/testingPath' - } + iotManager: { + host: 'localhost', + port: 8082, + path: '/protocols', + protocol: 'MQTT_UL', + description: 'MQTT Ultralight 2.0 IoT Agent (Node.js version)' }, - contextBrokerMock, - iotamMock; - + service: 'smartGondor', + subservice: 'gardens', + providerUrl: 'http://smartGondor.com', + deviceRegistrationDuration: 'P1M' +}; +const groupCreation = { + url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/services', + method: 'POST', + json: { + services: [ + { + resource: '', + apikey: '801230BJKL23Y9090DSFL123HJK09H324HV8732', + entity_type: 'TheLightType', + trust: '8970A9078A803H3BL98PINEQRW8342HBAMS', + cbHost: 'http://unexistentHost:1026', + commands: [], + lazy: [], + attributes: [ + { + name: 'status', + type: 'Boolean' + } + ], + static_attributes: [] + } + ] + }, + headers: { + 'fiware-service': 'TestService', + 'fiware-servicepath': '/testingPath' + } +}; +const deviceCreation = { + url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices', + method: 'POST', + json: utils.readExampleFile('./test/unit/examples/deviceProvisioningRequests/provisionNewDevice.json'), + headers: { + 'fiware-service': 'TestService', + 'fiware-servicepath': '/testingPath' + } +}; +let contextBrokerMock; +let iotamMock; -/* jshint camelcase: false */ describe('Device Service: utils', function() { beforeEach(function(done) { nock.cleanAll(); @@ -181,10 +177,7 @@ describe('Device Service: utils', function() { afterEach(function(done) { nock.cleanAll(); - async.series([ - iotAgentLib.clearAll, - iotAgentLib.deactivate - ], done); + async.series([iotAgentLib.clearAll, iotAgentLib.deactivate], done); }); describe('When an existing device tries to be retrieved with retrieveOrCreate()', function() { @@ -193,20 +186,26 @@ describe('Device Service: utils', function() { .matchHeader('fiware-service', 'TestService') .matchHeader('fiware-servicepath', '/testingPath') .post('/NGSI9/registerContext') - .reply(200, utils.readExampleFile( - './test/unit/examples/contextAvailabilityResponses/registerProvisionedDeviceSuccess.json')); + .reply( + 200, + utils.readExampleFile( + './test/unit/examples/contextAvailabilityResponses/registerProvisionedDeviceSuccess.json' + ) + ); contextBrokerMock .matchHeader('fiware-service', 'TestService') .matchHeader('fiware-servicepath', '/testingPath') .post('/v1/updateContext') - .reply(200, utils.readExampleFile( - './test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json')); + .reply( + 200, + utils.readExampleFile('./test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json') + ); - async.series([ - request.bind(request, groupCreation), - request.bind(request, deviceCreation) - ], function(error, results) { + async.series([request.bind(request, groupCreation), request.bind(request, deviceCreation)], function( + error, + results + ) { done(); }); }); @@ -228,46 +227,54 @@ describe('Device Service: utils', function() { .matchHeader('fiware-service', 'TestService') .matchHeader('fiware-servicepath', '/testingPath') .post('/NGSI9/registerContext') - .reply(200, utils.readExampleFile( - './test/unit/examples/contextAvailabilityResponses/registerProvisionedDeviceSuccess.json')); + .reply( + 200, + utils.readExampleFile( + './test/unit/examples/contextAvailabilityResponses/registerProvisionedDeviceSuccess.json' + ) + ); contextBrokerMock .matchHeader('fiware-service', 'TestService') .matchHeader('fiware-servicepath', '/testingPath') .post('/v1/updateContext') - .reply(200, utils.readExampleFile( - './test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json')); + .reply( + 200, + utils.readExampleFile('./test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json') + ); - async.series([ - request.bind(request, groupCreation) - ], function(error, results) { + async.series([request.bind(request, groupCreation)], function(error, results) { done(); }); }); it('should register the device and return it', function(done) { - iotAgentLib.retrieveDevice('UNEXISTENT_DEV', '801230BJKL23Y9090DSFL123HJK09H324HV8732', - function(error, device) { - should.not.exist(error); - should.exist(device); + iotAgentLib.retrieveDevice('UNEXISTENT_DEV', '801230BJKL23Y9090DSFL123HJK09H324HV8732', function( + error, + device + ) { + should.not.exist(error); + should.exist(device); - device.id.should.equal('UNEXISTENT_DEV'); - should.exist(device.protocol); - device.protocol.should.equal('MQTT_UL'); - done(); - }); + device.id.should.equal('UNEXISTENT_DEV'); + should.exist(device.protocol); + device.protocol.should.equal('MQTT_UL'); + done(); + }); }); }); describe('When an unexisting device tries to be retrieved for an unexisting APIKey', function() { it('should raise an error', function(done) { - iotAgentLib.retrieveDevice('UNEXISTENT_DEV_AND_GROUP', 'H2332Y909DSF3H346yh20JK092', - function(error, device) { - should.exist(error); - error.name.should.equal('DEVICE_GROUP_NOT_FOUND'); - should.not.exist(device); - done(); - }); + iotAgentLib.retrieveDevice('UNEXISTENT_DEV_AND_GROUP', 'H2332Y909DSF3H346yh20JK092', function( + error, + device + ) { + should.exist(error); + error.name.should.equal('DEVICE_GROUP_NOT_FOUND'); + should.not.exist(device); + done(); + }); }); }); }); diff --git a/test/unit/general/https-support-test.js b/test/unit/general/https-support-test.js index 5f3b62bce..d05262511 100644 --- a/test/unit/general/https-support-test.js +++ b/test/unit/general/https-support-test.js @@ -23,116 +23,113 @@ * Modified by: Federico M. Facca - Martel Innovate * Modified by: Daniel Calvo - ATOS Research & Innovation */ -'use strict'; -/* jshint camelcase: false */ +/* eslint-disable no-unused-vars */ -var iotAgentLib = require('../../../lib/fiware-iotagent-lib'), - request = require('request'), - nock = require('nock'), - utils = require('../../tools/utils'), - groupRegistryMemory = require('../../../lib/services/groups/groupRegistryMemory'), - should = require('should'), - iotAgentConfig = { - logLevel: 'FATAL', - contextBroker: { - url: 'https://192.168.1.1:1026' - }, - server: { - port: 4041 - }, - types: { - 'Light': { - commands: [], - lazy: [ - { - name: 'temperature', - type: 'centigrades' - } - ], - active: [ - { - name: 'pressure', - type: 'Hgmm' - } - ], - service: 'smartGondor', - subservice: 'gardens' - }, - 'Termometer': { - commands: [], - lazy: [ - { - name: 'temp', - type: 'kelvin' - } - ], - active: [ - ], - service: 'smartGondor', - subservice: 'gardens' - } - }, - service: 'smartGondor', - subservice: 'gardens', - providerUrl: 'http://smartGondor.com', - deviceRegistrationDuration: 'P1M', - iotManager: { - url: 'https://mockediotam.com:9876', - path: '/protocols', - protocol: 'GENERIC_PROTOCOL', - description: 'A generic protocol', - agentPath: '/iot' - }, - defaultResource: '/iot/d' +const iotAgentLib = require('../../../lib/fiware-iotagent-lib'); +const request = require('request'); +const nock = require('nock'); +const utils = require('../../tools/utils'); +const groupRegistryMemory = require('../../../lib/services/groups/groupRegistryMemory'); +const should = require('should'); +const iotAgentConfig = { + logLevel: 'FATAL', + contextBroker: { + url: 'https://192.168.1.1:1026' }, - groupCreation = { - service: 'theService', - subservice: 'theSubService', - resource: '/deviceTest', - apikey: '801230BJKL23Y9090DSFL123HJK09H324HV8732', - type: 'SensorMachine', - trust: '8970A9078A803H3BL98PINEQRW8342HBAMS', - commands: [ - { - name: 'wheel1', - type: 'Wheel' - } - ], - lazy: [ - { - name: 'luminescence', - type: 'Lumens' - } - ], - attributes: [ - { - name: 'status', - type: 'Boolean' - } - ] + server: { + port: 4041 }, - device1 = { - id: 'light1', - type: 'Light', - service: 'smartGondor', - subservice: 'gardens' + types: { + Light: { + commands: [], + lazy: [ + { + name: 'temperature', + type: 'centigrades' + } + ], + active: [ + { + name: 'pressure', + type: 'Hgmm' + } + ], + service: 'smartGondor', + subservice: 'gardens' + }, + Termometer: { + commands: [], + lazy: [ + { + name: 'temp', + type: 'kelvin' + } + ], + active: [], + service: 'smartGondor', + subservice: 'gardens' + } }, - contextBrokerMock, - iotamMock; - + service: 'smartGondor', + subservice: 'gardens', + providerUrl: 'http://smartGondor.com', + deviceRegistrationDuration: 'P1M', + iotManager: { + url: 'https://mockediotam.com:9876', + path: '/protocols', + protocol: 'GENERIC_PROTOCOL', + description: 'A generic protocol', + agentPath: '/iot' + }, + defaultResource: '/iot/d' +}; +const groupCreation = { + service: 'theService', + subservice: 'theSubService', + resource: '/deviceTest', + apikey: '801230BJKL23Y9090DSFL123HJK09H324HV8732', + type: 'SensorMachine', + trust: '8970A9078A803H3BL98PINEQRW8342HBAMS', + commands: [ + { + name: 'wheel1', + type: 'Wheel' + } + ], + lazy: [ + { + name: 'luminescence', + type: 'Lumens' + } + ], + attributes: [ + { + name: 'status', + type: 'Boolean' + } + ] +}; +const device1 = { + id: 'light1', + type: 'Light', + service: 'smartGondor', + subservice: 'gardens' +}; +let contextBrokerMock; +let iotamMock; describe('HTTPS support tests IOTAM', function() { - describe('When the IoT Agents is started with https "iotManager" config', function() { beforeEach(function(done) { nock.cleanAll(); iotamMock = nock('https://mockediotam.com:9876') - .post('/protocols', - utils.readExampleFile('./test/unit/examples/iotamRequests/registrationWithGroupsWithoutCB.json')) - .reply(200, - utils.readExampleFile('./test/unit/examples/iotamResponses/registrationSuccess.json')); + .post( + '/protocols', + utils.readExampleFile('./test/unit/examples/iotamRequests/registrationWithGroupsWithoutCB.json') + ) + .reply(200, utils.readExampleFile('./test/unit/examples/iotamResponses/registrationSuccess.json')); groupRegistryMemory.create(groupCreation, done); }); @@ -155,14 +152,14 @@ describe('HTTPS support tests IOTAM', function() { }); describe('HTTPS support tests', function() { - describe('When subscription is sent to HTTPS context broker', function() { beforeEach(function(done) { - var optionsProvision = { + const optionsProvision = { url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices', method: 'POST', json: utils.readExampleFile( - './test/unit/examples/deviceProvisioningRequests/provisionMinimumDevice.json'), + './test/unit/examples/deviceProvisioningRequests/provisionMinimumDevice.json' + ), headers: { 'fiware-service': 'smartGondor', 'fiware-servicepath': '/gardens' @@ -177,22 +174,34 @@ describe('HTTPS support tests', function() { contextBrokerMock = nock('https://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', '/gardens') - .post('/v1/updateContext', + .post( + '/v1/updateContext', utils.readExampleFile( - './test/unit/examples/contextRequests/createMinimumProvisionedDevice.json')) - .reply(200, + './test/unit/examples/contextRequests/createMinimumProvisionedDevice.json' + ) + ) + .reply( + 200, utils.readExampleFile( - './test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json')); + './test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json' + ) + ); contextBrokerMock = nock('https://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', '/gardens') - .post('/v1/subscribeContext', + .post( + '/v1/subscribeContext', utils.readExampleFile( - './test/unit/examples/subscriptionRequests/simpleSubscriptionRequest.json')) - .reply(200, + './test/unit/examples/subscriptionRequests/simpleSubscriptionRequest.json' + ) + ) + .reply( + 200, utils.readExampleFile( - './test/unit/examples/subscriptionResponses/simpleSubscriptionSuccess.json')); + './test/unit/examples/subscriptionResponses/simpleSubscriptionSuccess.json' + ) + ); iotAgentLib.clearAll(function() { request(optionsProvision, function(error, result, body) { @@ -232,17 +241,25 @@ describe('HTTPS support tests', function() { contextBrokerMock = nock('https://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/NGSI9/registerContext', utils.readExampleFile( - './test/unit/examples/contextAvailabilityRequests/registerIoTAgent1.json')) - .reply(200, utils.readExampleFile( - './test/unit/examples/contextAvailabilityResponses/registerIoTAgent1Success.json')); + .post( + '/NGSI9/registerContext', + utils.readExampleFile('./test/unit/examples/contextAvailabilityRequests/registerIoTAgent1.json') + ) + .reply( + 200, + utils.readExampleFile( + './test/unit/examples/contextAvailabilityResponses/registerIoTAgent1Success.json' + ) + ); contextBrokerMock .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') .post('/v1/updateContext') - .reply(200, utils.readExampleFile( - './test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json')); + .reply( + 200, + utils.readExampleFile('./test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json') + ); iotAgentLib.activate(iotAgentConfig, function(error) { iotAgentLib.clearAll(done); @@ -251,20 +268,19 @@ describe('HTTPS support tests', function() { it('should register as ContextProvider using HTTPS', function(done) { iotAgentLib.register(device1, function(error) { - should.not.exist(error); - contextBrokerMock.done(); - done(); + should.not.exist(error); + contextBrokerMock.done(); + done(); }); }); afterEach(function(done) { - nock.cleanAll(); - iotAgentLib.clearAll(function() { - // We need to remove the registrationId so that the library does not consider next operatios as updates. - delete device1.registrationId; - iotAgentLib.deactivate(done); - }); + nock.cleanAll(); + iotAgentLib.clearAll(function() { + // We need to remove the registrationId so that the library does not consider next operatios as updates. + delete device1.registrationId; + iotAgentLib.deactivate(done); + }); }); - }); }); diff --git a/test/unit/general/iotam-autoregistration-test.js b/test/unit/general/iotam-autoregistration-test.js index d1840f45c..941cf18c6 100644 --- a/test/unit/general/iotam-autoregistration-test.js +++ b/test/unit/general/iotam-autoregistration-test.js @@ -20,171 +20,170 @@ * For those usages not covered by the GNU Affero General Public License * please contact with::[contacto@tid.es] */ -'use strict'; - -/* jshint camelcase: false */ - -var iotAgentLib = require('../../../lib/fiware-iotagent-lib'), - request = require('request'), - nock = require('nock'), - utils = require('../../tools/utils'), - groupRegistryMemory = require('../../../lib/services/groups/groupRegistryMemory'), - should = require('should'), - iotAgentConfig = { - logLevel: 'FATAL', - contextBroker: { - host: '192.168.1.1', - port: '1026' - }, - server: { - port: 4041 - }, - types: { - 'Light': { - commands: [], - type: 'Light', + +/* eslint-disable no-unused-vars */ + +const iotAgentLib = require('../../../lib/fiware-iotagent-lib'); +const request = require('request'); +const nock = require('nock'); +const utils = require('../../tools/utils'); +const groupRegistryMemory = require('../../../lib/services/groups/groupRegistryMemory'); +const should = require('should'); +const iotAgentConfig = { + logLevel: 'FATAL', + contextBroker: { + host: '192.168.1.1', + port: '1026' + }, + server: { + port: 4041 + }, + types: { + Light: { + commands: [], + type: 'Light', + lazy: [ + { + name: 'temperature', + type: 'centigrades' + } + ], + attributes: [ + { + name: 'pressure', + type: 'Hgmm' + } + ] + } + }, + providerUrl: 'http://smartGondor.com', + deviceRegistrationDuration: 'P1M', + iotManager: { + host: 'mockediotam.com', + port: 9876, + path: '/protocols', + protocol: 'GENERIC_PROTOCOL', + description: 'A generic protocol', + agentPath: '/iot' + }, + defaultResource: '/iot/d' +}; +const groupCreation = { + service: 'theService', + subservice: 'theSubService', + resource: '/deviceTest', + apikey: '801230BJKL23Y9090DSFL123HJK09H324HV8732', + type: 'SensorMachine', + trust: '8970A9078A803H3BL98PINEQRW8342HBAMS', + cbHost: 'http://unexistentHost:1026', + commands: [ + { + name: 'wheel1', + type: 'Wheel' + } + ], + lazy: [ + { + name: 'luminescence', + type: 'Lumens' + } + ], + attributes: [ + { + name: 'status', + type: 'Boolean' + } + ] +}; +const optionsCreation = { + url: 'http://localhost:4041/iot/services', + method: 'POST', + json: { + services: [ + { + resource: '/deviceTest', + apikey: '801230BJKL23Y9090DSFL123HJK09H324HV8732', + entity_type: 'SensorMachine', + trust: '8970A9078A803H3BL98PINEQRW8342HBAMS', + cbHost: 'http://unexistentHost:1026', + commands: [ + { + name: 'wheel1', + type: 'Wheel' + } + ], lazy: [ { - name: 'temperature', - type: 'centigrades' + name: 'luminescence', + type: 'Lumens' } ], attributes: [ { - name: 'pressure', - type: 'Hgmm' + name: 'status', + type: 'Boolean' } ] } - }, - providerUrl: 'http://smartGondor.com', - deviceRegistrationDuration: 'P1M', - iotManager: { - host: 'mockediotam.com', - port: 9876, - path: '/protocols', - protocol: 'GENERIC_PROTOCOL', - description: 'A generic protocol', - agentPath: '/iot' - }, - defaultResource: '/iot/d' + ] }, - groupCreation = { - service: 'theService', - subservice: 'theSubService', - resource: '/deviceTest', - apikey: '801230BJKL23Y9090DSFL123HJK09H324HV8732', - type: 'SensorMachine', - trust: '8970A9078A803H3BL98PINEQRW8342HBAMS', - cbHost: 'http://unexistentHost:1026', - commands: [ - { - name: 'wheel1', - type: 'Wheel' - } - ], - lazy: [ - { - name: 'luminescence', - type: 'Lumens' - } - ], - attributes: [ + headers: { + 'fiware-service': 'theService', + 'fiware-servicepath': 'theSubService' + } +}; +const optionsCreationStatic = { + url: 'http://localhost:4041/iot/services', + method: 'POST', + json: { + services: [ { - name: 'status', - type: 'Boolean' + resource: '/deviceTest', + apikey: '801230BJKL23Y9090DSFL123HJK09H324HV8732', + entity_type: 'SensorMachine', + trust: '8970A9078A803H3BL98PINEQRW8342HBAMS', + cbHost: 'http://unexistentHost:1026', + commands: [ + { + name: 'wheel1', + type: 'Wheel' + } + ], + static_attributes: [ + { + name: 'position', + type: 'location', + values: '123,12' + } + ], + attributes: [ + { + name: 'status', + type: 'Boolean' + } + ] } ] }, - optionsCreation = { - url: 'http://localhost:4041/iot/services', - method: 'POST', - json: { - services: [ - { - resource: '/deviceTest', - apikey: '801230BJKL23Y9090DSFL123HJK09H324HV8732', - entity_type: 'SensorMachine', - trust: '8970A9078A803H3BL98PINEQRW8342HBAMS', - cbHost: 'http://unexistentHost:1026', - commands: [ - { - name: 'wheel1', - type: 'Wheel' - } - ], - lazy: [ - { - name: 'luminescence', - type: 'Lumens' - } - ], - attributes: [ - { - name: 'status', - type: 'Boolean' - } - ] - } - ] - }, - headers: { - 'fiware-service': 'theService', - 'fiware-servicepath': 'theSubService' - } + headers: { + 'fiware-service': 'theService', + 'fiware-servicepath': 'theSubService' + } +}; +const optionsDelete = { + url: 'http://localhost:4041/iot/services', + method: 'DELETE', + json: {}, + headers: { + 'fiware-service': 'theService', + 'fiware-servicepath': 'theSubService' }, - optionsCreationStatic = { - url: 'http://localhost:4041/iot/services', - method: 'POST', - json: { - services: [ - { - resource: '/deviceTest', - apikey: '801230BJKL23Y9090DSFL123HJK09H324HV8732', - entity_type: 'SensorMachine', - trust: '8970A9078A803H3BL98PINEQRW8342HBAMS', - cbHost: 'http://unexistentHost:1026', - commands: [ - { - name: 'wheel1', - type: 'Wheel' - } - ], - static_attributes: [ - { - name: 'position', - type: 'location', - values: '123,12' - } - ], - attributes: [ - { - name: 'status', - type: 'Boolean' - } - ] - } - ] - }, - headers: { - 'fiware-service': 'theService', - 'fiware-servicepath': 'theSubService' - } - }, - optionsDelete = { - url: 'http://localhost:4041/iot/services', - method: 'DELETE', - json: {}, - headers: { - 'fiware-service': 'theService', - 'fiware-servicepath': 'theSubService' - }, - qs: { - resource: '/deviceTest', - apikey: '801230BJKL23Y9090DSFL123HJK09H324HV8732' - } - }, - iotamMock; + qs: { + resource: '/deviceTest', + apikey: '801230BJKL23Y9090DSFL123HJK09H324HV8732' + } +}; +let iotamMock; describe('IoT Manager autoregistration', function() { describe('When the IoT Agent is started without a "iotManager" config parameter and empty services', function() { @@ -192,10 +191,8 @@ describe('IoT Manager autoregistration', function() { nock.cleanAll(); iotamMock = nock('http://mockediotam.com:9876') - .post('/protocols', - utils.readExampleFile('./test/unit/examples/iotamRequests/registrationEmpty.json')) - .reply(200, - utils.readExampleFile('./test/unit/examples/iotamResponses/registrationSuccess.json')); + .post('/protocols', utils.readExampleFile('./test/unit/examples/iotamRequests/registrationEmpty.json')) + .reply(200, utils.readExampleFile('./test/unit/examples/iotamResponses/registrationSuccess.json')); }); afterEach(function(done) { @@ -218,10 +215,8 @@ describe('IoT Manager autoregistration', function() { delete iotAgentConfig.providerUrl; iotamMock = nock('http://mockediotam.com:9876') - .post('/protocols', - utils.readExampleFile('./test/unit/examples/iotamRequests/registrationEmpty.json')) - .reply(200, - utils.readExampleFile('./test/unit/examples/iotamResponses/registrationSuccess.json')); + .post('/protocols', utils.readExampleFile('./test/unit/examples/iotamRequests/registrationEmpty.json')) + .reply(200, utils.readExampleFile('./test/unit/examples/iotamResponses/registrationSuccess.json')); }); afterEach(function() { @@ -242,10 +237,11 @@ describe('IoT Manager autoregistration', function() { nock.cleanAll(); iotamMock = nock('http://mockediotam.com:9876') - .post('/protocols', - utils.readExampleFile('./test/unit/examples/iotamRequests/registrationWithGroups.json')) - .reply(200, - utils.readExampleFile('./test/unit/examples/iotamResponses/registrationSuccess.json')); + .post( + '/protocols', + utils.readExampleFile('./test/unit/examples/iotamRequests/registrationWithGroups.json') + ) + .reply(200, utils.readExampleFile('./test/unit/examples/iotamResponses/registrationSuccess.json')); groupRegistryMemory.create(groupCreation, done); }); @@ -270,16 +266,15 @@ describe('IoT Manager autoregistration', function() { nock.cleanAll(); iotamMock = nock('http://mockediotam.com:9876') - .post('/protocols', - utils.readExampleFile('./test/unit/examples/iotamRequests/registrationEmpty.json')) - .reply(200, - utils.readExampleFile('./test/unit/examples/iotamResponses/registrationSuccess.json')); + .post('/protocols', utils.readExampleFile('./test/unit/examples/iotamRequests/registrationEmpty.json')) + .reply(200, utils.readExampleFile('./test/unit/examples/iotamResponses/registrationSuccess.json')); iotamMock - .post('/protocols', - utils.readExampleFile('./test/unit/examples/iotamRequests/registrationWithGroups.json')) - .reply(200, - utils.readExampleFile('./test/unit/examples/iotamResponses/registrationSuccess.json')); + .post( + '/protocols', + utils.readExampleFile('./test/unit/examples/iotamRequests/registrationWithGroups.json') + ) + .reply(200, utils.readExampleFile('./test/unit/examples/iotamResponses/registrationSuccess.json')); iotAgentLib.activate(iotAgentConfig, function(error) { done(); @@ -306,16 +301,15 @@ describe('IoT Manager autoregistration', function() { nock.cleanAll(); iotamMock = nock('http://mockediotam.com:9876') - .post('/protocols', - utils.readExampleFile('./test/unit/examples/iotamRequests/registrationWithGroups.json')) - .reply(200, - utils.readExampleFile('./test/unit/examples/iotamResponses/registrationSuccess.json')); + .post( + '/protocols', + utils.readExampleFile('./test/unit/examples/iotamRequests/registrationWithGroups.json') + ) + .reply(200, utils.readExampleFile('./test/unit/examples/iotamResponses/registrationSuccess.json')); iotamMock - .post('/protocols', - utils.readExampleFile('./test/unit/examples/iotamRequests/registrationEmpty.json')) - .reply(200, - utils.readExampleFile('./test/unit/examples/iotamResponses/registrationSuccess.json')); + .post('/protocols', utils.readExampleFile('./test/unit/examples/iotamRequests/registrationEmpty.json')) + .reply(200, utils.readExampleFile('./test/unit/examples/iotamResponses/registrationSuccess.json')); groupRegistryMemory.create(groupCreation, function() { iotAgentLib.activate(iotAgentConfig, done); @@ -342,16 +336,15 @@ describe('IoT Manager autoregistration', function() { nock.cleanAll(); iotamMock = nock('http://mockediotam.com:9876') - .post('/protocols', - utils.readExampleFile('./test/unit/examples/iotamRequests/registrationEmpty.json')) - .reply(200, - utils.readExampleFile('./test/unit/examples/iotamResponses/registrationSuccess.json')); + .post('/protocols', utils.readExampleFile('./test/unit/examples/iotamRequests/registrationEmpty.json')) + .reply(200, utils.readExampleFile('./test/unit/examples/iotamResponses/registrationSuccess.json')); iotamMock - .post('/protocols', - utils.readExampleFile('./test/unit/examples/iotamRequests/registrationWithStaticGroups.json')) - .reply(200, - utils.readExampleFile('./test/unit/examples/iotamResponses/registrationSuccess.json')); + .post( + '/protocols', + utils.readExampleFile('./test/unit/examples/iotamRequests/registrationWithStaticGroups.json') + ) + .reply(200, utils.readExampleFile('./test/unit/examples/iotamResponses/registrationSuccess.json')); iotAgentLib.activate(iotAgentConfig, function(error) { done(); diff --git a/test/unit/general/loglevel-api_test.js b/test/unit/general/loglevel-api_test.js index ce4311411..1f11745da 100644 --- a/test/unit/general/loglevel-api_test.js +++ b/test/unit/general/loglevel-api_test.js @@ -20,52 +20,51 @@ * For those usages not covered by the GNU Affero General Public License * please contact with::[iot_support@tid.es] */ -'use strict'; - -/* jshint camelcase: false */ - -var iotAgentLib = require('../../../lib/fiware-iotagent-lib'), - should = require('should'), - logger = require('logops'), - request = require('request'), - iotAgentConfig = { - contextBroker: { - host: '192.168.1.1', - port: '1026' - }, - server: { - port: 4041 - }, - types: { - 'Light': { - commands: [], - type: 'Light', - lazy: [ - { - object_id: 't', - name: 'temperature', - type: 'centigrades' - } - ], - active: [ - { - object_id: 'p', - name: 'pressure', - type: 'Hgmm' - }, - { - object_id: 'l', - name: 'luminance', - type: 'lumens' - } - ] - } - }, - service: 'smartGondor', - subservice: 'gardens', - providerUrl: 'http://smartGondor.com', - deviceRegistrationDuration: 'P1M' - }; + +/* eslint-disable no-unused-vars */ + +const iotAgentLib = require('../../../lib/fiware-iotagent-lib'); +const should = require('should'); +const logger = require('logops'); +const request = require('request'); +const iotAgentConfig = { + contextBroker: { + host: '192.168.1.1', + port: '1026' + }, + server: { + port: 4041 + }, + types: { + Light: { + commands: [], + type: 'Light', + lazy: [ + { + object_id: 't', + name: 'temperature', + type: 'centigrades' + } + ], + active: [ + { + object_id: 'p', + name: 'pressure', + type: 'Hgmm' + }, + { + object_id: 'l', + name: 'luminance', + type: 'lumens' + } + ] + } + }, + service: 'smartGondor', + subservice: 'gardens', + providerUrl: 'http://smartGondor.com', + deviceRegistrationDuration: 'P1M' +}; describe('Log level API', function() { beforeEach(function(done) { @@ -87,12 +86,12 @@ describe('Log level API', function() { }); describe('When a new valid log level request comes to the API', function() { - var options = { + const options = { uri: 'http://localhost:' + iotAgentConfig.server.port + '/admin/log', method: 'PUT', headers: { 'Content-Type': 'application/json', - 'Accept': 'application/json' + Accept: 'application/json' }, qs: { level: 'ERROR' @@ -110,12 +109,12 @@ describe('Log level API', function() { }); describe('When the current log level is requested', function() { - var options = { + const options = { uri: 'http://localhost:' + iotAgentConfig.server.port + '/admin/log', method: 'GET', headers: { 'Content-Type': 'application/json', - 'Accept': 'application/json' + Accept: 'application/json' } }; @@ -130,7 +129,7 @@ describe('Log level API', function() { it('should return the current log level', function(done) { request(options, function(error, response, body) { - var parsedBody = JSON.parse(body); + const parsedBody = JSON.parse(body); should.exist(parsedBody.level); parsedBody.level.should.equal('FATAL'); @@ -141,12 +140,12 @@ describe('Log level API', function() { }); describe('When a new log level request comes to the API with an invalid level', function() { - var options = { + const options = { uri: 'http://localhost:' + iotAgentConfig.server.port + '/admin/log', method: 'PUT', headers: { 'Content-Type': 'application/json', - 'Accept': 'application/json' + Accept: 'application/json' }, qs: { level: 'ALLRIGHT' @@ -155,13 +154,11 @@ describe('Log level API', function() { it('should return a 400 error indicating the log level is not valid', function(done) { request(options, function(error, response, body) { - var parsedBody; - should.not.exist(error); response.statusCode.should.equal(400); should.exist(body); - parsedBody = JSON.parse(body); + const parsedBody = JSON.parse(body); parsedBody.error.should.equal('invalid log level'); @@ -171,24 +168,22 @@ describe('Log level API', function() { }); describe('When a new log level request comes to the API without a log level', function() { - var options = { + const options = { uri: 'http://localhost:' + iotAgentConfig.server.port + '/admin/log', method: 'PUT', headers: { 'Content-Type': 'application/json', - 'Accept': 'application/json' + Accept: 'application/json' } }; it('should return a 400 error indicating the log level is missing', function(done) { request(options, function(error, response, body) { - var parsedBody; - should.not.exist(error); response.statusCode.should.equal(400); should.exist(body); - parsedBody = JSON.parse(body); + const parsedBody = JSON.parse(body); parsedBody.error.should.equal('log level missing'); diff --git a/test/unit/general/migration-test.js b/test/unit/general/migration-test.js index 3a3843016..d43758cb4 100644 --- a/test/unit/general/migration-test.js +++ b/test/unit/general/migration-test.js @@ -20,37 +20,47 @@ * For those usages not covered by the GNU Affero General Public License * please contact with::[contacto@tid.es] */ -'use strict'; -/* jshint camelcase: false */ +/* eslint-disable no-unused-vars */ -var migration = require('../../../lib/command/migration'), - mongo = require('mongodb').MongoClient, - mongoUtils = require('../mongodb/mongoDBUtils'), - utils = require('../../tools/utils'), - logger = require('logops'), - async = require('async'), - apply = async.apply, - should = require('should'), - deviceCollection = utils.readExampleFile('./test/unit/examples/mongoCollections/devices.json'), - configurationCollection = utils.readExampleFile('./test/unit/examples/mongoCollections/configurations.json'), - originDb, - targetDb; +const migration = require('../../../lib/command/migration'); +const mongo = require('mongodb').MongoClient; +const mongoUtils = require('../mongodb/mongoDBUtils'); +const utils = require('../../tools/utils'); +const logger = require('logops'); +const async = require('async'); +const apply = async.apply; +const should = require('should'); +const deviceCollection = utils.readExampleFile('./test/unit/examples/mongoCollections/devices.json'); +const configurationCollection = utils.readExampleFile('./test/unit/examples/mongoCollections/configurations.json'); +let originDb; +let targetDb; describe('MongoDB migration', function() { beforeEach(function(done) { logger.setLevel('FATAL'); - mongo.connect('mongodb://localhost:27017/iotOrigin', { useNewUrlParser: true }, function(err, client) { - originDb = client; - mongo.connect('mongodb://localhost:27017/iotTarget', { useNewUrlParser: true }, function(err, client) { - targetDb = client; - async.series([ - apply(mongoUtils.populate, 'localhost', 'iotOrigin', deviceCollection, 'DEVICE'), - apply(mongoUtils.populate, 'localhost', 'iotOrigin', configurationCollection, 'SERVICE') - ], done); - }); - }); + mongo.connect( + 'mongodb://localhost:27017/iotOrigin', + { useNewUrlParser: true }, + function(err, client) { + originDb = client; + mongo.connect( + 'mongodb://localhost:27017/iotTarget', + { useNewUrlParser: true }, + function(err, client) { + targetDb = client; + async.series( + [ + apply(mongoUtils.populate, 'localhost', 'iotOrigin', deviceCollection, 'DEVICE'), + apply(mongoUtils.populate, 'localhost', 'iotOrigin', configurationCollection, 'SERVICE') + ], + done + ); + } + ); + } + ); }); afterEach(function(done) { @@ -66,137 +76,169 @@ describe('MongoDB migration', function() { }); describe('When the full migration command is executed for two databases', function() { - var config = { + const config = { host: 'localhost', port: '27017' }; it('should migrate all the services', function(done) { migration.migrate(config, 'iotOrigin', 'iotTarget', null, null, function() { - targetDb.db().collection('groups').find({}).toArray(function(err, docs) { - should.not.exist(err); - docs.length.should.equal(3); - done(); - }); + targetDb + .db() + .collection('groups') + .find({}) + .toArray(function(err, docs) { + should.not.exist(err); + docs.length.should.equal(3); + done(); + }); }); }); it('should migrate all the devices', function(done) { migration.migrate(config, 'iotOrigin', 'iotTarget', null, null, function() { - targetDb.db().collection('devices').find({}).toArray(function(err, docs) { - should.not.exist(err); - docs.length.should.equal(4); - done(); - }); + targetDb + .db() + .collection('devices') + .find({}) + .toArray(function(err, docs) { + should.not.exist(err); + docs.length.should.equal(4); + done(); + }); }); }); it('should migrate all the fields for each device', function(done) { migration.migrate(config, 'iotOrigin', 'iotTarget', null, null, function() { - targetDb.db().collection('groups').find({ - service: 'dumb_mordor' - }).toArray(function(err, docs) { - should.not.exist(err); - docs.length.should.equal(1); - should.exist(docs[0].apikey); - should.exist(docs[0].cbHost); - should.exist(docs[0].resource); - should.exist(docs[0].service); - should.exist(docs[0].subservice); - should.exist(docs[0].type); - should.exist(docs[0].staticAttributes); - done(); - }); + targetDb + .db() + .collection('groups') + .find({ + service: 'dumb_mordor' + }) + .toArray(function(err, docs) { + should.not.exist(err); + docs.length.should.equal(1); + should.exist(docs[0].apikey); + should.exist(docs[0].cbHost); + should.exist(docs[0].resource); + should.exist(docs[0].service); + should.exist(docs[0].subservice); + should.exist(docs[0].type); + should.exist(docs[0].staticAttributes); + done(); + }); }); }); it('should migrate all the fields for each service', function(done) { migration.migrate(config, 'iotOrigin', 'iotTarget', null, null, function() { - targetDb.db().collection('devices').find({ - id: 'gk20' - }).toArray(function(err, docs) { - should.not.exist(err); - docs.length.should.equal(1); - should.exist(docs[0].id); - should.exist(docs[0].name); - should.exist(docs[0].protocol); - should.exist(docs[0].service); - should.exist(docs[0].subservice); - should.exist(docs[0].type); - should.exist(docs[0].active); - should.exist(docs[0].staticAttributes); - docs[0].id = 'gk20'; - docs[0].name = 'The GK20 Entity'; - docs[0].protocol = 'PDI-IoTA-UltraLight'; - docs[0].service = 'smart_gondor'; - docs[0].subservice = '/gardens'; - docs[0].type = 'acme.lights.sensor'; - done(); - }); + targetDb + .db() + .collection('devices') + .find({ + id: 'gk20' + }) + .toArray(function(err, docs) { + should.not.exist(err); + docs.length.should.equal(1); + should.exist(docs[0].id); + should.exist(docs[0].name); + should.exist(docs[0].protocol); + should.exist(docs[0].service); + should.exist(docs[0].subservice); + should.exist(docs[0].type); + should.exist(docs[0].active); + should.exist(docs[0].staticAttributes); + docs[0].id = 'gk20'; + docs[0].name = 'The GK20 Entity'; + docs[0].protocol = 'PDI-IoTA-UltraLight'; + docs[0].service = 'smart_gondor'; + docs[0].subservice = '/gardens'; + docs[0].type = 'acme.lights.sensor'; + done(); + }); }); }); }); describe('When a service migration command is executed', function() { - var config = { + const config = { host: 'localhost', port: '27017' }; - it('should migrate just the service\'s configurations', function(done) { + it("should migrate just the service's configurations", function(done) { migration.migrate(config, 'iotOrigin', 'iotTarget', 'smart_gondor', null, function() { - targetDb.db().collection('groups').find({}).toArray(function(err, docs) { - should.not.exist(err); - docs.length.should.equal(1); - done(); - }); + targetDb + .db() + .collection('groups') + .find({}) + .toArray(function(err, docs) { + should.not.exist(err); + docs.length.should.equal(1); + done(); + }); }); }); - it('should migrate just the service\'s devices', function(done) { + it("should migrate just the service's devices", function(done) { migration.migrate(config, 'iotOrigin', 'iotTarget', 'smart_gondor', null, function() { - targetDb.db().collection('devices').find({}).toArray(function(err, docs) { - should.not.exist(err); - docs.length.should.equal(3); - done(); - }); + targetDb + .db() + .collection('devices') + .find({}) + .toArray(function(err, docs) { + should.not.exist(err); + docs.length.should.equal(3); + done(); + }); }); }); }); describe('When a device has an empty string in its name', function() { - var config = { + const config = { host: 'localhost', port: '27017' }; it('should set the name as undefined', function(done) { migration.migrate(config, 'iotOrigin', 'iotTarget', 'dumb_mordor', null, function() { - targetDb.db().collection('devices').find({}).toArray(function(err, docs) { - docs.length.should.equal(1); - should.exist(docs[0].name); - docs[0].name.should.equal(docs[0].type + ':' + docs[0].id); - done(); - }); + targetDb + .db() + .collection('devices') + .find({}) + .toArray(function(err, docs) { + docs.length.should.equal(1); + should.exist(docs[0].name); + docs[0].name.should.equal(docs[0].type + ':' + docs[0].id); + done(); + }); }); }); }); describe('When a subservice migration command is executed', function() { - var config = { + const config = { host: 'localhost', port: '27017' }; - it('should migrate just the subservice\'s devices', function(done) { + it("should migrate just the subservice's devices", function(done) { migration.migrate(config, 'iotOrigin', 'iotTarget', 'smart_gondor', '/gardens', function() { - targetDb.db().collection('devices').find({}).toArray(function(err, docs) { - should.not.exist(err); - docs.length.should.equal(1); - done(); - }); + targetDb + .db() + .collection('devices') + .find({}) + .toArray(function(err, docs) { + should.not.exist(err); + docs.length.should.equal(1); + done(); + }); }); }); }); describe('When a subservice migration configuration has a protocol translation table', function() { - var config = { + const config = { host: 'localhost', port: '27017', protocols: { @@ -206,12 +248,16 @@ describe('MongoDB migration', function() { it('should change the protocol to the translated one', function(done) { migration.migrate(config, 'iotOrigin', 'iotTarget', 'smart_gondor', '/gardens', function() { - targetDb.db().collection('devices').find({}).toArray(function(err, docs) { - should.not.exist(err); - docs.length.should.equal(1); - docs[0].protocol.should.equal('NODE-Ultralight'); - done(); - }); + targetDb + .db() + .collection('devices') + .find({}) + .toArray(function(err, docs) { + should.not.exist(err); + docs.length.should.equal(1); + docs[0].protocol.should.equal('NODE-Ultralight'); + done(); + }); }); }); }); diff --git a/test/unit/general/startup-test.js b/test/unit/general/startup-test.js index bcedc6e3e..4d38a54e9 100644 --- a/test/unit/general/startup-test.js +++ b/test/unit/general/startup-test.js @@ -20,47 +20,48 @@ * For those usages not covered by the GNU Affero General Public License * please contact with::[contacto@tid.es] */ -'use strict'; -var iotAgentLib = require('../../../lib/fiware-iotagent-lib'), - should = require('should'), - nock = require('nock'), - utils = require('../../tools/utils'), - config = require('../../../lib/commonConfig'), - _ = require('underscore'), - iotAgentConfig = { - logLevel: 'ERROR', - contextBroker: { - host: '192.168.1.1', - port: '1026' - }, - server: { - port: 4041 - }, - types: { - 'Light': { - commands: [], - type: 'Light', - lazy: [ - { - name: 'temperature', - type: 'centigrades' - } - ], - attributes: [ - { - name: 'pressure', - type: 'Hgmm' - } - ] - } - }, - providerUrl: 'http://smartGondor.com', - deviceRegistrationDuration: 'P1M' +/* eslint-disable no-unused-vars */ + +const iotAgentLib = require('../../../lib/fiware-iotagent-lib'); +const should = require('should'); +const nock = require('nock'); +const utils = require('../../tools/utils'); +const config = require('../../../lib/commonConfig'); +const _ = require('underscore'); +const iotAgentConfig = { + logLevel: 'ERROR', + contextBroker: { + host: '192.168.1.1', + port: '1026' + }, + server: { + port: 4041 + }, + types: { + Light: { + commands: [], + type: 'Light', + lazy: [ + { + name: 'temperature', + type: 'centigrades' + } + ], + attributes: [ + { + name: 'pressure', + type: 'Hgmm' + } + ] + } }, - iotAgentConfigNoUrl = _.clone(iotAgentConfig), - iotAgentConfigNoTypes = _.clone(iotAgentConfig), - iotamMock; + providerUrl: 'http://smartGondor.com', + deviceRegistrationDuration: 'P1M' +}; +const iotAgentConfigNoUrl = _.clone(iotAgentConfig); +const iotAgentConfigNoTypes = _.clone(iotAgentConfig); +let iotamMock; describe('Startup tests', function() { describe('When the IoT Agent is started without a "providerUrl" config parameter', function() { diff --git a/test/unit/general/statistics-persistence_test.js b/test/unit/general/statistics-persistence_test.js index 819ea948c..f900d862c 100644 --- a/test/unit/general/statistics-persistence_test.js +++ b/test/unit/general/statistics-persistence_test.js @@ -20,46 +20,46 @@ * For those usages not covered by the GNU Affero General Public License * please contact with::[contacto@tid.es] */ -'use strict'; -var statsService = require('../../../lib/services/stats/statsRegistry'), - commonConfig = require('../../../lib/commonConfig'), - iotAgentLib = require('../../../lib/fiware-iotagent-lib'), - should = require('should'), - async = require('async'), - mongoUtils = require('../mongodb/mongoDBUtils'), - iotAgentConfig = { - logLevel: 'FATAL', - contextBroker: { - host: '192.168.1.1', - port: '1026' - }, - server: { - port: 4041, - baseRoot: '/' - }, - stats: { - interval: 50, - persistence: true - }, - mongodb: { - host: 'localhost', - port: '27017', - db: 'iotagent' - }, - types: {}, - service: 'smartGondor', - subservice: 'gardens', - providerUrl: 'http://smartGondor.com', - deviceRegistrationDuration: 'P1M' +/* eslint-disable no-unused-vars */ + +const statsService = require('../../../lib/services/stats/statsRegistry'); +const commonConfig = require('../../../lib/commonConfig'); +const iotAgentLib = require('../../../lib/fiware-iotagent-lib'); +const should = require('should'); +const async = require('async'); +const mongoUtils = require('../mongodb/mongoDBUtils'); +const iotAgentConfig = { + logLevel: 'FATAL', + contextBroker: { + host: '192.168.1.1', + port: '1026' + }, + server: { + port: 4041, + baseRoot: '/' + }, + stats: { + interval: 50, + persistence: true }, - iotAgentDb, - oldConfig; + mongodb: { + host: 'localhost', + port: '27017', + db: 'iotagent' + }, + types: {}, + service: 'smartGondor', + subservice: 'gardens', + providerUrl: 'http://smartGondor.com', + deviceRegistrationDuration: 'P1M' +}; +let iotAgentDb; +let oldConfig; describe('Statistics persistence service', function() { - function insertDummy(n, callback) { - iotAgentDb.collection('tests').insertOne({test: 'test'}, function() { + iotAgentDb.collection('tests').insertOne({ test: 'test' }, function() { callback(); }); } @@ -89,23 +89,29 @@ describe('Statistics persistence service', function() { describe('When a periodic persitence action is set', function() { beforeEach(function(done) { - statsService.globalLoad({ - stat1: 10 - }, function() { - statsService.add('stat1', 5, done); - }); + statsService.globalLoad( + { + stat1: 10 + }, + function() { + statsService.add('stat1', 5, done); + } + ); }); it('should store all the records in the database', function(done) { statsService.addTimerAction(statsService.mongodbPersistence, function() { setTimeout(function() { statsService.clearTimers(function() { - iotAgentDb.collection('kpis').find({}).toArray(function(err, docs) { - should.not.exist(err); - should.exist(docs); - docs.length.should.be.above(2); - done(); - }); + iotAgentDb + .collection('kpis') + .find({}) + .toArray(function(err, docs) { + should.not.exist(err); + should.exist(docs); + docs.length.should.be.above(2); + done(); + }); }); }, 200); }); diff --git a/test/unit/general/statistics-service_test.js b/test/unit/general/statistics-service_test.js index f29c3670d..9806fc49f 100644 --- a/test/unit/general/statistics-service_test.js +++ b/test/unit/general/statistics-service_test.js @@ -20,31 +20,30 @@ * For those usages not covered by the GNU Affero General Public License * please contact with::[contacto@tid.es] */ -'use strict'; -var statsService = require('../../../lib/services/stats/statsRegistry'), - should = require('should'), - commonConfig = require('../../../lib/commonConfig'), - iotAgentConfig = { - logLevel: 'FATAL', - contextBroker: { - host: '192.168.1.1', - port: '1026' - }, - server: { - port: 4041, - baseRoot: '/' - }, - stats: { - interval: 100 - }, - types: {}, - service: 'smartGondor', - subservice: 'gardens', - providerUrl: 'http://smartGondor.com', - deviceRegistrationDuration: 'P1M' +const statsService = require('../../../lib/services/stats/statsRegistry'); +const should = require('should'); +const commonConfig = require('../../../lib/commonConfig'); +const iotAgentConfig = { + logLevel: 'FATAL', + contextBroker: { + host: '192.168.1.1', + port: '1026' }, - oldConfig; + server: { + port: 4041, + baseRoot: '/' + }, + stats: { + interval: 100 + }, + types: {}, + service: 'smartGondor', + subservice: 'gardens', + providerUrl: 'http://smartGondor.com', + deviceRegistrationDuration: 'P1M' +}; +let oldConfig; describe('Statistics service', function() { beforeEach(function(done) { @@ -62,13 +61,16 @@ describe('Statistics service', function() { }); describe('When a new statistic is updated with add()', function() { - var statName = 'fakeStat', - statValue = 2; + const statName = 'fakeStat'; + const statValue = 2; beforeEach(function(done) { - statsService.globalLoad({ - fakeStat: 30 - }, done); + statsService.globalLoad( + { + fakeStat: 30 + }, + done + ); }); it('should appear the modified value in the getCurrent() statistics', function(done) { @@ -94,10 +96,13 @@ describe('Statistics service', function() { }); describe('When the global statistics are requested', function() { beforeEach(function(done) { - statsService.globalLoad({ - stat1: 82, - stat2: 38789 - }, done); + statsService.globalLoad( + { + stat1: 82, + stat2: 38789 + }, + done + ); }); it('should return all the statistics that were created', function(done) { @@ -136,16 +141,19 @@ describe('Statistics service', function() { }); }); describe('When a new periodic stats action is set', function() { - var valueCurrent = 0, - valueGlobal = 0, - times = 0; + let valueCurrent = 0; + let valueGlobal = 0; + let times = 0; beforeEach(function(done) { - statsService.globalLoad({ - stat1: 10 - }, function() { - statsService.add('stat1', 5, done); - }); + statsService.globalLoad( + { + stat1: 10 + }, + function() { + statsService.add('stat1', 5, done); + } + ); }); function mockedAction(current, global, callback) { diff --git a/test/unit/lazyAndCommands/active-devices-attribute-update-test.js b/test/unit/lazyAndCommands/active-devices-attribute-update-test.js index 5861375b3..b1c0187e0 100644 --- a/test/unit/lazyAndCommands/active-devices-attribute-update-test.js +++ b/test/unit/lazyAndCommands/active-devices-attribute-update-test.js @@ -20,50 +20,50 @@ * For those usages not covered by the GNU Affero General Public License * please contact with::[contacto@tid.es] */ -'use strict'; -var iotAgentLib = require('../../../lib/fiware-iotagent-lib'), - utils = require('../../tools/utils'), - should = require('should'), - logger = require('logops'), - nock = require('nock'), - mongoUtils = require('../mongodb/mongoDBUtils'), - request = require('request'), - contextBrokerMock, - iotAgentConfig = { - logLevel: 'FATAL', - contextBroker: { - host: '192.168.1.1', - port: '1026' - }, - server: { - port: 4041 - }, - types: { - 'Light': { - // commands are not defined - active: [ - { - name: 'pressure', - type: 'Hgmm' - } - ] - } - }, - service: 'smartGondor', - subservice: 'gardens', - providerUrl: 'http://smartGondor.com', - deviceRegistrationDuration: 'P1M' +/* eslint-disable no-unused-vars */ + +const iotAgentLib = require('../../../lib/fiware-iotagent-lib'); +const utils = require('../../tools/utils'); +const should = require('should'); +const logger = require('logops'); +const nock = require('nock'); +const mongoUtils = require('../mongodb/mongoDBUtils'); +const request = require('request'); +let contextBrokerMock; +const iotAgentConfig = { + logLevel: 'FATAL', + contextBroker: { + host: '192.168.1.1', + port: '1026' + }, + server: { + port: 4041 }, - device = { - id: 'somelight', - type: 'Light', - service: 'smartGondor', - subservice: 'gardens' - }; + types: { + Light: { + // commands are not defined + active: [ + { + name: 'pressure', + type: 'Hgmm' + } + ] + } + }, + service: 'smartGondor', + subservice: 'gardens', + providerUrl: 'http://smartGondor.com', + deviceRegistrationDuration: 'P1M' +}; +const device = { + id: 'somelight', + type: 'Light', + service: 'smartGondor', + subservice: 'gardens' +}; describe('Update attribute functionalities', function() { - beforeEach(function(done) { logger.setLevel('FATAL'); @@ -73,15 +73,19 @@ describe('Update attribute functionalities', function() { .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') .post('/NGSI9/registerContext') - .reply(200, utils.readExampleFile( - './test/unit/examples/contextAvailabilityResponses/registerIoTAgent1Success.json')); + .reply( + 200, + utils.readExampleFile('./test/unit/examples/contextAvailabilityResponses/registerIoTAgent1Success.json') + ); contextBrokerMock .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') .post('/v1/updateContext') - .reply(200, utils.readExampleFile( - './test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json')); + .reply( + 200, + utils.readExampleFile('./test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json') + ); iotAgentLib.activate(iotAgentConfig, done); }); @@ -100,7 +104,7 @@ describe('Update attribute functionalities', function() { }); describe('When a attribute update arrives to the IoT Agent as Context Provider', function() { - var options = { + const options = { url: 'http://localhost:' + iotAgentConfig.server.port + '/v1/updateContext', method: 'POST', json: { @@ -136,7 +140,7 @@ describe('Update attribute functionalities', function() { }); it('should call the client handler with correct values, even if commands are not defined', function(done) { - var handlerCalled = false; + let handlerCalled = false; iotAgentLib.setDataUpdateHandler(function(id, type, service, subservice, attributes, callback) { id.should.equal('Light:somelight'); @@ -148,13 +152,12 @@ describe('Update attribute functionalities', function() { handlerCalled = true; callback(null, { - id: id, - type: type, - attributes: attributes + id, + type, + attributes }); }); - request(options, function(error, response, body) { should.not.exist(error); handlerCalled.should.equal(true); diff --git a/test/unit/lazyAndCommands/command-test.js b/test/unit/lazyAndCommands/command-test.js index 28e796e46..fed93563c 100644 --- a/test/unit/lazyAndCommands/command-test.js +++ b/test/unit/lazyAndCommands/command-test.js @@ -20,92 +20,92 @@ * For those usages not covered by the GNU Affero General Public License * please contact with::[contacto@tid.es] */ -'use strict'; -var iotAgentLib = require('../../../lib/fiware-iotagent-lib'), - utils = require('../../tools/utils'), - should = require('should'), - logger = require('logops'), - nock = require('nock'), - mongoUtils = require('../mongodb/mongoDBUtils'), - request = require('request'), - contextBrokerMock, - statusAttributeMock, - iotAgentConfig = { - contextBroker: { - host: '192.168.1.1', - port: '1026' +/* eslint-disable no-unused-vars */ + +const iotAgentLib = require('../../../lib/fiware-iotagent-lib'); +const utils = require('../../tools/utils'); +const should = require('should'); +const logger = require('logops'); +const nock = require('nock'); +const mongoUtils = require('../mongodb/mongoDBUtils'); +const request = require('request'); +let contextBrokerMock; +let statusAttributeMock; +const iotAgentConfig = { + contextBroker: { + host: '192.168.1.1', + port: '1026' + }, + server: { + port: 4041 + }, + types: { + Light: { + commands: [], + lazy: [ + { + name: 'temperature', + type: 'centigrades' + } + ], + active: [ + { + name: 'pressure', + type: 'Hgmm' + } + ] }, - server: { - port: 4041 + Termometer: { + commands: [], + lazy: [ + { + name: 'temp', + type: 'kelvin' + } + ], + active: [] }, - types: { - 'Light': { - commands: [], - lazy: [ - { - name: 'temperature', - type: 'centigrades' - } - ], - active: [ - { - name: 'pressure', - type: 'Hgmm' - } - ] - }, - 'Termometer': { - commands: [], - lazy: [ - { - name: 'temp', - type: 'kelvin' - } - ], - active: [ - ] - }, - 'Motion': { - commands: [], - lazy: [ - { - name: 'moving', - type: 'Boolean' - } - ], - staticAttributes: [ - { - 'name': 'location', - 'type': 'Vector', - 'value': '(123,523)' - } - ], - active: [] - }, - 'Robot': { - commands: [ - { - name: 'position', - type: 'Array' - } - ], - lazy: [], - staticAttributes: [], - active: [] - } + Motion: { + commands: [], + lazy: [ + { + name: 'moving', + type: 'Boolean' + } + ], + staticAttributes: [ + { + name: 'location', + type: 'Vector', + value: '(123,523)' + } + ], + active: [] }, - service: 'smartGondor', - subservice: 'gardens', - providerUrl: 'http://smartGondor.com', - deviceRegistrationDuration: 'P1M' + Robot: { + commands: [ + { + name: 'position', + type: 'Array' + } + ], + lazy: [], + staticAttributes: [], + active: [] + } }, - device3 = { - id: 'r2d2', - type: 'Robot', - service: 'smartGondor', - subservice: 'gardens' - }; + service: 'smartGondor', + subservice: 'gardens', + providerUrl: 'http://smartGondor.com', + deviceRegistrationDuration: 'P1M' +}; +const device3 = { + id: 'r2d2', + type: 'Robot', + service: 'smartGondor', + subservice: 'gardens' +}; describe('Command functionalities', function() { beforeEach(function(done) { @@ -116,24 +116,29 @@ describe('Command functionalities', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/NGSI9/registerContext', - utils.readExampleFile('./test/unit/examples/contextAvailabilityRequests/registerIoTAgentCommands.json')) - .reply(200, - utils.readExampleFile('./test/unit/examples/contextAvailabilityResponses/registerIoTAgent1Success.json')); + .post( + '/NGSI9/registerContext', + utils.readExampleFile('./test/unit/examples/contextAvailabilityRequests/registerIoTAgentCommands.json') + ) + .reply( + 200, + utils.readExampleFile('./test/unit/examples/contextAvailabilityResponses/registerIoTAgent1Success.json') + ); contextBrokerMock .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') .post('/v1/updateContext') - .reply(200, - utils.readExampleFile( - './test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json')); + .reply( + 200, + utils.readExampleFile('./test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json') + ); iotAgentLib.activate(iotAgentConfig, done); }); afterEach(function(done) { - delete(device3.registrationId); + delete device3.registrationId; iotAgentLib.clearAll(function() { iotAgentLib.deactivate(function() { mongoUtils.cleanDbs(function() { @@ -156,7 +161,7 @@ describe('Command functionalities', function() { }); }); describe('When a command update arrives to the IoT Agent as Context Provider', function() { - var options = { + const options = { url: 'http://localhost:' + iotAgentConfig.server.port + '/v1/updateContext', method: 'POST', json: { @@ -186,10 +191,16 @@ describe('Command functionalities', function() { statusAttributeMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v1/updateContext', - utils.readExampleFile('./test/unit/examples/contextRequests/updateContextCommandStatus.json')) - .reply(200, - utils.readExampleFile('./test/unit/examples/contextResponses/updateContextCommandStatusSuccess.json')); + .post( + '/v1/updateContext', + utils.readExampleFile('./test/unit/examples/contextRequests/updateContextCommandStatus.json') + ) + .reply( + 200, + utils.readExampleFile( + './test/unit/examples/contextResponses/updateContextCommandStatusSuccess.json' + ) + ); iotAgentLib.register(device3, function(error) { done(); @@ -197,7 +208,7 @@ describe('Command functionalities', function() { }); it('should call the client handler', function(done) { - var handlerCalled = false; + let handlerCalled = false; iotAgentLib.setCommandHandler(function(id, type, service, subservice, attributes, callback) { id.should.equal(device3.type + ':' + device3.id); @@ -206,8 +217,8 @@ describe('Command functionalities', function() { attributes[0].value.should.equal('[28, -104, 23]'); handlerCalled = true; callback(null, { - id: id, - type: type, + id, + type, attributes: [ { name: 'position', @@ -227,8 +238,8 @@ describe('Command functionalities', function() { it('should create the attribute with the "_status" prefix in the Context Broker', function(done) { iotAgentLib.setCommandHandler(function(id, type, service, subservice, attributes, callback) { callback(null, { - id: id, - type: type, + id, + type, attributes: [ { name: 'position', @@ -246,13 +257,13 @@ describe('Command functionalities', function() { }); }); it('should create the attribute with the "_status" prefix in the Context Broker', function(done) { - var serviceAndSubservice = false; + let serviceAndSubservice = false; iotAgentLib.setCommandHandler(function(id, type, service, subservice, attributes, callback) { serviceAndSubservice = service === 'smartGondor' && subservice === 'gardens'; callback(null, { - id: id, - type: type, + id, + type, attributes: [ { name: 'position', @@ -274,10 +285,16 @@ describe('Command functionalities', function() { statusAttributeMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v1/updateContext', - utils.readExampleFile('./test/unit/examples/contextRequests/updateContextCommandFinish.json')) - .reply(200, - utils.readExampleFile('./test/unit/examples/contextResponses/updateContextCommandFinishSuccess.json')); + .post( + '/v1/updateContext', + utils.readExampleFile('./test/unit/examples/contextRequests/updateContextCommandFinish.json') + ) + .reply( + 200, + utils.readExampleFile( + './test/unit/examples/contextResponses/updateContextCommandFinishSuccess.json' + ) + ); iotAgentLib.register(device3, function(error) { done(); @@ -285,12 +302,11 @@ describe('Command functionalities', function() { }); it('should update its value and status in the Context Broker', function(done) { - iotAgentLib.setCommandResult('r2d2', 'Robot', '', 'position', '[72, 368, 1]', 'FINISHED', - function(error) { - should.not.exist(error); - statusAttributeMock.done(); - done(); - }); + iotAgentLib.setCommandResult('r2d2', 'Robot', '', 'position', '[72, 368, 1]', 'FINISHED', function(error) { + should.not.exist(error); + statusAttributeMock.done(); + done(); + }); }); }); describe('When an error command arrives from the south bound for a registered command', function() { @@ -298,10 +314,16 @@ describe('Command functionalities', function() { statusAttributeMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v1/updateContext', - utils.readExampleFile('./test/unit/examples/contextRequests/updateContextCommandError.json')) - .reply(200, - utils.readExampleFile('./test/unit/examples/contextResponses/updateContextCommandStatusSuccess.json')); + .post( + '/v1/updateContext', + utils.readExampleFile('./test/unit/examples/contextRequests/updateContextCommandError.json') + ) + .reply( + 200, + utils.readExampleFile( + './test/unit/examples/contextResponses/updateContextCommandStatusSuccess.json' + ) + ); iotAgentLib.register(device3, function(error) { done(); @@ -309,12 +331,11 @@ describe('Command functionalities', function() { }); it('should update its status in the Context Broker', function(done) { - iotAgentLib.setCommandResult('r2d2', 'Robot', '', 'position', 'Stalled', 'ERROR', - function(error) { - should.not.exist(error); - statusAttributeMock.done(); - done(); - }); + iotAgentLib.setCommandResult('r2d2', 'Robot', '', 'position', 'Stalled', 'ERROR', function(error) { + should.not.exist(error); + statusAttributeMock.done(); + done(); + }); }); }); }); diff --git a/test/unit/lazyAndCommands/commandRegistry_test.js b/test/unit/lazyAndCommands/commandRegistry_test.js index 57594f076..d4c966956 100644 --- a/test/unit/lazyAndCommands/commandRegistry_test.js +++ b/test/unit/lazyAndCommands/commandRegistry_test.js @@ -20,42 +20,43 @@ * For those usages not covered by the GNU Affero General Public License * please contact with::daniel.moranjimenez@telefonica.com */ -'use strict'; - -var iotAgentLib = require('../../../lib/fiware-iotagent-lib'), - async = require('async'), - should = require('should'), - iotAgentConfig = { - logLevel: 'FATAL', - contextBroker: { - host: '192.168.1.1', - port: '1026' - }, - server: { - name: 'testAgent', - port: 4041, - baseRoot: '/' - }, - types: {}, - deviceRegistry: { - type: 'memory' - }, - mongodb: { - host: 'localhost', - port: '27017', - db: 'iotagent' - }, - service: 'smartGondor', - subservice: 'gardens', - providerUrl: 'http://smartGondor.com', - deviceRegistrationDuration: 'P1M', - pollingExpiration: 800, - pollingDaemonFrequency: 20 - }; + +/* eslint-disable no-unused-vars */ + +const iotAgentLib = require('../../../lib/fiware-iotagent-lib'); +const async = require('async'); +const should = require('should'); +const iotAgentConfig = { + logLevel: 'FATAL', + contextBroker: { + host: '192.168.1.1', + port: '1026' + }, + server: { + name: 'testAgent', + port: 4041, + baseRoot: '/' + }, + types: {}, + deviceRegistry: { + type: 'memory' + }, + mongodb: { + host: 'localhost', + port: '27017', + db: 'iotagent' + }, + service: 'smartGondor', + subservice: 'gardens', + providerUrl: 'http://smartGondor.com', + deviceRegistrationDuration: 'P1M', + pollingExpiration: 800, + pollingDaemonFrequency: 20 +}; function testRegistry(registryType) { describe('Command registries test [' + registryType + ']', function() { - var commandTemplate = { + const commandTemplate = { name: 'commandName', type: 'commandType', value: 'commandValue' @@ -107,7 +108,7 @@ function testRegistry(registryType) { }); describe('When an already existing command arrives to the registry', function() { - var updatedCommand = { + const updatedCommand = { name: 'commandName', type: 'commandType', value: 'newValueForTheCommand' @@ -137,24 +138,18 @@ function testRegistry(registryType) { describe('When a command listing is requested for a device', function() { beforeEach(function(done) { - var commands = []; + const commands = []; - for (var i = 0; i < 3; i++) { - for (var j = 0; j < 5; j++) { - var newCommand = { + for (let i = 0; i < 3; i++) { + for (let j = 0; j < 5; j++) { + const newCommand = { name: commandTemplate.name + j, type: commandTemplate.type + j, value: commandTemplate.value + j }; commands.push( - async.apply( - iotAgentLib.addCommand, - 'smartGondor', - 'gardens', - 'devId' + i, - newCommand - ) + async.apply(iotAgentLib.addCommand, 'smartGondor', 'gardens', 'devId' + i, newCommand) ); } } @@ -168,7 +163,7 @@ function testRegistry(registryType) { iotAgentLib.commandQueue('smartGondor', 'gardens', 'devId1', function(error, commandList) { commandList.count.should.equal(5); - for (var i = 0; i < 5; i++) { + for (let i = 0; i < 5; i++) { commandList.commands[i].deviceId.should.equal('devId1'); } @@ -180,7 +175,7 @@ function testRegistry(registryType) { iotAgentLib.commandQueue('smartGondor', 'gardens', 'devId1', function(error, commandList) { commandList.count.should.equal(5); - for (var i = 0; i < 5; i++) { + for (let i = 0; i < 5; i++) { commandList.commands[i].name.should.equal('commandName' + i); commandList.commands[i].type.should.equal('commandType' + i); commandList.commands[i].value.should.equal('commandValue' + i); @@ -197,24 +192,16 @@ function testRegistry(registryType) { describe('When a command is removed from the queue', function() { beforeEach(function(done) { - var commands = []; + const commands = []; - for (var j = 0; j < 5; j++) { - var newCommand = { + for (let j = 0; j < 5; j++) { + const newCommand = { name: commandTemplate.name + j, type: commandTemplate.type + j, value: commandTemplate.value + j }; - commands.push( - async.apply( - iotAgentLib.addCommand, - 'smartGondor', - 'gardens', - 'devId', - newCommand - ) - ); + commands.push(async.apply(iotAgentLib.addCommand, 'smartGondor', 'gardens', 'devId', newCommand)); } async.series(commands, function(error) { @@ -227,7 +214,7 @@ function testRegistry(registryType) { iotAgentLib.commandQueue('smartGondor', 'gardens', 'devId', function(error, commandList) { commandList.commands.length.should.equal(4); - for (var i = 0; i < commandList.commands.length; i++) { + for (let i = 0; i < commandList.commands.length; i++) { commandList.commands[i].name.should.not.equal('commandName2'); } diff --git a/test/unit/lazyAndCommands/lazy-devices-test.js b/test/unit/lazyAndCommands/lazy-devices-test.js index fc1af7e82..af267661b 100644 --- a/test/unit/lazyAndCommands/lazy-devices-test.js +++ b/test/unit/lazyAndCommands/lazy-devices-test.js @@ -20,123 +20,123 @@ * For those usages not covered by the GNU Affero General Public License * please contact with::[contacto@tid.es] */ -'use strict'; - -var iotAgentLib = require('../../../lib/fiware-iotagent-lib'), - utils = require('../../tools/utils'), - async = require('async'), - apply = async.apply, - should = require('should'), - logger = require('logops'), - nock = require('nock'), - mongoUtils = require('../mongodb/mongoDBUtils'), - request = require('request'), - contextBrokerMock, - iotAgentConfig = { - contextBroker: { - host: '192.168.1.1', - port: '1026' + +/* eslint-disable no-unused-vars */ + +const iotAgentLib = require('../../../lib/fiware-iotagent-lib'); +const utils = require('../../tools/utils'); +const async = require('async'); +const apply = async.apply; +const should = require('should'); +const logger = require('logops'); +const nock = require('nock'); +const mongoUtils = require('../mongodb/mongoDBUtils'); +const request = require('request'); +let contextBrokerMock; +const iotAgentConfig = { + contextBroker: { + host: '192.168.1.1', + port: '1026' + }, + server: { + port: 4041 + }, + types: { + Light: { + commands: [], + lazy: [ + { + name: 'temperature', + type: 'centigrades' + } + ], + active: [ + { + name: 'pressure', + type: 'Hgmm' + } + ] }, - server: { - port: 4041 + Termometer: { + commands: [], + lazy: [ + { + name: 'temp', + type: 'kelvin' + } + ], + active: [] }, - types: { - 'Light': { - commands: [], - lazy: [ - { - name: 'temperature', - type: 'centigrades' - } - ], - active: [ - { - name: 'pressure', - type: 'Hgmm' - } - ] - }, - 'Termometer': { - commands: [], - lazy: [ - { - name: 'temp', - type: 'kelvin' - } - ], - active: [ - ] - }, - 'Motion': { - commands: [], - lazy: [ - { - name: 'moving', - type: 'Boolean' - } - ], - staticAttributes: [ - { - 'name': 'location', - 'type': 'Vector', - 'value': '(123,523)' - } - ], - active: [] - }, - 'RobotPre': { - commands: [], - lazy: [ - { - name: 'moving', - type: 'Boolean' - } - ], - staticAttributes: [], - attributes: [], - internalAttributes: { - lwm2mResourceMapping: { - position: { - objectType: 9090, - objectInstance: 0, - objectResource: 0 - } + Motion: { + commands: [], + lazy: [ + { + name: 'moving', + type: 'Boolean' + } + ], + staticAttributes: [ + { + name: 'location', + type: 'Vector', + value: '(123,523)' + } + ], + active: [] + }, + RobotPre: { + commands: [], + lazy: [ + { + name: 'moving', + type: 'Boolean' + } + ], + staticAttributes: [], + attributes: [], + internalAttributes: { + lwm2mResourceMapping: { + position: { + objectType: 9090, + objectInstance: 0, + objectResource: 0 } } } - }, - service: 'smartGondor', - subservice: 'gardens', - providerUrl: 'http://smartGondor.com', - deviceRegistrationDuration: 'P1M' - }, - device1 = { - id: 'light1', - type: 'Light', - service: 'smartGondor', - subservice: 'gardens' - }, - device2 = { - id: 'motion1', - type: 'Motion', - service: 'smartGondor', - subservice: 'gardens' + } }, - device3 = { - id: 'TestRobotPre', - type: 'RobotPre', - service: 'smartGondor', - subservice: 'gardens', - internalAttributes: { - lwm2mResourceMapping: { - position: { - objectType: 6789, - objectInstance: 0, - objectResource: 17 - } + service: 'smartGondor', + subservice: 'gardens', + providerUrl: 'http://smartGondor.com', + deviceRegistrationDuration: 'P1M' +}; +const device1 = { + id: 'light1', + type: 'Light', + service: 'smartGondor', + subservice: 'gardens' +}; +const device2 = { + id: 'motion1', + type: 'Motion', + service: 'smartGondor', + subservice: 'gardens' +}; +const device3 = { + id: 'TestRobotPre', + type: 'RobotPre', + service: 'smartGondor', + subservice: 'gardens', + internalAttributes: { + lwm2mResourceMapping: { + position: { + objectType: 6789, + objectInstance: 0, + objectResource: 17 } } - }; + } +}; describe('IoT Agent Lazy Devices', function() { beforeEach(function(done) { @@ -147,7 +147,7 @@ describe('IoT Agent Lazy Devices', function() { }); afterEach(function(done) { - delete(device1.registrationId); + delete device1.registrationId; iotAgentLib.clearAll(function() { iotAgentLib.deactivate(function() { mongoUtils.cleanDbs(done); @@ -156,7 +156,7 @@ describe('IoT Agent Lazy Devices', function() { }); describe('When the IoT Agent receives an update on the device data in JSON format', function() { - var options = { + const options = { url: 'http://localhost:' + iotAgentConfig.server.port + '/v1/updateContext', method: 'POST', json: { @@ -188,28 +188,33 @@ describe('IoT Agent Lazy Devices', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/NGSI9/registerContext', - utils.readExampleFile('./test/unit/examples/contextAvailabilityRequests/registerIoTAgent1.json')) - .reply(200, utils.readExampleFile( - './test/unit/examples/contextAvailabilityResponses/registerIoTAgent1Success.json')); + .post( + '/NGSI9/registerContext', + utils.readExampleFile('./test/unit/examples/contextAvailabilityRequests/registerIoTAgent1.json') + ) + .reply( + 200, + utils.readExampleFile( + './test/unit/examples/contextAvailabilityResponses/registerIoTAgent1Success.json' + ) + ); contextBrokerMock .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') .post('/v1/updateContext') - .reply(200, - utils.readExampleFile( - './test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json')); - - async.series([ - apply(iotAgentLib.activate, iotAgentConfig), - apply(iotAgentLib.register, device1) - ], done); + .reply( + 200, + utils.readExampleFile('./test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json') + ); + + async.series([apply(iotAgentLib.activate, iotAgentConfig), apply(iotAgentLib.register, device1)], done); }); it('should call the device handler with the received data', function(done) { - var expectedResponse = utils - .readExampleFile('./test/unit/examples/contextProviderResponses/updateInformationResponse.json'); + const expectedResponse = utils.readExampleFile( + './test/unit/examples/contextProviderResponses/updateInformationResponse.json' + ); iotAgentLib.setDataUpdateHandler(function(id, type, service, subservice, attributes, callback) { id.should.equal(device1.type + ':' + device1.id); @@ -231,40 +236,38 @@ describe('IoT Agent Lazy Devices', function() { }); describe('When a context query arrives to the IoT Agent', function() { - var options = { - url: 'http://localhost:' + iotAgentConfig.server.port + '/v1/queryContext', - method: 'POST', - json: { - entities: [ - { - type: 'Light', - isPattern: 'false', - id: 'Light:light1' - } - ], - attributes: [ - 'dimming' - ] - }, - headers: { - 'fiware-service': 'smartGondor', - 'fiware-servicepath': 'gardens' - } + const options = { + url: 'http://localhost:' + iotAgentConfig.server.port + '/v1/queryContext', + method: 'POST', + json: { + entities: [ + { + type: 'Light', + isPattern: 'false', + id: 'Light:light1' + } + ], + attributes: ['dimming'] }, - sensorData = [ - { - id: 'Light:light1', - isPattern: false, - type: 'Light', - attributes: [ - { - name: 'dimming', - type: 'Percentage', - value: '19' - } - ] - } - ]; + headers: { + 'fiware-service': 'smartGondor', + 'fiware-servicepath': 'gardens' + } + }; + const sensorData = [ + { + id: 'Light:light1', + isPattern: false, + type: 'Light', + attributes: [ + { + name: 'dimming', + type: 'Percentage', + value: '19' + } + ] + } + ]; beforeEach(function(done) { nock.cleanAll(); @@ -272,27 +275,33 @@ describe('IoT Agent Lazy Devices', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/NGSI9/registerContext', utils.readExampleFile( - './test/unit/examples/contextAvailabilityRequests/registerIoTAgent1.json')) - .reply(200, utils.readExampleFile( - './test/unit/examples/contextAvailabilityResponses/registerIoTAgent1Success.json')); + .post( + '/NGSI9/registerContext', + utils.readExampleFile('./test/unit/examples/contextAvailabilityRequests/registerIoTAgent1.json') + ) + .reply( + 200, + utils.readExampleFile( + './test/unit/examples/contextAvailabilityResponses/registerIoTAgent1Success.json' + ) + ); contextBrokerMock .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') .post('/v1/updateContext') - .reply(200, utils.readExampleFile( - './test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json')); + .reply( + 200, + utils.readExampleFile('./test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json') + ); - async.series([ - apply(iotAgentLib.activate, iotAgentConfig), - apply(iotAgentLib.register, device1) - ], done); + async.series([apply(iotAgentLib.activate, iotAgentConfig), apply(iotAgentLib.register, device1)], done); }); it('should return the information querying the underlying devices', function(done) { - var expectedResponse = utils - .readExampleFile('./test/unit/examples/contextProviderResponses/queryInformationResponse.json'); + const expectedResponse = utils.readExampleFile( + './test/unit/examples/contextProviderResponses/queryInformationResponse.json' + ); iotAgentLib.setDataQueryHandler(function(id, type, service, subservice, attributes, callback) { id.should.equal(device1.type + ':' + device1.id); @@ -310,26 +319,24 @@ describe('IoT Agent Lazy Devices', function() { }); describe('When a context query arrives to the IoT Agent and no handler is set', function() { - var options = { - url: 'http://localhost:' + iotAgentConfig.server.port + '/v1/queryContext', - method: 'POST', - json: { - entities: [ - { - type: 'Light', - isPattern: 'false', - id: 'Light:light1' - } - ], - attributes: [ - 'dimming' - ] - }, - headers: { - 'fiware-service': 'smartGondor', - 'fiware-servicepath': 'gardens' - } - }; + const options = { + url: 'http://localhost:' + iotAgentConfig.server.port + '/v1/queryContext', + method: 'POST', + json: { + entities: [ + { + type: 'Light', + isPattern: 'false', + id: 'Light:light1' + } + ], + attributes: ['dimming'] + }, + headers: { + 'fiware-service': 'smartGondor', + 'fiware-servicepath': 'gardens' + } + }; beforeEach(function(done) { nock.cleanAll(); @@ -337,23 +344,29 @@ describe('IoT Agent Lazy Devices', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/NGSI9/registerContext', utils.readExampleFile( - './test/unit/examples/contextAvailabilityRequests/registerIoTAgent1.json')) - .reply(200, utils.readExampleFile( - './test/unit/examples/contextAvailabilityResponses/registerIoTAgent1Success.json')); + .post( + '/NGSI9/registerContext', + utils.readExampleFile('./test/unit/examples/contextAvailabilityRequests/registerIoTAgent1.json') + ) + .reply( + 200, + utils.readExampleFile( + './test/unit/examples/contextAvailabilityResponses/registerIoTAgent1Success.json' + ) + ); contextBrokerMock .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') .post('/v1/updateContext') - .reply(200, - utils.readExampleFile( - './test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json')); - - async.series([ - apply(iotAgentLib.activate, iotAgentConfig), - apply(iotAgentLib.register, device1) - ], function(error) { + .reply( + 200, + utils.readExampleFile('./test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json') + ); + + async.series([apply(iotAgentLib.activate, iotAgentConfig), apply(iotAgentLib.register, device1)], function( + error + ) { done(); }); }); @@ -376,37 +389,37 @@ describe('IoT Agent Lazy Devices', function() { }); describe('When a query arrives to the IoT Agent without any attributes', function() { - var options = { - url: 'http://localhost:' + iotAgentConfig.server.port + '/v1/queryContext', - method: 'POST', - json: { - entities: [ - { - type: 'Light', - isPattern: 'false', - id: 'Light:light1' - } - ] - }, - headers: { - 'fiware-service': 'smartGondor', - 'fiware-servicepath': 'gardens' - } + const options = { + url: 'http://localhost:' + iotAgentConfig.server.port + '/v1/queryContext', + method: 'POST', + json: { + entities: [ + { + type: 'Light', + isPattern: 'false', + id: 'Light:light1' + } + ] }, - sensorData = [ - { - id: 'Light:light1', - isPattern: false, - type: 'Light', - attributes: [ - { - name: 'temperature', - type: 'centigrades', - value: '19' - } - ] - } - ]; + headers: { + 'fiware-service': 'smartGondor', + 'fiware-servicepath': 'gardens' + } + }; + const sensorData = [ + { + id: 'Light:light1', + isPattern: false, + type: 'Light', + attributes: [ + { + name: 'temperature', + type: 'centigrades', + value: '19' + } + ] + } + ]; beforeEach(function(done) { nock.cleanAll(); @@ -414,27 +427,33 @@ describe('IoT Agent Lazy Devices', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/NGSI9/registerContext', utils.readExampleFile( - './test/unit/examples/contextAvailabilityRequests/registerIoTAgent1.json')) - .reply(200, utils.readExampleFile( - './test/unit/examples/contextAvailabilityResponses/registerIoTAgent1Success.json')); + .post( + '/NGSI9/registerContext', + utils.readExampleFile('./test/unit/examples/contextAvailabilityRequests/registerIoTAgent1.json') + ) + .reply( + 200, + utils.readExampleFile( + './test/unit/examples/contextAvailabilityResponses/registerIoTAgent1Success.json' + ) + ); contextBrokerMock .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') .post('/v1/updateContext') - .reply(200, utils.readExampleFile( - './test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json')); + .reply( + 200, + utils.readExampleFile('./test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json') + ); - async.series([ - apply(iotAgentLib.activate, iotAgentConfig), - apply(iotAgentLib.register, device1) - ], done); + async.series([apply(iotAgentLib.activate, iotAgentConfig), apply(iotAgentLib.register, device1)], done); }); it('should return the information of all the attributes', function(done) { - var expectedResponse = utils.readExampleFile( - './test/unit/examples/contextProviderResponses/queryInformationResponseEmptyAttributes.json'); + const expectedResponse = utils.readExampleFile( + './test/unit/examples/contextProviderResponses/queryInformationResponseEmptyAttributes.json' + ); iotAgentLib.setDataQueryHandler(function(id, type, service, subservice, attributes, callback) { should.exist(attributes); @@ -452,38 +471,38 @@ describe('IoT Agent Lazy Devices', function() { }); describe('When a query arrives to the IoT Agent with an empty attributes array', function() { - var options = { - url: 'http://localhost:' + iotAgentConfig.server.port + '/v1/queryContext', - method: 'POST', - json: { - entities: [ - { - type: 'Light', - isPattern: 'false', - id: 'Light:light1' - } - ], - attributes: [] - }, - headers: { - 'fiware-service': 'smartGondor', - 'fiware-servicepath': 'gardens' - } + const options = { + url: 'http://localhost:' + iotAgentConfig.server.port + '/v1/queryContext', + method: 'POST', + json: { + entities: [ + { + type: 'Light', + isPattern: 'false', + id: 'Light:light1' + } + ], + attributes: [] }, - sensorData = [ - { - id: 'Light:light1', - isPattern: false, - type: 'Light', - attributes: [ - { - name: 'temperature', - type: 'centigrades', - value: '19' - } - ] - } - ]; + headers: { + 'fiware-service': 'smartGondor', + 'fiware-servicepath': 'gardens' + } + }; + const sensorData = [ + { + id: 'Light:light1', + isPattern: false, + type: 'Light', + attributes: [ + { + name: 'temperature', + type: 'centigrades', + value: '19' + } + ] + } + ]; beforeEach(function(done) { nock.cleanAll(); @@ -491,27 +510,33 @@ describe('IoT Agent Lazy Devices', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/NGSI9/registerContext', utils.readExampleFile( - './test/unit/examples/contextAvailabilityRequests/registerIoTAgent1.json')) - .reply(200, utils.readExampleFile( - './test/unit/examples/contextAvailabilityResponses/registerIoTAgent1Success.json')); + .post( + '/NGSI9/registerContext', + utils.readExampleFile('./test/unit/examples/contextAvailabilityRequests/registerIoTAgent1.json') + ) + .reply( + 200, + utils.readExampleFile( + './test/unit/examples/contextAvailabilityResponses/registerIoTAgent1Success.json' + ) + ); contextBrokerMock .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') .post('/v1/updateContext') - .reply(200, utils.readExampleFile( - './test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json')); + .reply( + 200, + utils.readExampleFile('./test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json') + ); - async.series([ - apply(iotAgentLib.activate, iotAgentConfig), - apply(iotAgentLib.register, device1) - ], done); + async.series([apply(iotAgentLib.activate, iotAgentConfig), apply(iotAgentLib.register, device1)], done); }); it('should return the information of all the attributes', function(done) { - var expectedResponse = utils.readExampleFile( - './test/unit/examples/contextProviderResponses/queryInformationResponseEmptyAttributes.json'); + const expectedResponse = utils.readExampleFile( + './test/unit/examples/contextProviderResponses/queryInformationResponseEmptyAttributes.json' + ); iotAgentLib.setDataQueryHandler(function(id, type, service, subservice, attributes, callback) { should.exist(attributes); @@ -529,40 +554,37 @@ describe('IoT Agent Lazy Devices', function() { }); describe('When a context query arrives to the IoT Agent for a type with static attributes', function() { - var options = { - url: 'http://localhost:' + iotAgentConfig.server.port + '/v1/queryContext', - method: 'POST', - json: { - entities: [ - { - type: 'Motion', - isPattern: 'false', - id: 'Motion:motion1' - } - ], - attributes: [ - 'moving', - 'location' - ] - }, - headers: { - 'fiware-service': 'smartGondor', - 'fiware-servicepath': 'gardens' - } + const options = { + url: 'http://localhost:' + iotAgentConfig.server.port + '/v1/queryContext', + method: 'POST', + json: { + entities: [ + { + type: 'Motion', + isPattern: 'false', + id: 'Motion:motion1' + } + ], + attributes: ['moving', 'location'] }, - sensorData = [ - { - id: 'Motion:motion1', - type: 'Motion', - attributes: [ - { - name: 'moving', - type: 'Boolean', - value: 'true' - } - ] - } - ]; + headers: { + 'fiware-service': 'smartGondor', + 'fiware-servicepath': 'gardens' + } + }; + const sensorData = [ + { + id: 'Motion:motion1', + type: 'Motion', + attributes: [ + { + name: 'moving', + type: 'Boolean', + value: 'true' + } + ] + } + ]; beforeEach(function(done) { nock.cleanAll(); @@ -570,27 +592,33 @@ describe('IoT Agent Lazy Devices', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/NGSI9/registerContext', utils.readExampleFile( - './test/unit/examples/contextAvailabilityRequests/registerIoTAgent2.json')) - .reply(200, utils.readExampleFile( - './test/unit/examples/contextAvailabilityResponses/registerIoTAgent1Success.json')); + .post( + '/NGSI9/registerContext', + utils.readExampleFile('./test/unit/examples/contextAvailabilityRequests/registerIoTAgent2.json') + ) + .reply( + 200, + utils.readExampleFile( + './test/unit/examples/contextAvailabilityResponses/registerIoTAgent1Success.json' + ) + ); contextBrokerMock .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') .post('/v1/updateContext') - .reply(200, utils.readExampleFile( - './test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json')); + .reply( + 200, + utils.readExampleFile('./test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json') + ); - async.series([ - apply(iotAgentLib.activate, iotAgentConfig), - apply(iotAgentLib.register, device2) - ], done); + async.series([apply(iotAgentLib.activate, iotAgentConfig), apply(iotAgentLib.register, device2)], done); }); it('should return the information adding the static attributes', function(done) { - var expectedResponse = utils.readExampleFile( - './test/unit/examples/contextProviderResponses/queryInformationStaticAttributesResponse.json'); + const expectedResponse = utils.readExampleFile( + './test/unit/examples/contextProviderResponses/queryInformationStaticAttributesResponse.json' + ); iotAgentLib.setDataQueryHandler(function(id, type, service, subservice, attributes, callback) { id.should.equal('Motion:motion1'); @@ -609,29 +637,29 @@ describe('IoT Agent Lazy Devices', function() { }); describe('When a context query arrives to the IoT Agent with a payload that is not JSON', function() { - var options = { - url: 'http://localhost:' + iotAgentConfig.server.port + '/v1/queryContext', - method: 'POST', - body: 'This is a body in text format', - headers: { - 'Content-Type': 'text/plain', - 'fiware-service': 'smartGondor', - 'fiware-servicepath': 'gardens' - } - }, - sensorData = [ - { - id: 'Light:light1', - type: 'Light', - attributes: [ - { - name: 'dimming', - type: 'Percentage', - value: '19' - } - ] - } - ]; + const options = { + url: 'http://localhost:' + iotAgentConfig.server.port + '/v1/queryContext', + method: 'POST', + body: 'This is a body in text format', + headers: { + 'Content-Type': 'text/plain', + 'fiware-service': 'smartGondor', + 'fiware-servicepath': 'gardens' + } + }; + const sensorData = [ + { + id: 'Light:light1', + type: 'Light', + attributes: [ + { + name: 'dimming', + type: 'Percentage', + value: '19' + } + ] + } + ]; beforeEach(function(done) { nock.cleanAll(); @@ -639,23 +667,31 @@ describe('IoT Agent Lazy Devices', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/NGSI9/registerContext', utils.readExampleFile( - './test/unit/examples/contextAvailabilityRequests/registerIoTAgent1.json')) - .reply(200, utils.readExampleFile( - './test/unit/examples/contextAvailabilityResponses/registerIoTAgent1Success.json')); + .post( + '/NGSI9/registerContext', + utils.readExampleFile('./test/unit/examples/contextAvailabilityRequests/registerIoTAgent1.json') + ) + .reply( + 200, + utils.readExampleFile( + './test/unit/examples/contextAvailabilityResponses/registerIoTAgent1Success.json' + ) + ); contextBrokerMock .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') .post('/v1/updateContext') - .reply(200, utils.readExampleFile( - './test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json')); + .reply( + 200, + utils.readExampleFile('./test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json') + ); iotAgentLib.activate(iotAgentConfig, done); }); it('should fail with a 400 error', function(done) { - var handlerCalled = false; + let handlerCalled = false; iotAgentLib.setDataQueryHandler(function(id, type, service, subservice, attributes, callback) { handlerCalled = true; @@ -671,7 +707,7 @@ describe('IoT Agent Lazy Devices', function() { }); it('should return an NGSI compliant payload', function(done) { - var handlerCalled = false; + let handlerCalled = false; iotAgentLib.setDataQueryHandler(function(id, type, service, subservice, attributes, callback) { handlerCalled = true; @@ -679,7 +715,7 @@ describe('IoT Agent Lazy Devices', function() { }); request(options, function(error, response, body) { - var parsedBody = JSON.parse(body); + const parsedBody = JSON.parse(body); should.exist(parsedBody.errorCode); parsedBody.errorCode.code.should.equal(400); parsedBody.errorCode.details.should.equal('Unsuported content type in the context request: text/plain'); @@ -691,24 +727,24 @@ describe('IoT Agent Lazy Devices', function() { }); describe('When a context query arrives to the IoT Agent with an invalid body', function() { - var options = { - url: 'http://localhost:' + iotAgentConfig.server.port + '/v1/queryContext', - method: 'POST', - json: {} - }, - sensorData = [ - { - id: 'Light:light1', - type: 'Light', - attributes: [ - { - name: 'dimming', - type: 'Percentage', - value: '19' - } - ] - } - ]; + const options = { + url: 'http://localhost:' + iotAgentConfig.server.port + '/v1/queryContext', + method: 'POST', + json: {} + }; + const sensorData = [ + { + id: 'Light:light1', + type: 'Light', + attributes: [ + { + name: 'dimming', + type: 'Percentage', + value: '19' + } + ] + } + ]; beforeEach(function(done) { nock.cleanAll(); @@ -716,23 +752,31 @@ describe('IoT Agent Lazy Devices', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/NGSI9/registerContext', utils.readExampleFile( - './test/unit/examples/contextAvailabilityRequests/registerIoTAgent1.json')) - .reply(200, utils.readExampleFile( - './test/unit/examples/contextAvailabilityResponses/registerIoTAgent1Success.json')); + .post( + '/NGSI9/registerContext', + utils.readExampleFile('./test/unit/examples/contextAvailabilityRequests/registerIoTAgent1.json') + ) + .reply( + 200, + utils.readExampleFile( + './test/unit/examples/contextAvailabilityResponses/registerIoTAgent1Success.json' + ) + ); contextBrokerMock .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', '/gardens') .post('/v1/updateContext') - .reply(200, utils.readExampleFile( - './test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json')); + .reply( + 200, + utils.readExampleFile('./test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json') + ); iotAgentLib.activate(iotAgentConfig, done); }); it('should fail with a 400 error', function(done) { - var handlerCalled = false; + let handlerCalled = false; iotAgentLib.setDataQueryHandler(function(id, type, service, subservice, attributes, callback) { handlerCalled = true; @@ -748,76 +792,85 @@ describe('IoT Agent Lazy Devices', function() { }); }); - describe('When the IoT Agent receives an update on the device data in JSON format for a type with' + - 'internalAttributes', function() { - var options = { - url: 'http://localhost:' + iotAgentConfig.server.port + '/v1/updateContext', - method: 'POST', - json: { - contextElements: [ - { - type: 'RobotPre', - isPattern: 'false', - id: 'RobotPre:TestRobotPre', - attributes: [ - { - name: 'moving', - type: 'Boolean', - value: 'True' - } - ] - } - ], - updateAction: 'APPEND' - }, - headers: { - 'fiware-service': 'smartGondor', - 'fiware-servicepath': 'gardens' - } - }; - - beforeEach(function(done) { - nock.cleanAll(); - - contextBrokerMock = nock('http://192.168.1.1:1026') - .matchHeader('fiware-service', 'smartGondor') - .matchHeader('fiware-servicepath', 'gardens') - .post('/NGSI9/registerContext', - utils.readExampleFile('./test/unit/examples/contextAvailabilityRequests/registerIoTAgent4.json')) - .reply(200, utils.readExampleFile( - './test/unit/examples/contextAvailabilityResponses/registerIoTAgent1Success.json')); - - contextBrokerMock - .matchHeader('fiware-service', 'smartGondor') - .matchHeader('fiware-servicepath', 'gardens') - .post('/v1/updateContext') - .reply(200, - utils.readExampleFile( - './test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json')); - - async.series([ - apply(iotAgentLib.activate, iotAgentConfig), - apply(iotAgentLib.register, device3) - ], done); - }); - - it('should call the device handler with the received data', function(done) { - var expectedResponse = utils - .readExampleFile('./test/unit/examples/contextProviderResponses/updateInformationResponse2.json'); + describe( + 'When the IoT Agent receives an update on the device data in JSON format for a type with' + + 'internalAttributes', + function() { + const options = { + url: 'http://localhost:' + iotAgentConfig.server.port + '/v1/updateContext', + method: 'POST', + json: { + contextElements: [ + { + type: 'RobotPre', + isPattern: 'false', + id: 'RobotPre:TestRobotPre', + attributes: [ + { + name: 'moving', + type: 'Boolean', + value: 'True' + } + ] + } + ], + updateAction: 'APPEND' + }, + headers: { + 'fiware-service': 'smartGondor', + 'fiware-servicepath': 'gardens' + } + }; - iotAgentLib.setDataUpdateHandler(function(id, type, service, subservice, attributes, callback) { - id.should.equal(device3.type + ':' + device3.id); - type.should.equal(device3.type); - attributes[0].value.should.equal('True'); - callback(null); + beforeEach(function(done) { + nock.cleanAll(); + + contextBrokerMock = nock('http://192.168.1.1:1026') + .matchHeader('fiware-service', 'smartGondor') + .matchHeader('fiware-servicepath', 'gardens') + .post( + '/NGSI9/registerContext', + utils.readExampleFile('./test/unit/examples/contextAvailabilityRequests/registerIoTAgent4.json') + ) + .reply( + 200, + utils.readExampleFile( + './test/unit/examples/contextAvailabilityResponses/registerIoTAgent1Success.json' + ) + ); + + contextBrokerMock + .matchHeader('fiware-service', 'smartGondor') + .matchHeader('fiware-servicepath', 'gardens') + .post('/v1/updateContext') + .reply( + 200, + utils.readExampleFile( + './test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json' + ) + ); + + async.series([apply(iotAgentLib.activate, iotAgentConfig), apply(iotAgentLib.register, device3)], done); }); - request(options, function(error, response, body) { - should.not.exist(error); - body.should.eql(expectedResponse); - done(); + it('should call the device handler with the received data', function(done) { + const expectedResponse = utils.readExampleFile( + './test/unit/examples/contextProviderResponses/updateInformationResponse2.json' + ); + + iotAgentLib.setDataUpdateHandler(function(id, type, service, subservice, attributes, callback) { + id.should.equal(device3.type + ':' + device3.id); + type.should.equal(device3.type); + attributes[0].value.should.equal('True'); + callback(null); + }); + + request(options, function(error, response, body) { + should.not.exist(error); + body.should.eql(expectedResponse); + done(); + }); }); - }); - }); - + } + ); }); diff --git a/test/unit/lazyAndCommands/polling-commands-test.js b/test/unit/lazyAndCommands/polling-commands-test.js index 16ccc32bc..4a2fa13fe 100644 --- a/test/unit/lazyAndCommands/polling-commands-test.js +++ b/test/unit/lazyAndCommands/polling-commands-test.js @@ -20,104 +20,104 @@ * For those usages not covered by the GNU Affero General Public License * please contact with::[contacto@tid.es] */ -'use strict'; - -var iotAgentLib = require('../../../lib/fiware-iotagent-lib'), - utils = require('../../tools/utils'), - should = require('should'), - logger = require('logops'), - nock = require('nock'), - mongoUtils = require('../mongodb/mongoDBUtils'), - request = require('request'), - contextBrokerMock, - statusAttributeMock, - iotAgentConfig = { - contextBroker: { - host: '192.168.1.1', - port: '1026' + +/* eslint-disable no-unused-vars */ + +const iotAgentLib = require('../../../lib/fiware-iotagent-lib'); +const utils = require('../../tools/utils'); +const should = require('should'); +const logger = require('logops'); +const nock = require('nock'); +const mongoUtils = require('../mongodb/mongoDBUtils'); +const request = require('request'); +let contextBrokerMock; +let statusAttributeMock; +const iotAgentConfig = { + contextBroker: { + host: '192.168.1.1', + port: '1026' + }, + server: { + port: 4041 + }, + types: { + Light: { + commands: [], + lazy: [ + { + name: 'temperature', + type: 'centigrades' + } + ], + active: [ + { + name: 'pressure', + type: 'Hgmm' + } + ] }, - server: { - port: 4041 + Termometer: { + commands: [], + lazy: [ + { + name: 'temp', + type: 'kelvin' + } + ], + active: [] }, - types: { - 'Light': { - commands: [], - lazy: [ - { - name: 'temperature', - type: 'centigrades' - } - ], - active: [ - { - name: 'pressure', - type: 'Hgmm' - } - ] - }, - 'Termometer': { - commands: [], - lazy: [ - { - name: 'temp', - type: 'kelvin' - } - ], - active: [ - ] - }, - 'Motion': { - commands: [], - lazy: [ - { - name: 'moving', - type: 'Boolean' - } - ], - staticAttributes: [ - { - 'name': 'location', - 'type': 'Vector', - 'value': '(123,523)' - } - ], - active: [] - }, - 'Robot': { - commands: [ - { - name: 'position', - type: 'Array' - } - ], - lazy: [], - staticAttributes: [], - active: [] - } - }, - deviceRegistry: { - type: 'mongodb' + Motion: { + commands: [], + lazy: [ + { + name: 'moving', + type: 'Boolean' + } + ], + staticAttributes: [ + { + name: 'location', + type: 'Vector', + value: '(123,523)' + } + ], + active: [] }, + Robot: { + commands: [ + { + name: 'position', + type: 'Array' + } + ], + lazy: [], + staticAttributes: [], + active: [] + } + }, + deviceRegistry: { + type: 'mongodb' + }, - mongodb: { - host: 'localhost', - port: '27017', - db: 'iotagent' - }, - service: 'smartGondor', - subservice: 'gardens', - providerUrl: 'http://smartGondor.com', - deviceRegistrationDuration: 'P1M', - pollingExpiration: 200, - pollingDaemonFrequency: 20 + mongodb: { + host: 'localhost', + port: '27017', + db: 'iotagent' }, - device3 = { - id: 'r2d2', - type: 'Robot', - service: 'smartGondor', - subservice: 'gardens', - polling: true - }; + service: 'smartGondor', + subservice: 'gardens', + providerUrl: 'http://smartGondor.com', + deviceRegistrationDuration: 'P1M', + pollingExpiration: 200, + pollingDaemonFrequency: 20 +}; +const device3 = { + id: 'r2d2', + type: 'Robot', + service: 'smartGondor', + subservice: 'gardens', + polling: true +}; describe('Polling commands', function() { beforeEach(function(done) { @@ -128,27 +128,29 @@ describe('Polling commands', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/NGSI9/registerContext', - utils.readExampleFile( - './test/unit/examples/contextAvailabilityRequests/registerIoTAgentCommands.json')) - .reply(200, - utils.readExampleFile( - './test/unit/examples/contextAvailabilityResponses/registerIoTAgent1Success.json')); + .post( + '/NGSI9/registerContext', + utils.readExampleFile('./test/unit/examples/contextAvailabilityRequests/registerIoTAgentCommands.json') + ) + .reply( + 200, + utils.readExampleFile('./test/unit/examples/contextAvailabilityResponses/registerIoTAgent1Success.json') + ); contextBrokerMock .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') .post('/v1/updateContext') - .reply(200, - utils.readExampleFile( - './test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json')); - + .reply( + 200, + utils.readExampleFile('./test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json') + ); iotAgentLib.activate(iotAgentConfig, done); }); afterEach(function(done) { - delete(device3.registrationId); + delete device3.registrationId; iotAgentLib.clearAll(function() { iotAgentLib.deactivate(function() { mongoUtils.cleanDbs(function() { @@ -162,7 +164,7 @@ describe('Polling commands', function() { }); describe('When a command update arrives to the IoT Agent for a device with polling', function() { - var options = { + const options = { url: 'http://localhost:' + iotAgentConfig.server.port + '/v1/updateContext', method: 'POST', json: { @@ -192,11 +194,16 @@ describe('Polling commands', function() { statusAttributeMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v1/updateContext', - utils.readExampleFile('./test/unit/examples/contextRequests/updateContextCommandStatus.json')) - .reply(200, + .post( + '/v1/updateContext', + utils.readExampleFile('./test/unit/examples/contextRequests/updateContextCommandStatus.json') + ) + .reply( + 200, utils.readExampleFile( - './test/unit/examples/contextResponses/updateContextCommandStatusSuccess.json')); + './test/unit/examples/contextResponses/updateContextCommandStatusSuccess.json' + ) + ); iotAgentLib.register(device3, function(error) { done(); @@ -204,13 +211,13 @@ describe('Polling commands', function() { }); it('should not call the client handler', function(done) { - var handlerCalled = false; + let handlerCalled = false; iotAgentLib.setCommandHandler(function(id, type, service, subservice, attributes, callback) { handlerCalled = true; callback(null, { - id: id, - type: type, + id, + type, attributes: [ { name: 'position', @@ -257,7 +264,7 @@ describe('Polling commands', function() { }); describe('When a command arrives with multiple values in the value field', function() { - var options = { + const options = { url: 'http://localhost:' + iotAgentConfig.server.port + '/v1/updateContext', method: 'POST', json: { @@ -290,11 +297,16 @@ describe('Polling commands', function() { statusAttributeMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v1/updateContext', - utils.readExampleFile('./test/unit/examples/contextRequests/updateContextCommandStatus.json')) - .reply(200, + .post( + '/v1/updateContext', + utils.readExampleFile('./test/unit/examples/contextRequests/updateContextCommandStatus.json') + ) + .reply( + 200, utils.readExampleFile( - './test/unit/examples/contextResponses/updateContextCommandStatusSuccess.json')); + './test/unit/examples/contextResponses/updateContextCommandStatusSuccess.json' + ) + ); iotAgentLib.register(device3, function(error) { done(); @@ -317,7 +329,7 @@ describe('Polling commands', function() { }); describe('When a polling command expires', function() { - var options = { + const options = { url: 'http://localhost:' + iotAgentConfig.server.port + '/v1/updateContext', method: 'POST', json: { @@ -347,20 +359,30 @@ describe('Polling commands', function() { statusAttributeMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v1/updateContext', - utils.readExampleFile('./test/unit/examples/contextRequests/updateContextCommandStatus.json')) - .reply(200, + .post( + '/v1/updateContext', + utils.readExampleFile('./test/unit/examples/contextRequests/updateContextCommandStatus.json') + ) + .reply( + 200, utils.readExampleFile( - './test/unit/examples/contextResponses/updateContextCommandStatusSuccess.json')); + './test/unit/examples/contextResponses/updateContextCommandStatusSuccess.json' + ) + ); statusAttributeMock .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v1/updateContext', - utils.readExampleFile('./test/unit/examples/contextRequests/updateContextCommandExpired.json')) - .reply(200, + .post( + '/v1/updateContext', + utils.readExampleFile('./test/unit/examples/contextRequests/updateContextCommandExpired.json') + ) + .reply( + 200, utils.readExampleFile( - './test/unit/examples/contextResponses/updateContextCommandStatusSuccess.json')); + './test/unit/examples/contextResponses/updateContextCommandStatusSuccess.json' + ) + ); iotAgentLib.register(device3, function(error) { done(); diff --git a/test/unit/memoryRegistry/deviceRegistryMemory_test.js b/test/unit/memoryRegistry/deviceRegistryMemory_test.js index 6d0e1a322..1407036a2 100644 --- a/test/unit/memoryRegistry/deviceRegistryMemory_test.js +++ b/test/unit/memoryRegistry/deviceRegistryMemory_test.js @@ -20,34 +20,35 @@ * For those usages not covered by the GNU Affero General Public License * please contact with::daniel.moranjimenez@telefonica.com */ -'use strict'; - -var iotAgentLib = require('../../../lib/fiware-iotagent-lib'), - async = require('async'), - should = require('should'), - nock = require('nock'), - utils = require('../../tools/utils'), - iotAgentConfig = { - logLevel: 'FATAL', - contextBroker: { - host: '192.168.1.1', - port: '1026' - }, - server: { - name: 'testAgent', - port: 4041, - baseRoot: '/' - }, - types: {}, - deviceRegistry: { - type: 'memory' - }, - service: 'smartGondor', - subservice: 'gardens', - providerUrl: 'http://smartGondor.com', - deviceRegistrationDuration: 'P1M' + +/* eslint-disable no-unused-vars */ + +const iotAgentLib = require('../../../lib/fiware-iotagent-lib'); +const async = require('async'); +const should = require('should'); +const nock = require('nock'); +const utils = require('../../tools/utils'); +const iotAgentConfig = { + logLevel: 'FATAL', + contextBroker: { + host: '192.168.1.1', + port: '1026' + }, + server: { + name: 'testAgent', + port: 4041, + baseRoot: '/' + }, + types: {}, + deviceRegistry: { + type: 'memory' }, - contextBrokerMock; + service: 'smartGondor', + subservice: 'gardens', + providerUrl: 'http://smartGondor.com', + deviceRegistrationDuration: 'P1M' +}; +let contextBrokerMock; describe('In memory device registry', function() { beforeEach(function(done) { @@ -65,13 +66,14 @@ describe('In memory device registry', function() { .times(10) .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .reply(200, - utils.readExampleFile( - './test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json')); + .reply( + 200, + utils.readExampleFile('./test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json') + ); - var devices = []; + const devices = []; - for (var i = 0; i < 10; i++) { + for (let i = 0; i < 10; i++) { devices.push({ id: 'id' + i, type: 'Light' + i, @@ -96,14 +98,16 @@ describe('In memory device registry', function() { iotAgentLib.clearRegistry(done); }); it('should return the appropriate device', function(done) { - iotAgentLib.getDevicesByAttribute('internalId', 'internal3', 'smartGondor', 'gardens', - function(error, devices) { - should.not.exist(error); - should.exist(devices); - devices.length.should.equal(1); - devices[0].id.should.equal('id3'); - done(); - }); + iotAgentLib.getDevicesByAttribute('internalId', 'internal3', 'smartGondor', 'gardens', function( + error, + devices + ) { + should.not.exist(error); + should.exist(devices); + devices.length.should.equal(1); + devices[0].id.should.equal('id3'); + done(); + }); }); }); @@ -112,18 +116,19 @@ describe('In memory device registry', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .post('/v1/updateContext') .times(10) - .reply(200, - utils.readExampleFile( - './test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json')); + .reply( + 200, + utils.readExampleFile('./test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json') + ); - var devices = []; + const devices = []; - for (var i = 0; i < 10; i++) { + for (let i = 0; i < 10; i++) { devices.push({ id: 'id' + i, - type: 'Light' + i % 2, + type: 'Light' + (i % 2), internalId: 'internal' + i, - service: 'smartGondor' + i % 3, + service: 'smartGondor' + (i % 3), subservice: 'gardens', active: [ { @@ -143,13 +148,12 @@ describe('In memory device registry', function() { iotAgentLib.clearRegistry(done); }); it('should return all the matching devices', function(done) { - iotAgentLib.getDevicesByAttribute('type', 'Light0', undefined, 'gardens', - function(error, devices) { - should.not.exist(error); - should.exist(devices); - devices.length.should.equal(5); - done(); - }); + iotAgentLib.getDevicesByAttribute('type', 'Light0', undefined, 'gardens', function(error, devices) { + should.not.exist(error); + should.exist(devices); + devices.length.should.equal(5); + done(); + }); }); }); @@ -158,18 +162,19 @@ describe('In memory device registry', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .post('/v1/updateContext') .times(10) - .reply(200, - utils.readExampleFile( - './test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json')); + .reply( + 200, + utils.readExampleFile('./test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json') + ); - var devices = []; + const devices = []; - for (var i = 0; i < 10; i++) { + for (let i = 0; i < 10; i++) { devices.push({ id: 'id' + i, type: 'Light', internalId: 'internal' + i, - service: 'smartGondor' + i % 3, + service: 'smartGondor' + (i % 3), subservice: 'gardens', active: [ { @@ -189,13 +194,12 @@ describe('In memory device registry', function() { iotAgentLib.clearRegistry(done); }); it('should return all the matching devices in that service', function(done) { - iotAgentLib.getDevicesByAttribute('type', 'Light', 'smartGondor0', 'gardens', - function(error, devices) { - should.not.exist(error); - should.exist(devices); - devices.length.should.equal(4); - done(); - }); + iotAgentLib.getDevicesByAttribute('type', 'Light', 'smartGondor0', 'gardens', function(error, devices) { + should.not.exist(error); + should.exist(devices); + devices.length.should.equal(4); + done(); + }); }); }); }); diff --git a/test/unit/mongodb/mongoDBUtils.js b/test/unit/mongodb/mongoDBUtils.js index 66cd1fb6a..2fdf51719 100644 --- a/test/unit/mongodb/mongoDBUtils.js +++ b/test/unit/mongodb/mongoDBUtils.js @@ -20,44 +20,52 @@ * For those usages not covered by the GNU Affero General Public License * please contact with::[contacto@tid.es] */ -'use strict'; -var MongoClient = require('mongodb').MongoClient, - async = require('async'); +/* eslint-disable no-unused-vars */ + +const MongoClient = require('mongodb').MongoClient; +const async = require('async'); function cleanDb(host, name, callback) { - var url = 'mongodb://' + host + ':27017/' + name; + const url = 'mongodb://' + host + ':27017/' + name; - MongoClient.connect(url, { useNewUrlParser: true }, function(err, db) { - if (db && db.db()) { - db.db().dropDatabase( function (err, result) { - db.close(); - callback(); - }); - + MongoClient.connect( + url, + { useNewUrlParser: true }, + function(err, db) { + if (db && db.db()) { + db.db().dropDatabase(function(err, result) { + db.close(); + callback(); + }); + } } - }); + ); } function cleanDbs(callback) { - async.series([ - async.apply(cleanDb, 'localhost', 'iotagent') - ], callback); + async.series([async.apply(cleanDb, 'localhost', 'iotagent')], callback); } function populate(host, dbName, entityList, collectionName, callback) { - var url = 'mongodb://' + host + ':27017/' + dbName; + const url = 'mongodb://' + host + ':27017/' + dbName; - MongoClient.connect(url, { useNewUrlParser: true }, function(err, db) { - if (db) { - db.db().collection(collectionName).insertMany(entityList, function(err, r) { - db.close(); - callback(err); - }); - } else { - callback(); + MongoClient.connect( + url, + { useNewUrlParser: true }, + function(err, db) { + if (db) { + db.db() + .collection(collectionName) + .insertMany(entityList, function(err, r) { + db.close(); + callback(err); + }); + } else { + callback(); + } } - }); + ); } exports.cleanDb = cleanDb; diff --git a/test/unit/mongodb/mongodb-group-registry-test.js b/test/unit/mongodb/mongodb-group-registry-test.js index cf057ea3e..5925267b0 100644 --- a/test/unit/mongodb/mongodb-group-registry-test.js +++ b/test/unit/mongodb/mongodb-group-registry-test.js @@ -22,171 +22,172 @@ * * Modified by: Daniel Calvo - ATOS Research & Innovation */ -'use strict'; -/*jshint camelcase:false */ - -var iotAgentLib = require('../../../lib/fiware-iotagent-lib'), - _ = require('underscore'), - utils = require('../../tools/utils'), - async = require('async'), - request = require('request'), - should = require('should'), - iotAgentConfig = { - logLevel: 'FATAL', - contextBroker: { - host: '192.168.1.1', - port: '1026' - }, - server: { - name: 'testAgent', - port: 4041, - baseRoot: '/' - }, - types: {}, - deviceRegistry: { - type: 'mongodb' - }, - mongodb: { - host: 'localhost', - port: '27017', - db: 'iotagent' - }, - service: 'smartGondor', - subservice: 'gardens', - providerUrl: 'http://smartGondor.com', - deviceRegistrationDuration: 'P1M' +/* eslint-disable no-unused-vars */ + +const iotAgentLib = require('../../../lib/fiware-iotagent-lib'); +const _ = require('underscore'); +const utils = require('../../tools/utils'); +const async = require('async'); +const request = require('request'); +const should = require('should'); +const iotAgentConfig = { + logLevel: 'FATAL', + contextBroker: { + host: '192.168.1.1', + port: '1026' + }, + server: { + name: 'testAgent', + port: 4041, + baseRoot: '/' + }, + types: {}, + deviceRegistry: { + type: 'mongodb' }, - mongo = require('mongodb').MongoClient, - mongoUtils = require('./mongoDBUtils'), - optionsCreation = { - url: 'http://localhost:4041/iot/services', - method: 'POST', - json: { - services: [ - { - resource: '/deviceTest', - apikey: '801230BJKL23Y9090DSFL123HJK09H324HV8732', - entity_type: 'Light', - trust: '8970A9078A803H3BL98PINEQRW8342HBAMS', - cbHost: 'http://unexistentHost:1026', - commands: [ - { - name: 'wheel1', - type: 'Wheel' - } - ], - lazy: [ - { - name: 'luminescence', - type: 'Lumens' - } - ], - attributes: [ - { - name: 'status', - type: 'Boolean' - } - ], - internal_attributes: [ - { - customField: 'customValue' - } - ] - } - ] - }, - headers: { - 'fiware-service': 'TestService', - 'fiware-servicepath': '/testingPath' - } + mongodb: { + host: 'localhost', + port: '27017', + db: 'iotagent' }, - optionsDelete = { - url: 'http://localhost:4041/iot/services', - method: 'DELETE', - json: {}, - headers: { - 'fiware-service': 'TestService', - 'fiware-servicepath': '/testingPath' - }, - qs: { - resource: '/deviceTest', - apikey: '801230BJKL23Y9090DSFL123HJK09H324HV8732' - } + service: 'smartGondor', + subservice: 'gardens', + providerUrl: 'http://smartGondor.com', + deviceRegistrationDuration: 'P1M' +}; +const mongo = require('mongodb').MongoClient; +const mongoUtils = require('./mongoDBUtils'); +const optionsCreation = { + url: 'http://localhost:4041/iot/services', + method: 'POST', + json: { + services: [ + { + resource: '/deviceTest', + apikey: '801230BJKL23Y9090DSFL123HJK09H324HV8732', + entity_type: 'Light', + trust: '8970A9078A803H3BL98PINEQRW8342HBAMS', + cbHost: 'http://unexistentHost:1026', + commands: [ + { + name: 'wheel1', + type: 'Wheel' + } + ], + lazy: [ + { + name: 'luminescence', + type: 'Lumens' + } + ], + attributes: [ + { + name: 'status', + type: 'Boolean' + } + ], + internal_attributes: [ + { + customField: 'customValue' + } + ] + } + ] }, - optionsList = { - url: 'http://localhost:4041/iot/services', - method: 'GET', - json: {}, - headers: { - 'fiware-service': 'TestService', - 'fiware-servicepath': '/*' - } + headers: { + 'fiware-service': 'TestService', + 'fiware-servicepath': '/testingPath' + } +}; +const optionsDelete = { + url: 'http://localhost:4041/iot/services', + method: 'DELETE', + json: {}, + headers: { + 'fiware-service': 'TestService', + 'fiware-servicepath': '/testingPath' }, - optionsUpdate = { - url: 'http://localhost:4041/iot/services', - method: 'PUT', - json: { - apikey: '801230BJKL23Y9090DSFL123HJK09H324HV8732', - trust: '8970A9078A803H3BL98PINEQRW8342HBAMS', - cbHost: 'http://anotherUnexistentHost:1026', - commands: [ - { - name: 'wheel1', - type: 'Wheel' - } - ], - lazy: [ - { - name: 'luminescence', - type: 'Lumens' - } - ], - attributes: [ - { - name: 'status', - type: 'Boolean' - } - ], - static_attributes: [ - { - name: 'bootstrapServer', - type: 'Address', - value: '127.0.0.1' - } - ] - }, - headers: { - 'fiware-service': 'TestService', - 'fiware-servicepath': '/testingPath' - }, - qs: { - resource: '/deviceTest', - apikey: '801230BJKL23Y9090DSFL123HJK09H324HV8732' - } + qs: { + resource: '/deviceTest', + apikey: '801230BJKL23Y9090DSFL123HJK09H324HV8732' + } +}; +const optionsList = { + url: 'http://localhost:4041/iot/services', + method: 'GET', + json: {}, + headers: { + 'fiware-service': 'TestService', + 'fiware-servicepath': '/*' + } +}; +const optionsUpdate = { + url: 'http://localhost:4041/iot/services', + method: 'PUT', + json: { + apikey: '801230BJKL23Y9090DSFL123HJK09H324HV8732', + trust: '8970A9078A803H3BL98PINEQRW8342HBAMS', + cbHost: 'http://anotherUnexistentHost:1026', + commands: [ + { + name: 'wheel1', + type: 'Wheel' + } + ], + lazy: [ + { + name: 'luminescence', + type: 'Lumens' + } + ], + attributes: [ + { + name: 'status', + type: 'Boolean' + } + ], + static_attributes: [ + { + name: 'bootstrapServer', + type: 'Address', + value: '127.0.0.1' + } + ] }, - optionsGet = { - url: 'http://localhost:4041/iot/services', - method: 'GET', - json: {}, - headers: { - 'fiware-service': 'TestService', - 'fiware-servicepath': '/testingPath' - } + headers: { + 'fiware-service': 'TestService', + 'fiware-servicepath': '/testingPath' }, - iotAgentDb; + qs: { + resource: '/deviceTest', + apikey: '801230BJKL23Y9090DSFL123HJK09H324HV8732' + } +}; +const optionsGet = { + url: 'http://localhost:4041/iot/services', + method: 'GET', + json: {}, + headers: { + 'fiware-service': 'TestService', + 'fiware-servicepath': '/testingPath' + } +}; +let iotAgentDb; describe('MongoDB Group Registry test', function() { - beforeEach(function(done) { mongoUtils.cleanDbs(function() { iotAgentLib.activate(iotAgentConfig, function() { - mongo.connect('mongodb://localhost:27017/iotagent', { useNewUrlParser: true }, function(err, db) { - iotAgentDb = db; - done(); - }); + mongo.connect( + 'mongodb://localhost:27017/iotagent', + { useNewUrlParser: true }, + function(err, db) { + iotAgentDb = db; + done(); + } + ); }); - }); }); @@ -200,35 +201,43 @@ describe('MongoDB Group Registry test', function() { describe('When a new device group creation request arrives', function() { it('should store it in the DB', function(done) { request(optionsCreation, function(error, response, body) { - iotAgentDb.db().collection('groups').find({}).toArray(function(err, docs) { - should.not.exist(err); - should.exist(docs); - should.exist(docs.length); - docs.length.should.equal(1); - should.exist(docs[0].type); - should.exist(docs[0].internalAttributes); - should.exist(docs[0].attributes); - should.exist(docs[0].apikey); - docs[0].type.should.equal('Light'); - docs[0].apikey.should.equal('801230BJKL23Y9090DSFL123HJK09H324HV8732'); - docs[0].internalAttributes.length.should.equal(1); - docs[0].internalAttributes[0].customField.should.equal('customValue'); - docs[0].attributes.length.should.equal(1); - docs[0].attributes[0].name.should.equal('status'); - done(); - }); + iotAgentDb + .db() + .collection('groups') + .find({}) + .toArray(function(err, docs) { + should.not.exist(err); + should.exist(docs); + should.exist(docs.length); + docs.length.should.equal(1); + should.exist(docs[0].type); + should.exist(docs[0].internalAttributes); + should.exist(docs[0].attributes); + should.exist(docs[0].apikey); + docs[0].type.should.equal('Light'); + docs[0].apikey.should.equal('801230BJKL23Y9090DSFL123HJK09H324HV8732'); + docs[0].internalAttributes.length.should.equal(1); + docs[0].internalAttributes[0].customField.should.equal('customValue'); + docs[0].attributes.length.should.equal(1); + docs[0].attributes[0].name.should.equal('status'); + done(); + }); }); }); it('should store the service information from the headers into the DB', function(done) { request(optionsCreation, function(error, response, body) { - iotAgentDb.db().collection('groups').find({}).toArray(function(err, docs) { - should.not.exist(err); - should.exist(docs[0].service); - should.exist(docs[0].subservice); - docs[0].service.should.equal('TestService'); - docs[0].subservice.should.equal('/testingPath'); - done(); - }); + iotAgentDb + .db() + .collection('groups') + .find({}) + .toArray(function(err, docs) { + should.not.exist(err); + should.exist(docs[0].service); + should.exist(docs[0].subservice); + docs[0].service.should.equal('TestService'); + docs[0].subservice.should.equal('/testingPath'); + done(); + }); }); }); }); @@ -252,13 +261,17 @@ describe('MongoDB Group Registry test', function() { it('should remove it from the database', function(done) { request(optionsDelete, function(error, response, body) { - iotAgentDb.db().collection('groups').find({}).toArray(function(err, docs) { - should.not.exist(err); - should.exist(docs); - should.exist(docs.length); - docs.length.should.equal(0); - done(); - }); + iotAgentDb + .db() + .collection('groups') + .find({}) + .toArray(function(err, docs) { + should.not.exist(err); + should.exist(docs); + should.exist(docs.length); + docs.length.should.equal(0); + done(); + }); }); }); @@ -277,47 +290,55 @@ describe('MongoDB Group Registry test', function() { it('should update the values in the database', function(done) { request(optionsUpdate, function(error, response, body) { - iotAgentDb.db().collection('groups').find({}).toArray(function(err, docs) { - should.not.exist(err); - should.exist(docs); - should.exist(docs[0].cbHost); - docs[0].cbHost.should.equal('http://anotherUnexistentHost:1026'); - should.exist(docs[0].staticAttributes); - docs[0].staticAttributes.length.should.equal(1); - done(); - }); + iotAgentDb + .db() + .collection('groups') + .find({}) + .toArray(function(err, docs) { + should.not.exist(err); + should.exist(docs); + should.exist(docs[0].cbHost); + docs[0].cbHost.should.equal('http://anotherUnexistentHost:1026'); + should.exist(docs[0].staticAttributes); + docs[0].staticAttributes.length.should.equal(1); + done(); + }); }); }); }); describe('When a multiple device group creation arrives', function() { - var optionsMultipleCreation = _.clone(optionsCreation); + const optionsMultipleCreation = _.clone(optionsCreation); beforeEach(function(done) { optionsMultipleCreation.json = utils.readExampleFile( - './test/unit/examples/groupProvisioningRequests/multipleGroupsCreation.json'); + './test/unit/examples/groupProvisioningRequests/multipleGroupsCreation.json' + ); done(); }); it('should create the values in the database', function(done) { request(optionsMultipleCreation, function(error, response, body) { - iotAgentDb.db().collection('groups').find({}).toArray(function(err, docs) { - should.not.exist(err); - should.exist(docs); - docs.length.should.equal(2); - done(); - }); + iotAgentDb + .db() + .collection('groups') + .find({}) + .toArray(function(err, docs) { + should.not.exist(err); + should.exist(docs); + docs.length.should.equal(2); + done(); + }); }); }); }); describe('When a device group listing request arrives', function() { beforeEach(function(done) { - var optionsCreation1 = _.clone(optionsCreation), - optionsCreation2 = _.clone(optionsCreation), - optionsCreation3 = _.clone(optionsCreation); - + const optionsCreation1 = _.clone(optionsCreation); + const optionsCreation2 = _.clone(optionsCreation); + const optionsCreation3 = _.clone(optionsCreation); optionsCreation2.json = { services: [] }; optionsCreation3.json = { services: [] }; @@ -328,11 +349,14 @@ describe('MongoDB Group Registry test', function() { optionsCreation2.json.services[0].apikey = 'qwertyuiop'; optionsCreation3.json.services[0].apikey = 'lkjhgfds'; - async.series([ - async.apply(request, optionsCreation1), - async.apply(request, optionsCreation2), - async.apply(request, optionsCreation3) - ], done); + async.series( + [ + async.apply(request, optionsCreation1), + async.apply(request, optionsCreation2), + async.apply(request, optionsCreation3) + ], + done + ); }); it('should return all the configured device groups from the database', function(done) { @@ -344,7 +368,7 @@ describe('MongoDB Group Registry test', function() { }); describe('When a device group listing arrives with a limit', function() { - var optionsConstrained = { + const optionsConstrained = { url: 'http://localhost:4041/iot/services', method: 'GET', qs: { @@ -359,10 +383,10 @@ describe('MongoDB Group Registry test', function() { }; beforeEach(function(done) { - var optionsCreationList = [], - creationFns = []; + const optionsCreationList = []; + const creationFns = []; - for (var i = 0; i < 10; i++) { + for (let i = 0; i < 10; i++) { optionsCreationList[i] = _.clone(optionsCreation); optionsCreationList[i].json = { services: [] }; optionsCreationList[i].json.services[0] = _.clone(optionsCreation.json.services[0]); @@ -383,9 +407,7 @@ describe('MongoDB Group Registry test', function() { describe('When a device info request arrives', function() { beforeEach(function(done) { - async.series([ - async.apply(request, optionsCreation) - ], done); + async.series([async.apply(request, optionsCreation)], done); }); it('should return all the configured device groups from the database', function(done) { @@ -404,10 +426,10 @@ describe('MongoDB Group Registry test', function() { describe('When a device info request arrives and multiple groups have been created', function() { beforeEach(function(done) { - var optionsCreationList = [], - creationFns = []; + const optionsCreationList = []; + const creationFns = []; - for (var i = 0; i < 10; i++) { + for (let i = 0; i < 10; i++) { optionsCreationList[i] = _.clone(optionsCreation); optionsCreationList[i].json = { services: [] }; optionsCreationList[i].json.services[0] = _.clone(optionsCreation.json.services[0]); diff --git a/test/unit/mongodb/mongodb-registry-test.js b/test/unit/mongodb/mongodb-registry-test.js index ee9cfda30..f1ac21ba3 100644 --- a/test/unit/mongodb/mongodb-registry-test.js +++ b/test/unit/mongodb/mongodb-registry-test.js @@ -20,191 +20,198 @@ * For those usages not covered by the GNU Affero General Public License * please contact with::[contacto@tid.es] */ -'use strict'; - -var iotAgentLib = require('../../../lib/fiware-iotagent-lib'), - utils = require('../../tools/utils'), - should = require('should'), - logger = require('logops'), - mongo = require('mongodb').MongoClient, - nock = require('nock'), - async = require('async'), - mongoUtils = require('./mongoDBUtils'), - contextBrokerMock, - iotAgentConfig = { - contextBroker: { - host: '192.168.1.1', - port: '1026' - }, - server: { - port: 4041 - }, - types: { - 'Light': { - commands: [ - { - name: 'position', - type: 'Array' - } - ], - lazy: [ - { - name: 'temperature', - type: 'centigrades' - } - ], - attributes: [ - { - name: 'pressure', - type: 'Hgmm' - } - ], - staticAttributes: [ - { - name: 'location', - type: 'Vector' - } - ], - service: 'smartGondor', - subservice: 'gardens', - internalAttributes: { - customAttribute: 'customValue' + +/* eslint-disable no-unused-vars */ + +const iotAgentLib = require('../../../lib/fiware-iotagent-lib'); +const utils = require('../../tools/utils'); +const should = require('should'); +const logger = require('logops'); +const mongo = require('mongodb').MongoClient; +const nock = require('nock'); +const async = require('async'); +const mongoUtils = require('./mongoDBUtils'); +let contextBrokerMock; +const iotAgentConfig = { + contextBroker: { + host: '192.168.1.1', + port: '1026' + }, + server: { + port: 4041 + }, + types: { + Light: { + commands: [ + { + name: 'position', + type: 'Array' + } + ], + lazy: [ + { + name: 'temperature', + type: 'centigrades' + } + ], + attributes: [ + { + name: 'pressure', + type: 'Hgmm' } - }, - 'Termometer': { - commands: [], - lazy: [ - { - name: 'temp', - type: 'kelvin' - } - ], - attributes: [ - ], - service: 'smartGondor', - subservice: 'gardens' + ], + staticAttributes: [ + { + name: 'location', + type: 'Vector' + } + ], + service: 'smartGondor', + subservice: 'gardens', + internalAttributes: { + customAttribute: 'customValue' } }, - deviceRegistry: { - type: 'mongodb' - }, - mongodb: { - host: 'localhost', - port: '27017', - db: 'iotagent' - }, - service: 'smartGondor', - subservice: 'gardens', - providerUrl: 'http://smartGondor.com', - deviceRegistrationDuration: 'P1M' - }, - device1 = { - id: 'light1', - type: 'Light', - service: 'smartGondor', - subservice: 'gardens', - endpoint: 'http://testEndpoint.com', - transport: 'HTTP', - resource: '/test', - apikey: '2345678ikjhgfr678i', - protocol: 'GENERIC_PROTOCOL', - commands: [ - { - name: 'position', - type: 'Array' - } - ], - lazy: [ - { - name: 'temperature', - type: 'centigrades' - } - ], - active: [ - { - name: 'pressure', - type: 'Hgmm' - } - ], - staticAttributes: [ - { - name: 'location', - type: 'Vector' - } - ], - internalAttributes: { - customAttribute: 'customValue' + Termometer: { + commands: [], + lazy: [ + { + name: 'temp', + type: 'kelvin' + } + ], + attributes: [], + service: 'smartGondor', + subservice: 'gardens' } }, - device2 = { - id: 'term2', - type: 'Termometer', - service: 'smartGondor', - subservice: 'gardens', - resource: '/', - apikey: 'dsf8yy789iyushu786', - protocol: 'GENERIC_PROTOCOL' + deviceRegistry: { + type: 'mongodb' }, - device3 = { - id: 'light1', - type: 'Light', - service: 'smartMordor', - subservice: 'electricity', - endpoint: 'http://testEndpoint.com', - transport: 'HTTP', - resource: '/test', - apikey: '2345678ikjhgfr678i', - protocol: 'GENERIC_PROTOCOL', - commands: [ - { - name: 'position', - type: 'Array' - } - ], - lazy: [ - { - name: 'temperature', - type: 'centigrades' - } - ], - active: [ - { - name: 'pressure', - type: 'Hgmm' - } - ], - staticAttributes: [ - { - name: 'location', - type: 'Vector' - } - ], - internalAttributes: { - customAttribute: 'customValue' - } + mongodb: { + host: 'localhost', + port: '27017', + db: 'iotagent' }, - iotAgentDb; + service: 'smartGondor', + subservice: 'gardens', + providerUrl: 'http://smartGondor.com', + deviceRegistrationDuration: 'P1M' +}; +const device1 = { + id: 'light1', + type: 'Light', + service: 'smartGondor', + subservice: 'gardens', + endpoint: 'http://testEndpoint.com', + transport: 'HTTP', + resource: '/test', + apikey: '2345678ikjhgfr678i', + protocol: 'GENERIC_PROTOCOL', + commands: [ + { + name: 'position', + type: 'Array' + } + ], + lazy: [ + { + name: 'temperature', + type: 'centigrades' + } + ], + active: [ + { + name: 'pressure', + type: 'Hgmm' + } + ], + staticAttributes: [ + { + name: 'location', + type: 'Vector' + } + ], + internalAttributes: { + customAttribute: 'customValue' + } +}; +const device2 = { + id: 'term2', + type: 'Termometer', + service: 'smartGondor', + subservice: 'gardens', + resource: '/', + apikey: 'dsf8yy789iyushu786', + protocol: 'GENERIC_PROTOCOL' +}; +const device3 = { + id: 'light1', + type: 'Light', + service: 'smartMordor', + subservice: 'electricity', + endpoint: 'http://testEndpoint.com', + transport: 'HTTP', + resource: '/test', + apikey: '2345678ikjhgfr678i', + protocol: 'GENERIC_PROTOCOL', + commands: [ + { + name: 'position', + type: 'Array' + } + ], + lazy: [ + { + name: 'temperature', + type: 'centigrades' + } + ], + active: [ + { + name: 'pressure', + type: 'Hgmm' + } + ], + staticAttributes: [ + { + name: 'location', + type: 'Vector' + } + ], + internalAttributes: { + customAttribute: 'customValue' + } +}; +let iotAgentDb; describe('MongoDB Device Registry', function() { beforeEach(function(done) { logger.setLevel('FATAL'); mongoUtils.cleanDbs(function() { - mongo.connect('mongodb://localhost:27017/iotagent', { useNewUrlParser: true }, function(err, db) { - iotAgentDb = db; - done(); - }); + mongo.connect( + 'mongodb://localhost:27017/iotagent', + { useNewUrlParser: true }, + function(err, db) { + iotAgentDb = db; + done(); + } + ); }); }); afterEach(function(done) { - delete(device1.registrationId); + delete device1.registrationId; iotAgentLib.deactivate(function(error) { - iotAgentDb.db().collection('devices').deleteOne(function(error) { - iotAgentDb.close(function(error) { - mongoUtils.cleanDbs(done); + iotAgentDb + .db() + .collection('devices') + .deleteOne(function(error) { + iotAgentDb.close(function(error) { + mongoUtils.cleanDbs(done); + }); }); - }); }); }); @@ -215,16 +222,23 @@ describe('MongoDB Device Registry', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/NGSI9/registerContext', utils.readExampleFile( - './test/unit/examples/contextAvailabilityRequests/registerIoTAgent3.json')) - .reply(200, utils.readExampleFile( - './test/unit/examples/contextAvailabilityResponses/registerIoTAgent1Success.json')); + .post( + '/NGSI9/registerContext', + utils.readExampleFile('./test/unit/examples/contextAvailabilityRequests/registerIoTAgent3.json') + ) + .reply( + 200, + utils.readExampleFile( + './test/unit/examples/contextAvailabilityResponses/registerIoTAgent1Success.json' + ) + ); contextBrokerMock .post('/v1/updateContext') - .reply(200, - utils.readExampleFile( - './test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json')); + .reply( + 200, + utils.readExampleFile('./test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json') + ); iotAgentLib.activate(iotAgentConfig, function(error) { done(); @@ -235,34 +249,38 @@ describe('MongoDB Device Registry', function() { iotAgentLib.register(device1, function(error) { should.not.exist(error); - iotAgentDb.db().collection('devices').find({}).toArray(function(err, docs) { - should.not.exist(err); - should.exist(docs); - should.exist(docs.length); - docs.length.should.equal(1); - should.exist(docs[0].internalAttributes); - should.exist(docs[0].staticAttributes); - should.exist(docs[0].internalAttributes.customAttribute); - should.exist(docs[0].active); - should.exist(docs[0].commands); - should.exist(docs[0].resource); - should.exist(docs[0].endpoint); - should.exist(docs[0].transport); - should.exist(docs[0].apikey); - should.exist(docs[0].protocol); - docs[0].active.length.should.equal(1); - docs[0].staticAttributes.length.should.equal(1); - docs[0].staticAttributes[0].name.should.equal('location'); - docs[0].active[0].name.should.equal('pressure'); - docs[0].commands[0].name.should.equal('position'); - docs[0].internalAttributes.customAttribute.should.equal('customValue'); - docs[0].resource.should.equal('/test'); - docs[0].endpoint.should.equal('http://testEndpoint.com'); - docs[0].transport.should.equal('HTTP'); - docs[0].protocol.should.equal('GENERIC_PROTOCOL'); - docs[0].apikey.should.equal('2345678ikjhgfr678i'); - done(); - }); + iotAgentDb + .db() + .collection('devices') + .find({}) + .toArray(function(err, docs) { + should.not.exist(err); + should.exist(docs); + should.exist(docs.length); + docs.length.should.equal(1); + should.exist(docs[0].internalAttributes); + should.exist(docs[0].staticAttributes); + should.exist(docs[0].internalAttributes.customAttribute); + should.exist(docs[0].active); + should.exist(docs[0].commands); + should.exist(docs[0].resource); + should.exist(docs[0].endpoint); + should.exist(docs[0].transport); + should.exist(docs[0].apikey); + should.exist(docs[0].protocol); + docs[0].active.length.should.equal(1); + docs[0].staticAttributes.length.should.equal(1); + docs[0].staticAttributes[0].name.should.equal('location'); + docs[0].active[0].name.should.equal('pressure'); + docs[0].commands[0].name.should.equal('position'); + docs[0].internalAttributes.customAttribute.should.equal('customValue'); + docs[0].resource.should.equal('/test'); + docs[0].endpoint.should.equal('http://testEndpoint.com'); + docs[0].transport.should.equal('HTTP'); + docs[0].protocol.should.equal('GENERIC_PROTOCOL'); + docs[0].apikey.should.equal('2345678ikjhgfr678i'); + done(); + }); }); }); }); @@ -274,28 +292,44 @@ describe('MongoDB Device Registry', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/NGSI9/registerContext', utils.readExampleFile( - './test/unit/examples/contextAvailabilityRequests/registerIoTAgent3.json')) - .reply(200, utils.readExampleFile( - './test/unit/examples/contextAvailabilityResponses/registerIoTAgent1Success.json')); + .post( + '/NGSI9/registerContext', + utils.readExampleFile('./test/unit/examples/contextAvailabilityRequests/registerIoTAgent3.json') + ) + .reply( + 200, + utils.readExampleFile( + './test/unit/examples/contextAvailabilityResponses/registerIoTAgent1Success.json' + ) + ); contextBrokerMock .post('/v1/updateContext') - .reply(200, utils.readExampleFile( - './test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json')); + .reply( + 200, + utils.readExampleFile('./test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json') + ); contextBrokerMock .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/NGSI9/registerContext', utils.readExampleFile( - './test/unit/examples/contextAvailabilityRequests/registerIoTAgent3.json')) - .reply(200, utils.readExampleFile( - './test/unit/examples/contextAvailabilityResponses/registerIoTAgent1Success.json')); + .post( + '/NGSI9/registerContext', + utils.readExampleFile('./test/unit/examples/contextAvailabilityRequests/registerIoTAgent3.json') + ) + .reply( + 200, + utils.readExampleFile( + './test/unit/examples/contextAvailabilityResponses/registerIoTAgent1Success.json' + ) + ); contextBrokerMock .post('/v1/updateContext') - .reply(200, utils.readExampleFile( - './test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json')); + .reply( + 200, + utils.readExampleFile('./test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json') + ); iotAgentLib.activate(iotAgentConfig, function(error) { done(); @@ -318,26 +352,42 @@ describe('MongoDB Device Registry', function() { nock.cleanAll(); contextBrokerMock = nock('http://192.168.1.1:1026') - .post('/NGSI9/registerContext', utils.readExampleFile( - './test/unit/examples/contextAvailabilityRequests/registerIoTAgent3.json')) - .reply(200, utils.readExampleFile( - './test/unit/examples/contextAvailabilityResponses/registerIoTAgent1Success.json')); + .post( + '/NGSI9/registerContext', + utils.readExampleFile('./test/unit/examples/contextAvailabilityRequests/registerIoTAgent3.json') + ) + .reply( + 200, + utils.readExampleFile( + './test/unit/examples/contextAvailabilityResponses/registerIoTAgent1Success.json' + ) + ); contextBrokerMock .post('/v1/updateContext') - .reply(200, utils.readExampleFile( - './test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json')); + .reply( + 200, + utils.readExampleFile('./test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json') + ); contextBrokerMock - .post('/NGSI9/registerContext', utils.readExampleFile( - './test/unit/examples/contextAvailabilityRequests/registerIoTAgent3.json')) - .reply(200, utils.readExampleFile( - './test/unit/examples/contextAvailabilityResponses/registerIoTAgent1Success.json')); + .post( + '/NGSI9/registerContext', + utils.readExampleFile('./test/unit/examples/contextAvailabilityRequests/registerIoTAgent3.json') + ) + .reply( + 200, + utils.readExampleFile( + './test/unit/examples/contextAvailabilityResponses/registerIoTAgent1Success.json' + ) + ); contextBrokerMock .post('/v1/updateContext') - .reply(200, utils.readExampleFile( - './test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json')); + .reply( + 200, + utils.readExampleFile('./test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json') + ); iotAgentLib.activate(iotAgentConfig, function(error) { done(); @@ -356,54 +406,73 @@ describe('MongoDB Device Registry', function() { describe('When a device is removed from the IoT Agent', function() { beforeEach(function(done) { - var expectedPayload3 = utils - .readExampleFile('./test/unit/examples/contextAvailabilityRequests/unregisterDevice3.json'); + const expectedPayload3 = utils.readExampleFile( + './test/unit/examples/contextAvailabilityRequests/unregisterDevice3.json' + ); nock.cleanAll(); contextBrokerMock = nock('http://192.168.1.1:1026') .post('/NGSI9/registerContext') - .reply(200, utils.readExampleFile( - './test/unit/examples/contextAvailabilityResponses/registerNewDevice1Success.json')); + .reply( + 200, + utils.readExampleFile( + './test/unit/examples/contextAvailabilityResponses/registerNewDevice1Success.json' + ) + ); contextBrokerMock .post('/v1/updateContext') - .reply(200, - utils.readExampleFile( - './test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json')); + .reply( + 200, + utils.readExampleFile('./test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json') + ); contextBrokerMock .post('/NGSI9/registerContext') - .reply(200, utils.readExampleFile( - './test/unit/examples/contextAvailabilityResponses/registerNewDevice2Success.json')); + .reply( + 200, + utils.readExampleFile( + './test/unit/examples/contextAvailabilityResponses/registerNewDevice2Success.json' + ) + ); contextBrokerMock .post('/v1/updateContext') - .reply(200, - utils.readExampleFile( - './test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json')); + .reply( + 200, + utils.readExampleFile('./test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json') + ); contextBrokerMock .post('/NGSI9/registerContext', expectedPayload3) - .reply(200, utils.readExampleFile( - './test/unit/examples/contextAvailabilityResponses/unregisterDevice1Success.json')); + .reply( + 200, + utils.readExampleFile( + './test/unit/examples/contextAvailabilityResponses/unregisterDevice1Success.json' + ) + ); iotAgentLib.activate(iotAgentConfig, function(error) { - async.series([ - async.apply(iotAgentLib.register, device1), - async.apply(iotAgentLib.register, device2) - ], done); + async.series( + [async.apply(iotAgentLib.register, device1), async.apply(iotAgentLib.register, device2)], + done + ); }); }); it('should be removed from MongoDB', function(done) { iotAgentLib.unregister(device1.id, 'smartGondor', 'gardens', function(error) { - iotAgentDb.db().collection('devices').find({}).toArray(function(err, docs) { - should.not.exist(err); - should.exist(docs); - should.exist(docs.length); - docs.length.should.equal(1); - done(); - }); + iotAgentDb + .db() + .collection('devices') + .find({}) + .toArray(function(err, docs) { + should.not.exist(err); + should.exist(docs); + should.exist(docs.length); + docs.length.should.equal(1); + done(); + }); }); }); }); @@ -415,13 +484,14 @@ describe('MongoDB Device Registry', function() { .times(10) .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .reply(200, - utils.readExampleFile( - './test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json')); + .reply( + 200, + utils.readExampleFile('./test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json') + ); - var devices = []; + const devices = []; - for (var i = 0; i < 10; i++) { + for (let i = 0; i < 10; i++) { devices.push({ id: 'id' + i, type: 'Light' + i, @@ -448,14 +518,16 @@ describe('MongoDB Device Registry', function() { iotAgentLib.clearRegistry(done); }); it('should return the appropriate device', function(done) { - iotAgentLib.getDevicesByAttribute('internalId', 'internal3', 'smartGondor', 'gardens', - function(error, devices) { - should.not.exist(error); - should.exist(devices); - devices.length.should.equal(1); - devices[0].id.should.equal('id3'); - done(); - }); + iotAgentLib.getDevicesByAttribute('internalId', 'internal3', 'smartGondor', 'gardens', function( + error, + devices + ) { + should.not.exist(error); + should.exist(devices); + devices.length.should.equal(1); + devices[0].id.should.equal('id3'); + done(); + }); }); }); @@ -466,13 +538,14 @@ describe('MongoDB Device Registry', function() { .times(10) .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .reply(200, - utils.readExampleFile( - './test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json')); + .reply( + 200, + utils.readExampleFile('./test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json') + ); - var devices = []; + const devices = []; - for (var i = 0; i < 10; i++) { + for (let i = 0; i < 10; i++) { devices.push({ id: 'id' + i, type: 'Light' + i, diff --git a/test/unit/ngsiService/active-devices-test.js b/test/unit/ngsiService/active-devices-test.js index 648f9a392..0f9771528 100644 --- a/test/unit/ngsiService/active-devices-test.js +++ b/test/unit/ngsiService/active-devices-test.js @@ -20,106 +20,104 @@ * For those usages not covered by the GNU Affero General Public License * please contact with::[contacto@tid.es] */ -'use strict'; - -var iotAgentLib = require('../../../lib/fiware-iotagent-lib'), - utils = require('../../tools/utils'), - timekeeper = require('timekeeper'), - should = require('should'), - logger = require('logops'), - nock = require('nock'), - contextBrokerMock, - iotAgentConfig = { - contextBroker: { - host: '192.168.1.1', - port: '1026' + +const iotAgentLib = require('../../../lib/fiware-iotagent-lib'); +const utils = require('../../tools/utils'); +const timekeeper = require('timekeeper'); +const should = require('should'); +const logger = require('logops'); +const nock = require('nock'); +let contextBrokerMock; +const iotAgentConfig = { + contextBroker: { + host: '192.168.1.1', + port: '1026' + }, + server: { + port: 4041 + }, + types: { + Light: { + commands: [], + type: 'Light', + lazy: [ + { + name: 'temperature', + type: 'centigrades' + } + ], + active: [ + { + name: 'pressure', + type: 'Hgmm' + } + ] }, - server: { - port: 4041 + BrokenLight: { + commands: [], + lazy: [ + { + name: 'temperature', + type: 'centigrades' + } + ], + active: [ + { + name: 'pressure', + type: 'Hgmm' + } + ] }, - types: { - 'Light': { - commands: [], - type: 'Light', - lazy: [ - { - name: 'temperature', - type: 'centigrades' - } - ], - active: [ - { - name: 'pressure', - type: 'Hgmm' - } - ] - }, - 'BrokenLight': { - commands: [], - lazy: [ - { - name: 'temperature', - type: 'centigrades' - } - ], - active: [ - { - name: 'pressure', - type: 'Hgmm' - } - ] - }, - 'Termometer': { - type: 'Termometer', - commands: [], - lazy: [ - { - name: 'temp', - type: 'kelvin' - } - ], - active: [ - ] - }, - 'Humidity': { - type: 'Humidity', - cbHost: 'http://192.168.1.1:3024', - commands: [], - lazy: [], - active: [ - { - name: 'humidity', - type: 'percentage' - } - ] - }, - 'Motion': { - type: 'Motion', - commands: [], - lazy: [], - staticAttributes: [ - { - 'name': 'location', - 'type': 'Vector', - 'value': '(123,523)' - } - ], - active: [ - { - name: 'humidity', - type: 'percentage' - } - ] - } + Termometer: { + type: 'Termometer', + commands: [], + lazy: [ + { + name: 'temp', + type: 'kelvin' + } + ], + active: [] + }, + Humidity: { + type: 'Humidity', + cbHost: 'http://192.168.1.1:3024', + commands: [], + lazy: [], + active: [ + { + name: 'humidity', + type: 'percentage' + } + ] }, - service: 'smartGondor', - subservice: 'gardens', - providerUrl: 'http://smartGondor.com', - deviceRegistrationDuration: 'P1M' - }; + Motion: { + type: 'Motion', + commands: [], + lazy: [], + staticAttributes: [ + { + name: 'location', + type: 'Vector', + value: '(123,523)' + } + ], + active: [ + { + name: 'humidity', + type: 'percentage' + } + ] + } + }, + service: 'smartGondor', + subservice: 'gardens', + providerUrl: 'http://smartGondor.com', + deviceRegistrationDuration: 'P1M' +}; describe('Active attributes test', function() { - var values = [ + const values = [ { name: 'state', type: 'Boolean', @@ -147,10 +145,11 @@ describe('Active attributes test', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v1/updateContext', - utils.readExampleFile('./test/unit/examples/contextRequests/updateContext1.json')) - .reply(200, - utils.readExampleFile('./test/unit/examples/contextResponses/updateContext1Success.json')); + .post( + '/v1/updateContext', + utils.readExampleFile('./test/unit/examples/contextRequests/updateContext1.json') + ) + .reply(200, utils.readExampleFile('./test/unit/examples/contextResponses/updateContext1Success.json')); iotAgentLib.activate(iotAgentConfig, done); }); @@ -171,10 +170,11 @@ describe('Active attributes test', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v1/updateContext', - utils.readExampleFile('./test/unit/examples/contextRequests/updateContextAppendMode.json')) - .reply(200, - utils.readExampleFile('./test/unit/examples/contextResponses/updateContext1Success.json')); + .post( + '/v1/updateContext', + utils.readExampleFile('./test/unit/examples/contextRequests/updateContextAppendMode.json') + ) + .reply(200, utils.readExampleFile('./test/unit/examples/contextResponses/updateContext1Success.json')); iotAgentConfig.appendMode = true; iotAgentLib.activate(iotAgentConfig, done); @@ -196,10 +196,10 @@ describe('Active attributes test', function() { }); describe('When the IoT Agent receives new information and the timestamp flag is on', function() { - var modifiedValues; + let modifiedValues; beforeEach(function(done) { - var time = new Date(1438760101468); // 2015-08-05T07:35:01.468+00:00 + const time = new Date(1438760101468); // 2015-08-05T07:35:01.468+00:00 modifiedValues = [ { @@ -221,10 +221,11 @@ describe('Active attributes test', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v1/updateContext', - utils.readExampleFile('./test/unit/examples/contextRequests/updateContextTimestamp.json')) - .reply(200, - utils.readExampleFile('./test/unit/examples/contextResponses/updateContext1Success.json')); + .post( + '/v1/updateContext', + utils.readExampleFile('./test/unit/examples/contextRequests/updateContextTimestamp.json') + ) + .reply(200, utils.readExampleFile('./test/unit/examples/contextResponses/updateContext1Success.json')); iotAgentConfig.timestamp = true; iotAgentLib.activate(iotAgentConfig, done); @@ -246,12 +247,11 @@ describe('Active attributes test', function() { }); }); - describe('When the IoT Agent receives new information, the timestamp flag is on' + - 'and timezone is defined', function() { - var modifiedValues; + describe('When the IoT Agent receives new information, the timestamp flag is on and timezone is defined', function() { + let modifiedValues; beforeEach(function(done) { - var time = new Date(1438760101468); // 2015-08-05T07:35:01.468+00:00 + const time = new Date(1438760101468); // 2015-08-05T07:35:01.468+00:00 modifiedValues = [ { @@ -273,10 +273,11 @@ describe('Active attributes test', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v1/updateContext', - utils.readExampleFile('./test/unit/examples/contextRequests/updateContextTimestampTimezone.json')) - .reply(200, - utils.readExampleFile('./test/unit/examples/contextResponses/updateContext1Success.json')); + .post( + '/v1/updateContext', + utils.readExampleFile('./test/unit/examples/contextRequests/updateContextTimestampTimezone.json') + ) + .reply(200, utils.readExampleFile('./test/unit/examples/contextResponses/updateContext1Success.json')); iotAgentConfig.timestamp = true; iotAgentConfig.types.Light.timezone = 'America/Los_Angeles'; @@ -301,10 +302,10 @@ describe('Active attributes test', function() { }); describe('When the IoTA gets a set of values with a TimeInstant and the timestamp flag is on', function() { - var modifiedValues; + let modifiedValues; beforeEach(function(done) { - var time = new Date(1438760101468); // 2015-08-05T07:35:01.468+00:00 + const time = new Date(1438760101468); // 2015-08-05T07:35:01.468+00:00 modifiedValues = [ { @@ -326,10 +327,11 @@ describe('Active attributes test', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v1/updateContext', - utils.readExampleFile('./test/unit/examples/contextRequests/updateContextTimestampOverride.json')) - .reply(200, - utils.readExampleFile('./test/unit/examples/contextResponses/updateContext1Success.json')); + .post( + '/v1/updateContext', + utils.readExampleFile('./test/unit/examples/contextRequests/updateContextTimestampOverride.json') + ) + .reply(200, utils.readExampleFile('./test/unit/examples/contextResponses/updateContext1Success.json')); iotAgentConfig.timestamp = true; iotAgentLib.activate(iotAgentConfig, done); @@ -352,10 +354,9 @@ describe('Active attributes test', function() { }); describe('When the IoTA gets a set of values with a TimeInstant which are not in ISO8601 format', function() { - var modifiedValues; + let modifiedValues; beforeEach(function(done) { - modifiedValues = [ { name: 'state', @@ -390,12 +391,11 @@ describe('Active attributes test', function() { }); }); - describe('When the IoTA gets a set of values with a TimeInstant which are in ISO8601 format ' + - 'without milis', function() { - var modifiedValues; + describe('When the IoTA gets a set of values with a TimeInstant which are in ISO8601 format without milis', function() { + let modifiedValues; beforeEach(function(done) { - var time = new Date(1666477342000); // 2022-10-22T22:22:22Z + const time = new Date(1666477342000); // 2022-10-22T22:22:22Z modifiedValues = [ { @@ -417,11 +417,13 @@ describe('Active attributes test', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v1/updateContext', - utils.readExampleFile('./test/unit/examples/contextRequests/' + - 'updateContextTimestampOverrideWithoutMilis.json')) - .reply(200, - utils.readExampleFile('./test/unit/examples/contextResponses/updateContext1Success.json')); + .post( + '/v1/updateContext', + utils.readExampleFile( + './test/unit/examples/contextRequests/ updateContextTimestampOverrideWithoutMilis.json' + ) + ) + .reply(200, utils.readExampleFile('./test/unit/examples/contextResponses/updateContext1Success.json')); iotAgentConfig.timestamp = true; iotAgentConfig.types.Light.timezone = 'America/Los_Angeles'; @@ -444,12 +446,11 @@ describe('Active attributes test', function() { }); }); - describe('When the IoTA gets a set of values with a TimeInstant, the timestamp flag is on' + - 'and timezone is defined', function() { - var modifiedValues; + describe('When the IoTA gets a set of values with a TimeInstant, the timestamp flag is on and timezone is defined', function() { + let modifiedValues; beforeEach(function(done) { - var time = new Date(1438760101468); // 2015-08-05T07:35:01.468+00:00 + const time = new Date(1438760101468); // 2015-08-05T07:35:01.468+00:00 modifiedValues = [ { @@ -471,10 +472,11 @@ describe('Active attributes test', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v1/updateContext', - utils.readExampleFile('./test/unit/examples/contextRequests/updateContextTimestampOverride.json')) - .reply(200, - utils.readExampleFile('./test/unit/examples/contextResponses/updateContext1Success.json')); + .post( + '/v1/updateContext', + utils.readExampleFile('./test/unit/examples/contextRequests/updateContextTimestampOverride.json') + ) + .reply(200, utils.readExampleFile('./test/unit/examples/contextResponses/updateContext1Success.json')); iotAgentConfig.timestamp = true; iotAgentConfig.types.Light.timezone = 'America/Los_Angeles'; @@ -488,7 +490,6 @@ describe('Active attributes test', function() { done(); }); - it('should not override the received instant and should not add metadatas for this request', function(done) { iotAgentLib.update('light1', 'Light', '', modifiedValues, function(error) { should.not.exist(error); @@ -498,7 +499,7 @@ describe('Active attributes test', function() { }); }); - describe('When the IoT Agent receives information from a device whose type doesn\'t have a type name', function() { + describe("When the IoT Agent receives information from a device whose type doesn't have a type name", function() { beforeEach(function(done) { nock.cleanAll(); @@ -522,10 +523,11 @@ describe('Active attributes test', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v1/updateContext', - utils.readExampleFile('./test/unit/examples/contextRequests/updateContext1.json')) - .reply(200, - utils.readExampleFile('./test/unit/examples/contextResponses/updateContext1Failed.json')); + .post( + '/v1/updateContext', + utils.readExampleFile('./test/unit/examples/contextRequests/updateContext1.json') + ) + .reply(200, utils.readExampleFile('./test/unit/examples/contextResponses/updateContext1Failed.json')); iotAgentLib.activate(iotAgentConfig, done); }); @@ -550,10 +552,11 @@ describe('Active attributes test', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v1/updateContext', - utils.readExampleFile('./test/unit/examples/contextRequests/updateContext1.json')) - .reply(200, - utils.readExampleFile('./test/unit/examples/contextResponses/updateContext2Failed.json')); + .post( + '/v1/updateContext', + utils.readExampleFile('./test/unit/examples/contextRequests/updateContext1.json') + ) + .reply(200, utils.readExampleFile('./test/unit/examples/contextResponses/updateContext2Failed.json')); iotAgentLib.activate(iotAgentConfig, done); }); @@ -575,10 +578,11 @@ describe('Active attributes test', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v1/updateContext', - utils.readExampleFile('./test/unit/examples/contextRequests/updateContext1.json')) - .reply(500, - utils.readExampleFile('./test/unit/examples/contextResponses/updateContext2Failed.json')); + .post( + '/v1/updateContext', + utils.readExampleFile('./test/unit/examples/contextRequests/updateContext1.json') + ) + .reply(500, utils.readExampleFile('./test/unit/examples/contextResponses/updateContext2Failed.json')); iotAgentLib.activate(iotAgentConfig, done); }); @@ -603,10 +607,11 @@ describe('Active attributes test', function() { contextBrokerMock = nock('http://192.168.1.1:3024') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v1/updateContext', - utils.readExampleFile('./test/unit/examples/contextRequests/updateContext2.json')) - .reply(200, - utils.readExampleFile('./test/unit/examples/contextResponses/updateContext1Success.json')); + .post( + '/v1/updateContext', + utils.readExampleFile('./test/unit/examples/contextRequests/updateContext2.json') + ) + .reply(200, utils.readExampleFile('./test/unit/examples/contextResponses/updateContext1Success.json')); iotAgentLib.activate(iotAgentConfig, done); }); @@ -621,7 +626,7 @@ describe('Active attributes test', function() { }); describe('When an IoT Agent receives information for a type with static attributes', function() { - var newValues = [ + const newValues = [ { name: 'moving', type: 'Boolean', @@ -635,10 +640,11 @@ describe('Active attributes test', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v1/updateContext', - utils.readExampleFile('./test/unit/examples/contextRequests/updateContextStaticAttributes.json')) - .reply(200, - utils.readExampleFile('./test/unit/examples/contextResponses/updateContext1Success.json')); + .post( + '/v1/updateContext', + utils.readExampleFile('./test/unit/examples/contextRequests/updateContextStaticAttributes.json') + ) + .reply(200, utils.readExampleFile('./test/unit/examples/contextResponses/updateContext1Success.json')); iotAgentLib.activate(iotAgentConfig, done); }); @@ -651,8 +657,7 @@ describe('Active attributes test', function() { }); }); - describe('When the IoT Agent receives new information from a device and CB' + - 'is defined using environment variables', function() { + describe('When the IoT Agent receives new information from a device and CB is defined using environment variables', function() { beforeEach(function(done) { process.env.IOTA_CB_HOST = 'cbhost'; @@ -661,10 +666,11 @@ describe('Active attributes test', function() { contextBrokerMock = nock('http://cbhost:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v1/updateContext', - utils.readExampleFile('./test/unit/examples/contextRequests/updateContext1.json')) - .reply(200, - utils.readExampleFile('./test/unit/examples/contextResponses/updateContext1Success.json')); + .post( + '/v1/updateContext', + utils.readExampleFile('./test/unit/examples/contextRequests/updateContext1.json') + ) + .reply(200, utils.readExampleFile('./test/unit/examples/contextResponses/updateContext1Success.json')); iotAgentLib.activate(iotAgentConfig, done); }); diff --git a/test/unit/ngsiService/queryDeviceInformationInCb-test.js b/test/unit/ngsiService/queryDeviceInformationInCb-test.js index f0dbd50d2..f0ab2a491 100644 --- a/test/unit/ngsiService/queryDeviceInformationInCb-test.js +++ b/test/unit/ngsiService/queryDeviceInformationInCb-test.js @@ -20,113 +20,107 @@ * For those usages not covered by the GNU Affero General Public License * please contact with::[contacto@tid.es] */ -'use strict'; - -var iotAgentLib = require('../../../lib/fiware-iotagent-lib'), - utils = require('../../tools/utils'), - should = require('should'), - logger = require('logops'), - nock = require('nock'), - contextBrokerMock, - iotAgentConfig = { - contextBroker: { - host: '192.168.1.1', - port: '1026' + +const iotAgentLib = require('../../../lib/fiware-iotagent-lib'); +const utils = require('../../tools/utils'); +const should = require('should'); +const logger = require('logops'); +const nock = require('nock'); +let contextBrokerMock; +const iotAgentConfig = { + contextBroker: { + host: '192.168.1.1', + port: '1026' + }, + server: { + port: 4041 + }, + types: { + Light: { + commands: [], + type: 'Light', + lazy: [ + { + name: 'temperature', + type: 'centigrades' + } + ], + active: [ + { + name: 'pressure', + type: 'Hgmm' + } + ] + }, + BrokenLight: { + commands: [], + lazy: [ + { + name: 'temperature', + type: 'centigrades' + } + ], + active: [ + { + name: 'pressure', + type: 'Hgmm' + } + ] }, - server: { - port: 4041 + Termometer: { + type: 'Termometer', + commands: [], + lazy: [ + { + name: 'temp', + type: 'kelvin' + } + ], + active: [] }, - types: { - 'Light': { - commands: [], - type: 'Light', - lazy: [ - { - name: 'temperature', - type: 'centigrades' - } - ], - active: [ - { - name: 'pressure', - type: 'Hgmm' - } - ] - }, - 'BrokenLight': { - commands: [], - lazy: [ - { - name: 'temperature', - type: 'centigrades' - } - ], - active: [ - { - name: 'pressure', - type: 'Hgmm' - } - ] - }, - 'Termometer': { - type: 'Termometer', - commands: [], - lazy: [ - { - name: 'temp', - type: 'kelvin' - } - ], - active: [ - ] - }, - 'Humidity': { - type: 'Humidity', - cbHost: 'http://192.168.1.1:3024', - commands: [], - lazy: [], - active: [ - { - name: 'humidity', - type: 'percentage' - } - ] - }, - 'Motion': { - type: 'Motion', - commands: [], - lazy: [], - staticAttributes: [ - { - 'name': 'location', - 'type': 'Vector', - 'value': '(123,523)' - } - ], - active: [ - { - name: 'humidity', - type: 'percentage' - } - ] - } + Humidity: { + type: 'Humidity', + cbHost: 'http://192.168.1.1:3024', + commands: [], + lazy: [], + active: [ + { + name: 'humidity', + type: 'percentage' + } + ] }, - service: 'smartGondor', - subservice: 'gardens', - providerUrl: 'http://smartGondor.com', - deviceRegistrationDuration: 'P1M' - }; + Motion: { + type: 'Motion', + commands: [], + lazy: [], + staticAttributes: [ + { + name: 'location', + type: 'Vector', + value: '(123,523)' + } + ], + active: [ + { + name: 'humidity', + type: 'percentage' + } + ] + } + }, + service: 'smartGondor', + subservice: 'gardens', + providerUrl: 'http://smartGondor.com', + deviceRegistrationDuration: 'P1M' +}; describe('Query device information in the Context Broker', function() { - var attributes = [ - 'state', - 'dimming' - ]; + const attributes = ['state', 'dimming']; beforeEach(function(done) { logger.setLevel('FATAL'); - iotAgentLib.activate(iotAgentConfig, done); }); @@ -141,10 +135,11 @@ describe('Query device information in the Context Broker', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v1/queryContext', - utils.readExampleFile('./test/unit/examples/contextRequests/queryContext1.json')) - .reply(200, - utils.readExampleFile('./test/unit/examples/contextResponses/queryContext1Success.json')); + .post( + '/v1/queryContext', + utils.readExampleFile('./test/unit/examples/contextRequests/queryContext1.json') + ) + .reply(200, utils.readExampleFile('./test/unit/examples/contextResponses/queryContext1Success.json')); }); it('should return the information about the desired attributes', function(done) { @@ -156,18 +151,18 @@ describe('Query device information in the Context Broker', function() { }); }); - describe('When the user requests information about a device that it\'s not in the CB', function() { + describe("When the user requests information about a device that it's not in the CB", function() { beforeEach(function() { nock.cleanAll(); contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v1/queryContext', - utils.readExampleFile('./test/unit/examples/contextRequests/queryContext2.json')) - .reply(200, - utils.readExampleFile('./test/unit/examples/contextResponses/queryContext2Error.json')); - + .post( + '/v1/queryContext', + utils.readExampleFile('./test/unit/examples/contextRequests/queryContext2.json') + ) + .reply(200, utils.readExampleFile('./test/unit/examples/contextResponses/queryContext2Error.json')); }); it('should return a DEVICE_NOT_FOUND_ERROR', function(done) { @@ -186,11 +181,11 @@ describe('Query device information in the Context Broker', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v1/queryContext', - utils.readExampleFile('./test/unit/examples/contextRequests/queryContext2.json')) - .reply(200, - utils.readExampleFile('./test/unit/examples/contextResponses/queryContext3Error.json')); - + .post( + '/v1/queryContext', + utils.readExampleFile('./test/unit/examples/contextRequests/queryContext2.json') + ) + .reply(200, utils.readExampleFile('./test/unit/examples/contextResponses/queryContext3Error.json')); }); it('should return a DEVICE_NOT_FOUND_ERROR', function(done) { @@ -209,11 +204,14 @@ describe('Query device information in the Context Broker', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v1/queryContext', - utils.readExampleFile('./test/unit/examples/contextRequests/queryContext2.json')) - .reply(200, - utils.readExampleFile('./test/unit/examples/contextResponses/queryContext2UnknownError.json')); - + .post( + '/v1/queryContext', + utils.readExampleFile('./test/unit/examples/contextRequests/queryContext2.json') + ) + .reply( + 200, + utils.readExampleFile('./test/unit/examples/contextResponses/queryContext2UnknownError.json') + ); }); it('should return a ENTITY_GENERIC_ERROR', function(done) { @@ -229,5 +227,4 @@ describe('Query device information in the Context Broker', function() { }); }); }); - }); diff --git a/test/unit/ngsiService/staticAttributes-test.js b/test/unit/ngsiService/staticAttributes-test.js index f062905ef..55046e44c 100644 --- a/test/unit/ngsiService/staticAttributes-test.js +++ b/test/unit/ngsiService/staticAttributes-test.js @@ -20,69 +20,69 @@ * For those usages not covered by the GNU Affero General Public License * please contact with::[contacto@tid.es] */ -'use strict'; -var iotAgentLib = require('../../../lib/fiware-iotagent-lib'), - async = require('async'), - utils = require('../../tools/utils'), - should = require('should'), - logger = require('logops'), - nock = require('nock'), - contextBrokerMock, - iotAgentConfig = { - contextBroker: { - host: '192.168.1.1', - port: '1026' - }, - server: { - port: 4041 - }, - types: { - 'Light': { - commands: [], - type: 'Light', - lazy: [ - { - name: 'temperature', - type: 'centigrades' - } - ], - active: [ - { - name: 'pressure', - type: 'Hgmm' - } - ], - staticAttributes: [ - { - name: 'attr1', - type: 'type1' - }, - { - name: 'attr2', - type: 'type2' - }, - { - name: 'attr3', - type: 'type3' - }, - { - name: 'attr4', - type: 'type4' - }, - ] - } - }, - timestamp: true, - service: 'smartGondor', - subservice: 'gardens', - providerUrl: 'http://smartGondor.com', - deviceRegistrationDuration: 'P1M' - }; +/* eslint-disable no-unused-vars */ +const iotAgentLib = require('../../../lib/fiware-iotagent-lib'); +const async = require('async'); +const utils = require('../../tools/utils'); +const should = require('should'); +const logger = require('logops'); +const nock = require('nock'); +let contextBrokerMock; +const iotAgentConfig = { + contextBroker: { + host: '192.168.1.1', + port: '1026' + }, + server: { + port: 4041 + }, + types: { + Light: { + commands: [], + type: 'Light', + lazy: [ + { + name: 'temperature', + type: 'centigrades' + } + ], + active: [ + { + name: 'pressure', + type: 'Hgmm' + } + ], + staticAttributes: [ + { + name: 'attr1', + type: 'type1' + }, + { + name: 'attr2', + type: 'type2' + }, + { + name: 'attr3', + type: 'type3' + }, + { + name: 'attr4', + type: 'type4' + } + ] + } + }, + timestamp: true, + service: 'smartGondor', + subservice: 'gardens', + providerUrl: 'http://smartGondor.com', + deviceRegistrationDuration: 'P1M' +}; describe('Static attributes test', function() { - var values = [ + const values = [ { name: 'state', type: 'Boolean', @@ -112,36 +112,37 @@ describe('Static attributes test', function() { .matchHeader('fiware-servicepath', 'gardens') .post('/v1/updateContext') .times(4) - .reply(200, - utils.readExampleFile('./test/unit/examples/contextResponses/updateContext1Success.json')) + .reply(200, utils.readExampleFile('./test/unit/examples/contextResponses/updateContext1Success.json')) .post('/v1/updateContext', function(body) { - var metadatas = 0; + let metadatas = 0; - for (var i = 0; i < body.contextElements[0].attributes.length; i++) { + for (let i = 0; i < body.contextElements[0].attributes.length; i++) { if (body.contextElements[0].attributes[i].metadatas) { metadatas += body.contextElements[0].attributes[i].metadatas.length; } } return metadatas === body.contextElements[0].attributes.length - 1; }) - .reply(200, - utils.readExampleFile('./test/unit/examples/contextResponses/updateContext1Success.json')); + .reply(200, utils.readExampleFile('./test/unit/examples/contextResponses/updateContext1Success.json')); iotAgentLib.activate(iotAgentConfig, done); }); it('should send a single TimeInstant per attribute', function(done) { - async.series([ - async.apply(iotAgentLib.update, 'light1', 'Light', '', values), - async.apply(iotAgentLib.update, 'light1', 'Light', '', values), - async.apply(iotAgentLib.update, 'light1', 'Light', '', values), - async.apply(iotAgentLib.update, 'light1', 'Light', '', values), - async.apply(iotAgentLib.update, 'light1', 'Light', '', values) - ], function(error, results) { - should.not.exist(error); - contextBrokerMock.done(); - done(); - }); + async.series( + [ + async.apply(iotAgentLib.update, 'light1', 'Light', '', values), + async.apply(iotAgentLib.update, 'light1', 'Light', '', values), + async.apply(iotAgentLib.update, 'light1', 'Light', '', values), + async.apply(iotAgentLib.update, 'light1', 'Light', '', values), + async.apply(iotAgentLib.update, 'light1', 'Light', '', values) + ], + function(error, results) { + should.not.exist(error); + contextBrokerMock.done(); + done(); + } + ); }); }); }); diff --git a/test/unit/ngsiService/subscriptions-test.js b/test/unit/ngsiService/subscriptions-test.js index 8a73a5a1e..327a76fe1 100644 --- a/test/unit/ngsiService/subscriptions-test.js +++ b/test/unit/ngsiService/subscriptions-test.js @@ -20,33 +20,34 @@ * For those usages not covered by the GNU Affero General Public License * please contact with::[contacto@tid.es] */ -'use strict'; - -var iotAgentLib = require('../../../lib/fiware-iotagent-lib'), - utils = require('../../tools/utils'), - should = require('should'), - request = require('request'), - nock = require('nock'), - contextBrokerMock, - iotAgentConfig = { - logLevel: 'FATAL', - contextBroker: { - host: '192.168.1.1', - port: '1026' - }, - server: { - port: 4041 - }, - types: {}, - service: 'smartGondor', - subservice: 'gardens', - providerUrl: 'http://smartGondor.com', - deviceRegistrationDuration: 'P1M' - }; + +/* eslint-disable no-unused-vars */ + +const iotAgentLib = require('../../../lib/fiware-iotagent-lib'); +const utils = require('../../tools/utils'); +const should = require('should'); +const request = require('request'); +const nock = require('nock'); +let contextBrokerMock; +const iotAgentConfig = { + logLevel: 'FATAL', + contextBroker: { + host: '192.168.1.1', + port: '1026' + }, + server: { + port: 4041 + }, + types: {}, + service: 'smartGondor', + subservice: 'gardens', + providerUrl: 'http://smartGondor.com', + deviceRegistrationDuration: 'P1M' +}; describe('Subscription tests', function() { beforeEach(function(done) { - var optionsProvision = { + const optionsProvision = { url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices', method: 'POST', json: utils.readExampleFile('./test/unit/examples/deviceProvisioningRequests/provisionMinimumDevice.json'), @@ -62,18 +63,26 @@ describe('Subscription tests', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', '/gardens') - .post('/v1/updateContext', - utils.readExampleFile('./test/unit/examples/contextRequests/createMinimumProvisionedDevice.json')) - .reply(200, - utils.readExampleFile('./test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json')); + .post( + '/v1/updateContext', + utils.readExampleFile('./test/unit/examples/contextRequests/createMinimumProvisionedDevice.json') + ) + .reply( + 200, + utils.readExampleFile('./test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json') + ); contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', '/gardens') - .post('/v1/subscribeContext', - utils.readExampleFile('./test/unit/examples/subscriptionRequests/simpleSubscriptionRequest.json')) - .reply(200, - utils.readExampleFile('./test/unit/examples/subscriptionResponses/simpleSubscriptionSuccess.json')); + .post( + '/v1/subscribeContext', + utils.readExampleFile('./test/unit/examples/subscriptionRequests/simpleSubscriptionRequest.json') + ) + .reply( + 200, + utils.readExampleFile('./test/unit/examples/subscriptionResponses/simpleSubscriptionSuccess.json') + ); iotAgentLib.clearAll(function() { request(optionsProvision, function(error, result, body) { @@ -124,10 +133,14 @@ describe('Subscription tests', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', '/gardens') - .post('/v1/unsubscribeContext', - utils.readExampleFile('./test/unit/examples/subscriptionRequests/simpleSubscriptionRemove.json')) - .reply(200, - utils.readExampleFile('./test/unit/examples/subscriptionResponses/simpleSubscriptionSuccess.json')); + .post( + '/v1/unsubscribeContext', + utils.readExampleFile('./test/unit/examples/subscriptionRequests/simpleSubscriptionRemove.json') + ) + .reply( + 200, + utils.readExampleFile('./test/unit/examples/subscriptionResponses/simpleSubscriptionSuccess.json') + ); done(); }); @@ -164,10 +177,14 @@ describe('Subscription tests', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', '/gardens') - .post('/v1/unsubscribeContext', - utils.readExampleFile('./test/unit/examples/subscriptionRequests/simpleSubscriptionRemove.json')) - .reply(200, - utils.readExampleFile('./test/unit/examples/subscriptionResponses/simpleSubscriptionSuccess.json')); + .post( + '/v1/unsubscribeContext', + utils.readExampleFile('./test/unit/examples/subscriptionRequests/simpleSubscriptionRemove.json') + ) + .reply( + 200, + utils.readExampleFile('./test/unit/examples/subscriptionResponses/simpleSubscriptionSuccess.json') + ); done(); }); @@ -193,17 +210,16 @@ describe('Subscription tests', function() { }); it('should invoke the user defined callback', function(done) { - var notificationOptions = { - url: 'http://localhost:' + iotAgentConfig.server.port + '/notify', - method: 'POST', - json: utils.readExampleFile('./test/unit/examples/subscriptionRequests/simpleNotification.json'), - headers: { - 'fiware-service': 'smartGondor', - 'fiware-servicepath': '/gardens' - } - }, - - executedHandler = false; + const notificationOptions = { + url: 'http://localhost:' + iotAgentConfig.server.port + '/notify', + method: 'POST', + json: utils.readExampleFile('./test/unit/examples/subscriptionRequests/simpleNotification.json'), + headers: { + 'fiware-service': 'smartGondor', + 'fiware-servicepath': '/gardens' + } + }; + let executedHandler = false; function mockedHandler(device, notification, callback) { executedHandler = true; @@ -220,18 +236,18 @@ describe('Subscription tests', function() { }); }); it('should invoke all the notification middlewares before the user defined callback', function(done) { - var notificationOptions = { - url: 'http://localhost:' + iotAgentConfig.server.port + '/notify', - method: 'POST', - json: utils.readExampleFile('./test/unit/examples/subscriptionRequests/simpleNotification.json'), - headers: { - 'fiware-service': 'smartGondor', - 'fiware-servicepath': '/gardens' - } - }, - executedMiddlewares = false, - executedHandler = false, - modifiedData = false; + const notificationOptions = { + url: 'http://localhost:' + iotAgentConfig.server.port + '/notify', + method: 'POST', + json: utils.readExampleFile('./test/unit/examples/subscriptionRequests/simpleNotification.json'), + headers: { + 'fiware-service': 'smartGondor', + 'fiware-servicepath': '/gardens' + } + }; + let executedMiddlewares = false; + let executedHandler = false; + let modifiedData = false; function mockedHandler(device, notification, callback) { executedHandler = true; @@ -262,20 +278,26 @@ describe('Subscription tests', function() { }); }); it('should get the correspondent device information', function(done) { - var notificationOptions = { - url: 'http://localhost:' + iotAgentConfig.server.port + '/notify', - method: 'POST', - json: utils.readExampleFile('./test/unit/examples/subscriptionRequests/simpleNotification.json'), - headers: { - 'fiware-service': 'smartGondor', - 'fiware-servicepath': '/gardens' - } - }, - rightFields = false; + const notificationOptions = { + url: 'http://localhost:' + iotAgentConfig.server.port + '/notify', + method: 'POST', + json: utils.readExampleFile('./test/unit/examples/subscriptionRequests/simpleNotification.json'), + headers: { + 'fiware-service': 'smartGondor', + 'fiware-servicepath': '/gardens' + } + }; + let rightFields = false; function mockedHandler(device, data, callback) { - if (device && device.id === 'MicroLight1' && device.name === 'FirstMicroLight' && - data && data.length === 1 && data[0].name === 'attr_name') { + if ( + device && + device.id === 'MicroLight1' && + device.name === 'FirstMicroLight' && + data && + data.length === 1 && + data[0].name === 'attr_name' + ) { rightFields = true; } @@ -294,17 +316,16 @@ describe('Subscription tests', function() { }); describe('When a new notification arrives to the IOTA with a non-200 code', function() { it('should not call the handler', function(done) { - var notificationOptions = { - url: 'http://localhost:' + iotAgentConfig.server.port + '/notify', - method: 'POST', - json: utils.readExampleFile('./test/unit/examples/subscriptionRequests/errorNotification.json'), - headers: { - 'fiware-service': 'smartGondor', - 'fiware-servicepath': '/gardens' - } - }, - - executedHandler = false; + const notificationOptions = { + url: 'http://localhost:' + iotAgentConfig.server.port + '/notify', + method: 'POST', + json: utils.readExampleFile('./test/unit/examples/subscriptionRequests/errorNotification.json'), + headers: { + 'fiware-service': 'smartGondor', + 'fiware-servicepath': '/gardens' + } + }; + let executedHandler = false; function mockedHandler(device, notification, callback) { executedHandler = true; diff --git a/test/unit/ngsiv2/expressions/expressionBasedTransformations-test.js b/test/unit/ngsiv2/expressions/expressionBasedTransformations-test.js index 35144ac38..97ee81a4d 100644 --- a/test/unit/ngsiv2/expressions/expressionBasedTransformations-test.js +++ b/test/unit/ngsiv2/expressions/expressionBasedTransformations-test.js @@ -22,176 +22,174 @@ * * Modified by: Daniel Calvo - ATOS Research & Innovation */ -'use strict'; - -/* jshint camelcase: false */ - -var iotAgentLib = require('../../../../lib/fiware-iotagent-lib'), - utils = require('../../../tools/utils'), - should = require('should'), - logger = require('logops'), - nock = require('nock'), - contextBrokerMock, - iotAgentConfig = { - logLevel: 'FATAL', - contextBroker: { - host: '192.168.1.1', - port: '1026', - ngsiVersion: 'v2' + +/* eslint-disable no-useless-concat */ + +const iotAgentLib = require('../../../../lib/fiware-iotagent-lib'); +const utils = require('../../../tools/utils'); +const should = require('should'); +const logger = require('logops'); +const nock = require('nock'); +let contextBrokerMock; +const iotAgentConfig = { + logLevel: 'FATAL', + contextBroker: { + host: '192.168.1.1', + port: '1026', + ngsiVersion: 'v2' + }, + server: { + port: 4041 + }, + types: { + Light: { + commands: [], + type: 'Light', + lazy: [], + active: [ + { + object_id: 'p', + name: 'pressure', + type: 'Number' + }, + { + object_id: 'e', + name: 'consumption', + type: 'Number' + }, + { + object_id: 'a', + name: 'alive', + type: 'None' + }, + { + object_id: 'u', + name: 'updated', + type: 'Boolean' + }, + { + object_id: 'm', + name: 'manufacturer', + type: 'Object' + }, + { + object_id: 'r', + name: 'revisions', + type: 'Array' + }, + { + object_id: 'x', + name: 'consumption_x', + type: 'Number', + expression: '${@pressure * 20}' + } + ] }, - server: { - port: 4041 + LightError: { + commands: [], + type: 'Light', + lazy: [], + active: [ + { + object_id: 'p', + name: 'pressure', + type: 'Number', + expression: '${@pressure * / 20}' + } + ] }, - types: { - 'Light': { - commands: [], - type: 'Light', - lazy: [], - active: [ - { - object_id: 'p', - name: 'pressure', - type: 'Number' - }, - { - object_id: 'e', - name: 'consumption', - type: 'Number' - }, - { - object_id: 'a', - name: 'alive', - type: 'None', - }, - { - object_id: 'u', - name: 'updated', - type: 'Boolean', - }, - { - object_id: 'm', - name: 'manufacturer', - type: 'Object', - }, - { - object_id: 'r', - name: 'revisions', - type: 'Array', - }, - { - object_id: 'x', - name: 'consumption_x', - type: 'Number', - expression: '${@pressure * 20}' - } - ] - }, - 'LightError': { - commands: [], - type: 'Light', - lazy: [], - active: [ - { - object_id: 'p', - name: 'pressure', - type: 'Number', - expression: '${@pressure * / 20}' - } - ] - }, - 'WeatherStation': { - commands: [], - type: 'WeatherStation', - lazy: [], - active: [ - { - object_id: 'p', - name: 'pressure', - type: 'Number', - expression: '${@pressure * 20}' - }, - { - object_id: 'e', - name: 'consumption', - type: 'Number', - expression: '${@consumption * 20}' - }, - { - object_id: 'h', - name: 'humidity', - type: 'Percentage' - }, - { - name: 'weather', - type: 'Summary', - expression: 'Humidity ${@humidity / 2} and pressure ${@pressure * 20}' - }, - { - object_id: 'a', - name: 'alive', - type: 'None', - expression: '${@alive * 20}' - }, - { - object_id: 'u', - name: 'updated', - type: 'Boolean', - expression: '${@updated * 20}' - }, - ] - }, - 'WeatherStationMultiple': { - commands: [], - type: 'WeatherStation', - lazy: [], - active: [ - - { - object_id: 'p', - name: 'pressure', - type: 'Number', - expression: '${trim(@pressure)}' - }, - { - object_id: 'p25', - name: 'pressure25', - type: 'Number' - }, - { - object_id: 'e', - name: 'consumption', - type: 'Number', - expression: '${trim(@consumption)}' - }, - { - object_id: 'h', - name: 'humidity12', - type: 'Percentage' - }, - { - name: 'weather', - type: 'Summary', - expression: 'Humidity ${@humidity12 / 2} and pressure ${@pressure25 * 20}' - }, - { - object_id: 'a', - name: 'alive', - type: 'None', - expression: '${trim(@alive)}' - }, - { - object_id: 'u', - name: 'updated', - type: 'Boolean', - expression: '${trim(@updated)}' - }, - ] - } + WeatherStation: { + commands: [], + type: 'WeatherStation', + lazy: [], + active: [ + { + object_id: 'p', + name: 'pressure', + type: 'Number', + expression: '${@pressure * 20}' + }, + { + object_id: 'e', + name: 'consumption', + type: 'Number', + expression: '${@consumption * 20}' + }, + { + object_id: 'h', + name: 'humidity', + type: 'Percentage' + }, + { + name: 'weather', + type: 'Summary', + expression: 'Humidity ${@humidity / 2} and pressure ${@pressure * 20}' + }, + { + object_id: 'a', + name: 'alive', + type: 'None', + expression: '${@alive * 20}' + }, + { + object_id: 'u', + name: 'updated', + type: 'Boolean', + expression: '${@updated * 20}' + } + ] }, - service: 'smartGondor', - subservice: 'gardens', - providerUrl: 'http://smartGondor.com' - }; + WeatherStationMultiple: { + commands: [], + type: 'WeatherStation', + lazy: [], + active: [ + { + object_id: 'p', + name: 'pressure', + type: 'Number', + expression: '${trim(@pressure)}' + }, + { + object_id: 'p25', + name: 'pressure25', + type: 'Number' + }, + { + object_id: 'e', + name: 'consumption', + type: 'Number', + expression: '${trim(@consumption)}' + }, + { + object_id: 'h', + name: 'humidity12', + type: 'Percentage' + }, + { + name: 'weather', + type: 'Summary', + expression: 'Humidity ${@humidity12 / 2} and pressure ${@pressure25 * 20}' + }, + { + object_id: 'a', + name: 'alive', + type: 'None', + expression: '${trim(@alive)}' + }, + { + object_id: 'u', + name: 'updated', + type: 'Boolean', + expression: '${trim(@updated)}' + } + ] + } + }, + service: 'smartGondor', + subservice: 'gardens', + providerUrl: 'http://smartGondor.com' +}; describe('Expression-based transformations plugin', function() { beforeEach(function(done) { @@ -215,7 +213,7 @@ describe('Expression-based transformations plugin', function() { describe('When an update comes for expressions with syntax errors', function() { // Case: Update for an attribute with bad expression - var values = [ + const values = [ { name: 'p', type: 'centigrades', @@ -235,7 +233,7 @@ describe('Expression-based transformations plugin', function() { describe('When there are expression attributes that are just calculated (not sent by the device)', function() { // Case: Expression which results is sent as a new attribute - var values = [ + const values = [ { name: 'p', type: 'Number', @@ -254,9 +252,13 @@ describe('Expression-based transformations plugin', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v2/entities/ws1/attrs', utils.readExampleFile( - './test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin2.json')) - .query({type: 'WeatherStation'}) + .post( + '/v2/entities/ws1/attrs', + utils.readExampleFile( + './test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin2.json' + ) + ) + .query({ type: 'WeatherStation' }) .reply(204); }); @@ -272,7 +274,7 @@ describe('Expression-based transformations plugin', function() { describe('When an expression with multiple variables with numbers arrive', function() { // Case: Update for integer and string attributes with expression - var values = [ + const values = [ { name: 'p25', type: 'Number', @@ -291,9 +293,13 @@ describe('Expression-based transformations plugin', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v2/entities/ws1/attrs', utils.readExampleFile( - './test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin4.json')) - .query({type: 'WeatherStation'}) + .post( + '/v2/entities/ws1/attrs', + utils.readExampleFile( + './test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin4.json' + ) + ) + .query({ type: 'WeatherStation' }) .reply(204); }); @@ -308,7 +314,7 @@ describe('Expression-based transformations plugin', function() { describe('When an update comes for attributes without expressions and type integer', function() { // Case: Update for an integer attribute without expression - var values = [ + const values = [ { name: 'e', type: 'Number', @@ -322,9 +328,13 @@ describe('Expression-based transformations plugin', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v2/entities/light1/attrs', utils.readExampleFile( - './test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin11.json')) - .query({type: 'Light'}) + .post( + '/v2/entities/light1/attrs', + utils.readExampleFile( + './test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin11.json' + ) + ) + .query({ type: 'Light' }) .reply(204); }); @@ -339,7 +349,7 @@ describe('Expression-based transformations plugin', function() { describe('When an update comes for attributes with numeric expressions and type integer', function() { // Case: Update for an integer attribute with arithmetic expression - var values = [ + const values = [ { name: 'p', type: 'Number', @@ -353,9 +363,13 @@ describe('Expression-based transformations plugin', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v2/entities/ws1/attrs', utils.readExampleFile( - './test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin1.json')) - .query({type: 'WeatherStation'}) + .post( + '/v2/entities/ws1/attrs', + utils.readExampleFile( + './test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin1.json' + ) + ) + .query({ type: 'WeatherStation' }) .reply(204); }); @@ -370,7 +384,7 @@ describe('Expression-based transformations plugin', function() { describe('When an update comes for attributes with string expression and type integer', function() { // Case: Update for an integer attribute with string expression - var values = [ + const values = [ { name: 'e', type: 'Number', @@ -384,9 +398,13 @@ describe('Expression-based transformations plugin', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v2/entities/ws1/attrs', utils.readExampleFile( - './test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin11.json')) - .query({type: 'WeatherStation'}) + .post( + '/v2/entities/ws1/attrs', + utils.readExampleFile( + './test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin11.json' + ) + ) + .query({ type: 'WeatherStation' }) .reply(204); }); @@ -402,7 +420,7 @@ describe('Expression-based transformations plugin', function() { describe('When an update comes for attributes without expressions and type float', function() { // Case: Update for a Float attribute without expressions - var values = [ + const values = [ { name: 'e', type: 'Number', @@ -416,9 +434,13 @@ describe('Expression-based transformations plugin', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v2/entities/light1/attrs', utils.readExampleFile( - './test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin3.json')) - .query({type: 'Light'}) + .post( + '/v2/entities/light1/attrs', + utils.readExampleFile( + './test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin3.json' + ) + ) + .query({ type: 'Light' }) .reply(204); }); @@ -434,7 +456,7 @@ describe('Expression-based transformations plugin', function() { describe('When an update comes for attributes with numeric expressions and type float', function() { // Case: Update for a Float attribute with arithmetic expression - var values = [ + const values = [ { name: 'e', type: 'Number', @@ -448,9 +470,13 @@ describe('Expression-based transformations plugin', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v2/entities/ws1/attrs', utils.readExampleFile( - './test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin8.json')) - .query({type: 'WeatherStation'}) + .post( + '/v2/entities/ws1/attrs', + utils.readExampleFile( + './test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin8.json' + ) + ) + .query({ type: 'WeatherStation' }) .reply(204); }); @@ -466,7 +492,7 @@ describe('Expression-based transformations plugin', function() { describe('When an update comes for attributes with string expressions and type float', function() { // Case: Update for a Float attribute with string expression - var values = [ + const values = [ { name: 'e', type: 'Number', @@ -480,9 +506,13 @@ describe('Expression-based transformations plugin', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v2/entities/ws1/attrs', utils.readExampleFile( - './test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin3.json')) - .query({type: 'WeatherStation'}) + .post( + '/v2/entities/ws1/attrs', + utils.readExampleFile( + './test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin3.json' + ) + ) + .query({ type: 'WeatherStation' }) .reply(204); }); @@ -498,7 +528,7 @@ describe('Expression-based transformations plugin', function() { describe('When an update comes for attributes without expressions and NULL type', function() { // Case: Update for a Null attribute without expression - var values = [ + const values = [ { name: 'a', type: 'None', @@ -512,9 +542,13 @@ describe('Expression-based transformations plugin', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v2/entities/light1/attrs', utils.readExampleFile( - './test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin5.json')) - .query({type: 'Light'}) + .post( + '/v2/entities/light1/attrs', + utils.readExampleFile( + './test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin5.json' + ) + ) + .query({ type: 'Light' }) .reply(204); }); @@ -530,7 +564,7 @@ describe('Expression-based transformations plugin', function() { describe('When an update comes for attributes with numeric expressions and NULL type', function() { // Case: Update for a Null attribute with arithmetic expression - var values = [ + const values = [ { name: 'a', type: 'None', @@ -544,9 +578,13 @@ describe('Expression-based transformations plugin', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v2/entities/ws1/attrs', utils.readExampleFile( - './test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin5.json')) - .query({type: 'WeatherStation'}) + .post( + '/v2/entities/ws1/attrs', + utils.readExampleFile( + './test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin5.json' + ) + ) + .query({ type: 'WeatherStation' }) .reply(204); }); @@ -562,7 +600,7 @@ describe('Expression-based transformations plugin', function() { describe('When an update comes for attributes with string expressions and NULL type', function() { // Case: Update for a Null attribute with string expression - var values = [ + const values = [ { name: 'a', type: 'None', @@ -576,9 +614,13 @@ describe('Expression-based transformations plugin', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v2/entities/ws1/attrs', utils.readExampleFile( - './test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin5.json')) - .query({type: 'WeatherStation'}) + .post( + '/v2/entities/ws1/attrs', + utils.readExampleFile( + './test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin5.json' + ) + ) + .query({ type: 'WeatherStation' }) .reply(204); }); @@ -594,7 +636,7 @@ describe('Expression-based transformations plugin', function() { describe('When an update comes for attributes without expressions and Boolean type', function() { // Case: Update for a Boolean attribute without expression - var values = [ + const values = [ { name: 'u', type: 'Boolean', @@ -608,9 +650,13 @@ describe('Expression-based transformations plugin', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v2/entities/light1/attrs', utils.readExampleFile( - './test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin9.json')) - .query({type: 'Light'}) + .post( + '/v2/entities/light1/attrs', + utils.readExampleFile( + './test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin9.json' + ) + ) + .query({ type: 'Light' }) .reply(204); }); @@ -626,7 +672,7 @@ describe('Expression-based transformations plugin', function() { describe('When an update comes for attributes with numeric expressions and Boolean type', function() { // Case: Update for a Boolean attribute with arithmetic expression - var values = [ + const values = [ { name: 'u', type: 'Boolean', @@ -640,9 +686,13 @@ describe('Expression-based transformations plugin', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v2/entities/ws1/attrs', utils.readExampleFile( - './test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin10.json')) - .query({type: 'WeatherStation'}) + .post( + '/v2/entities/ws1/attrs', + utils.readExampleFile( + './test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin10.json' + ) + ) + .query({ type: 'WeatherStation' }) .reply(204); }); @@ -657,7 +707,7 @@ describe('Expression-based transformations plugin', function() { describe('When an update comes for attributes with string expressions and Boolean type', function() { // Case: Update for a Boolean attribute with string expression - var values = [ + const values = [ { name: 'u', type: 'Boolean', @@ -671,9 +721,13 @@ describe('Expression-based transformations plugin', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v2/entities/ws1/attrs', utils.readExampleFile( - './test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin9.json')) - .query({type: 'WeatherStation'}) + .post( + '/v2/entities/ws1/attrs', + utils.readExampleFile( + './test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin9.json' + ) + ) + .query({ type: 'WeatherStation' }) .reply(204); }); @@ -688,7 +742,7 @@ describe('Expression-based transformations plugin', function() { describe('When an update comes for attributes without expressions and Object type', function() { // Case: Update for a JSON document attribute without expression - var values = [ + const values = [ { name: 'm', type: 'Object', @@ -702,9 +756,13 @@ describe('Expression-based transformations plugin', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v2/entities/light1/attrs', utils.readExampleFile( - './test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin6.json')) - .query({type: 'Light'}) + .post( + '/v2/entities/light1/attrs', + utils.readExampleFile( + './test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin6.json' + ) + ) + .query({ type: 'Light' }) .reply(204); }); @@ -720,7 +778,7 @@ describe('Expression-based transformations plugin', function() { describe('When an update comes for attributes without expressions and Object type', function() { // Case: Update for a JSON array attribute without expression - var values = [ + const values = [ { name: 'r', type: 'Object', @@ -734,9 +792,13 @@ describe('Expression-based transformations plugin', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v2/entities/light1/attrs', utils.readExampleFile( - './test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin7.json')) - .query({type: 'Light'}) + .post( + '/v2/entities/light1/attrs', + utils.readExampleFile( + './test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin7.json' + ) + ) + .query({ type: 'Light' }) .reply(204); }); @@ -750,8 +812,7 @@ describe('Expression-based transformations plugin', function() { }); describe('When there are expressions including other attributes and they are not updated', function() { - - var values = [ + const values = [ { name: 'x', type: 'Number', @@ -765,9 +826,13 @@ describe('Expression-based transformations plugin', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v2/entities/light1/attrs', utils.readExampleFile( - './test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin12.json')) - .query({type: 'Light'}) + .post( + '/v2/entities/light1/attrs', + utils.readExampleFile( + './test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin12.json' + ) + ) + .query({ type: 'Light' }) .reply(204); }); @@ -781,8 +846,7 @@ describe('Expression-based transformations plugin', function() { }); describe('When there are expressions including other attributes and they are updated', function() { - - var values = [ + const values = [ { name: 'p', type: 'Number', @@ -796,9 +860,13 @@ describe('Expression-based transformations plugin', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v2/entities/light1/attrs', utils.readExampleFile( - './test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin13.json')) - .query({type: 'Light'}) + .post( + '/v2/entities/light1/attrs', + utils.readExampleFile( + './test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin13.json' + ) + ) + .query({ type: 'Light' }) .reply(204); }); @@ -811,10 +879,8 @@ describe('Expression-based transformations plugin', function() { }); }); - describe('When there are expressions including other attributes and they are updated' + - '(overriding situation)', function() { - - var values = [ + describe('When there are expressions including other attributes and they are updated (overriding situation)', function() { + const values = [ { name: 'x', type: 'Number', @@ -833,9 +899,13 @@ describe('Expression-based transformations plugin', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v2/entities/light1/attrs', utils.readExampleFile( - './test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin13.json')) - .query({type: 'Light'}) + .post( + '/v2/entities/light1/attrs', + utils.readExampleFile( + './test/unit/ngsiv2/examples/contextRequests/updateContextExpressionPlugin13.json' + ) + ) + .query({ type: 'Light' }) .reply(204); }); @@ -847,5 +917,4 @@ describe('Expression-based transformations plugin', function() { }); }); }); - }); diff --git a/test/unit/ngsiv2/general/contextBrokerOAuthSecurityAccess-test.js b/test/unit/ngsiv2/general/contextBrokerOAuthSecurityAccess-test.js index 17aa680d2..cb66ff206 100644 --- a/test/unit/ngsiv2/general/contextBrokerOAuthSecurityAccess-test.js +++ b/test/unit/ngsiv2/general/contextBrokerOAuthSecurityAccess-test.js @@ -22,75 +22,75 @@ * * Modified by: Daniel Calvo - ATOS Research & Innovation */ -'use strict'; - -var iotAgentLib = require('../../../../lib/fiware-iotagent-lib'), - utils = require('../../../tools/utils'), - should = require('should'), - logger = require('logops'), - nock = require('nock'), - request = require('request'), - timekeeper = require('timekeeper'), - contextBrokerMock, - oauth2Mock, - iotAgentConfig = { - contextBroker: { - host: '192.168.1.1', - port: '1026', - ngsiVersion: 'v2' - }, - server: { - port: 4041 - }, - authentication: { - type: 'oauth2', - url: 'http://192.168.1.1:3000', - header: 'Authorization', - clientId: 'context-broker', - clientSecret: 'c8d58d16-0a42-400e-9765-f32e154a5a9e', - tokenPath: '/auth/realms/default/protocol/openid-connect/token', - enabled: true - }, - types: { - 'Light': { - service: 'smartGondor', - subservice: 'electricity', - trust: 'eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJ3cHdWclJ3', - type: 'Light', - commands: [], - lazy: [ - { - name: 'temperature', - type: 'centigrades' - } - ], - active: [ - { - name: 'pressure', - type: 'Hgmm' - } - ] - }, - 'Termometer': { - commands: [], - type: 'Termometer', - lazy: [ - { - name: 'temp', - type: 'kelvin' - } - ], - active: [ - ] - } + +/* eslint-disable no-unused-vars */ + +const iotAgentLib = require('../../../../lib/fiware-iotagent-lib'); +const utils = require('../../../tools/utils'); +const should = require('should'); +const logger = require('logops'); +const nock = require('nock'); +const request = require('request'); +const timekeeper = require('timekeeper'); +let contextBrokerMock; +let oauth2Mock; +const iotAgentConfig = { + contextBroker: { + host: '192.168.1.1', + port: '1026', + ngsiVersion: 'v2' + }, + server: { + port: 4041 + }, + authentication: { + type: 'oauth2', + url: 'http://192.168.1.1:3000', + header: 'Authorization', + clientId: 'context-broker', + clientSecret: 'c8d58d16-0a42-400e-9765-f32e154a5a9e', + tokenPath: '/auth/realms/default/protocol/openid-connect/token', + enabled: true + }, + types: { + Light: { + service: 'smartGondor', + subservice: 'electricity', + trust: 'eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJ3cHdWclJ3', + type: 'Light', + commands: [], + lazy: [ + { + name: 'temperature', + type: 'centigrades' + } + ], + active: [ + { + name: 'pressure', + type: 'Hgmm' + } + ] }, - service: 'smartGondor', - subservice: 'gardens', - providerUrl: 'http://smartGondor.com' - }; + Termometer: { + commands: [], + type: 'Termometer', + lazy: [ + { + name: 'temp', + type: 'kelvin' + } + ], + active: [] + } + }, + service: 'smartGondor', + subservice: 'gardens', + providerUrl: 'http://smartGondor.com' +}; describe('Secured access to the Context Broker with OAuth2 provider', function() { - var values = [ + const values = [ { name: 'state', type: 'Boolean', @@ -117,20 +117,21 @@ describe('Secured access to the Context Broker with OAuth2 provider', function() nock.cleanAll(); oauth2Mock = nock('http://192.168.1.1:3000') - .post('/auth/realms/default/protocol/openid-connect/token', - utils.readExampleFile('./test/unit/examples/oauthRequests/getTokenFromTrust.json', true)) - .reply( - 201, - utils.readExampleFile('./test/unit/examples/oauthResponses/tokenFromTrust.json'), - {}); + .post( + '/auth/realms/default/protocol/openid-connect/token', + utils.readExampleFile('./test/unit/examples/oauthRequests/getTokenFromTrust.json', true) + ) + .reply(201, utils.readExampleFile('./test/unit/examples/oauthResponses/tokenFromTrust.json'), {}); contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'electricity') .matchHeader('Authorization', 'Bearer eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJ3cHdWclJ3') - .post('/v2/entities/light1/attrs', - utils.readExampleFile('./test/unit/ngsiv2/examples/contextRequests/updateContext1.json')) - .query({type: 'Light'}) + .post( + '/v2/entities/light1/attrs', + utils.readExampleFile('./test/unit/ngsiv2/examples/contextRequests/updateContext1.json') + ) + .query({ type: 'Light' }) .reply(204, {}); iotAgentLib.activate(iotAgentConfig, done); @@ -156,22 +157,22 @@ describe('Secured access to the Context Broker with OAuth2 provider', function() nock.cleanAll(); oauth2Mock = nock('http://192.168.1.1:3000') - .post('/auth/realms/default/protocol/openid-connect/token', - utils.readExampleFile('./test/unit/examples/oauthRequests/getTokenFromTrust.json', true)) - .reply( - 201, - utils.readExampleFile('./test/unit/examples/oauthResponses/tokenFromTrust.json'), - {}); + .post( + '/auth/realms/default/protocol/openid-connect/token', + utils.readExampleFile('./test/unit/examples/oauthRequests/getTokenFromTrust.json', true) + ) + .reply(201, utils.readExampleFile('./test/unit/examples/oauthResponses/tokenFromTrust.json'), {}); contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'electricity') .matchHeader('Authorization', 'Bearer eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJ3cHdWclJ3') - .post('/v2/entities/light1/attrs', - utils.readExampleFile('./test/unit/ngsiv2/examples/contextRequests/updateContext1.json')) - .query({type: 'Light'}) - .reply( - 403, {}); + .post( + '/v2/entities/light1/attrs', + utils.readExampleFile('./test/unit/ngsiv2/examples/contextRequests/updateContext1.json') + ) + .query({ type: 'Light' }) + .reply(403, {}); iotAgentLib.activate(iotAgentConfig, done); }); @@ -188,19 +189,24 @@ describe('Secured access to the Context Broker with OAuth2 provider', function() beforeEach(function(done) { nock.cleanAll(); - oauth2Mock = nock('http://192.168.1.1:3000') - .post('/auth/realms/default/protocol/openid-connect/token', - utils.readExampleFile('./test/unit/examples/oauthRequests/getTokenFromTrust.json', true)) + oauth2Mock = nock('http://192.168.1.1:3000') + .post( + '/auth/realms/default/protocol/openid-connect/token', + utils.readExampleFile('./test/unit/examples/oauthRequests/getTokenFromTrust.json', true) + ) .reply( - 400, - utils.readExampleFile('./test/unit/examples/oauthResponses/tokenFromTrustUnauthorized.json')); + 400, + utils.readExampleFile('./test/unit/examples/oauthResponses/tokenFromTrustUnauthorized.json') + ); contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'electricity') .matchHeader('Authorization', 'Bearer eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJ3cHdWclJ3') - .post('/v2/entities/light1/attrs', - utils.readExampleFile('./test/unit/ngsiv2/examples/contextRequests/updateContext1.json')) + .post( + '/v2/entities/light1/attrs', + utils.readExampleFile('./test/unit/ngsiv2/examples/contextRequests/updateContext1.json') + ) .reply(204, {}); iotAgentLib.activate(iotAgentConfig, done); @@ -216,29 +222,27 @@ describe('Secured access to the Context Broker with OAuth2 provider', function() }); describe('When the user requests information about a device in a protected CB', function() { - var attributes = [ - 'state', - 'dimming' - ]; + const attributes = ['state', 'dimming']; beforeEach(function(done) { nock.cleanAll(); oauth2Mock = nock('http://192.168.1.1:3000') - .post('/auth/realms/default/protocol/openid-connect/token', - utils.readExampleFile('./test/unit/examples/oauthRequests/getTokenFromTrust.json', true)) - .reply( - 201, - utils.readExampleFile('./test/unit/examples/oauthResponses/tokenFromTrust.json'), - {}); + .post( + '/auth/realms/default/protocol/openid-connect/token', + utils.readExampleFile('./test/unit/examples/oauthRequests/getTokenFromTrust.json', true) + ) + .reply(201, utils.readExampleFile('./test/unit/examples/oauthResponses/tokenFromTrust.json'), {}); contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'electricity') .matchHeader('Authorization', 'Bearer eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJ3cHdWclJ3') .get('/v2/entities/light1/attrs?attrs=state,dimming&type=Light') - .reply(200, - utils.readExampleFile('./test/unit/ngsiv2/examples/contextResponses/queryContext1Success.json')); + .reply( + 200, + utils.readExampleFile('./test/unit/ngsiv2/examples/contextResponses/queryContext1Success.json') + ); iotAgentLib.activate(iotAgentConfig, done); }); @@ -252,51 +256,60 @@ describe('Secured access to the Context Broker with OAuth2 provider', function() }); }); describe('When subscriptions are used on a protected Context Broker', function() { - beforeEach(function(done) { - var optionsProvision = { + beforeEach(function(done) { + const optionsProvision = { url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices', method: 'POST', json: utils.readExampleFile( - './test/unit/examples/deviceProvisioningRequests/provisionMinimumDevice3.json'), + './test/unit/examples/deviceProvisioningRequests/provisionMinimumDevice3.json' + ), headers: { 'fiware-service': 'smartGondor', 'fiware-servicepath': 'electricity' } }; - + nock.cleanAll(); - + iotAgentLib.activate(iotAgentConfig, function() { oauth2Mock = nock('http://192.168.1.1:3000') - .post('/auth/realms/default/protocol/openid-connect/token', - utils.readExampleFile('./test/unit/examples/oauthRequests/getTokenFromTrust.json', true)) + .post( + '/auth/realms/default/protocol/openid-connect/token', + utils.readExampleFile('./test/unit/examples/oauthRequests/getTokenFromTrust.json', true) + ) .times(3) - .reply( - 201, - utils.readExampleFile('./test/unit/examples/oauthResponses/tokenFromTrust.json'), - {}); - + .reply(201, utils.readExampleFile('./test/unit/examples/oauthResponses/tokenFromTrust.json'), {}); contextBrokerMock = nock('http://192.168.1.1:1026'); contextBrokerMock - .post('/v2/registrations', utils.readExampleFile( - './test/unit/ngsiv2/examples/contextAvailabilityRequests/registerProvisionedDeviceWithGroup3.json')) - .reply(201, null, {'Location': '/v2/registrations/6319a7f5254b05844116584d'}); + .post( + '/v2/registrations', + utils.readExampleFile( + './test/unit/ngsiv2/examples/contextAvailabilityRequests/registerProvisionedDeviceWithGroup3.json' + ) + ) + .reply(201, null, { Location: '/v2/registrations/6319a7f5254b05844116584d' }); contextBrokerMock - .post('/v2/entities?options=upsert', utils.readExampleFile( - './test/unit/ngsiv2/examples/contextRequests/createProvisionedDeviceWithGroupAndStatic3.json')) - .reply(204, {}); + .post( + '/v2/entities?options=upsert', + utils.readExampleFile( + './test/unit/ngsiv2/examples/contextRequests/createProvisionedDeviceWithGroupAndStatic3.json' + ) + ) + .reply(204, {}); contextBrokerMock - .post('/v2/subscriptions', - utils.readExampleFile('./test/unit/ngsiv2/examples' + - '/subscriptionRequests/simpleSubscriptionRequest2.json')) + .post( + '/v2/subscriptions', + utils.readExampleFile( + './test/unit/ngsiv2/examples/subscriptionRequests/simpleSubscriptionRequest2.json' + ) + ) .matchHeader('Authorization', 'Bearer eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJ3cHdWclJ3') - .reply(201, null, {'Location': '/v2/subscriptions/51c0ac9ed714fb3b37d7d5a8'}); + .reply(201, null, { Location: '/v2/subscriptions/51c0ac9ed714fb3b37d7d5a8' }); - iotAgentLib.clearAll(function() { request(optionsProvision, function(error, result, body) { done(); @@ -318,18 +331,14 @@ describe('Secured access to the Context Broker with OAuth2 provider', function() }); it('unsubscribe requests use auth header', function(done) { + oauth2Mock + .post( + '/auth/realms/default/protocol/openid-connect/token', + utils.readExampleFile('./test/unit/examples/oauthRequests/getTokenFromTrust.json', true) + ) + .reply(201, utils.readExampleFile('./test/unit/examples/oauthResponses/tokenFromTrust.json'), {}); - oauth2Mock - .post('/auth/realms/default/protocol/openid-connect/token', - utils.readExampleFile('./test/unit/examples/oauthRequests/getTokenFromTrust.json', true)) - .reply( - 201, - utils.readExampleFile('./test/unit/examples/oauthResponses/tokenFromTrust.json'), - {}); - - contextBrokerMock - .delete('/v2/subscriptions/51c0ac9ed714fb3b37d7d5a8') - .reply(204); + contextBrokerMock.delete('/v2/subscriptions/51c0ac9ed714fb3b37d7d5a8').reply(204); iotAgentLib.getDevice('Light1', 'smartGondor', 'electricity', function(error, device) { iotAgentLib.subscribe(device, ['dimming'], null, function(error) { @@ -340,13 +349,11 @@ describe('Secured access to the Context Broker with OAuth2 provider', function() }); }); }); - }); }); describe('Secured access to the Context Broker with OAuth2 provider (FIWARE Keyrock IDM)', function() { - - var values = [ + const values = [ { name: 'state', type: 'Boolean', @@ -373,20 +380,25 @@ describe('Secured access to the Context Broker with OAuth2 provider (FIWARE Keyr nock.cleanAll(); oauth2Mock = nock('http://192.168.1.1:3000') - .post('/oauth2/token', - utils.readExampleFile('./test/unit/examples/oauthRequests/getTokenFromTrust.json', true)) + .post( + '/oauth2/token', + utils.readExampleFile('./test/unit/examples/oauthRequests/getTokenFromTrust.json', true) + ) .reply( 200, utils.readExampleFile('./test/unit/examples/oauthResponses/tokenFromTrustKeyrock.json'), - {}); + {} + ); contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'electricity') .matchHeader('Authorization', 'Bearer c1b752e377680acd1349a3ed59db855a1db07605') - .post('/v2/entities/light1/attrs', - utils.readExampleFile('./test/unit/ngsiv2/examples/contextRequests/updateContext1.json')) - .query({type: 'Light'}) + .post( + '/v2/entities/light1/attrs', + utils.readExampleFile('./test/unit/ngsiv2/examples/contextRequests/updateContext1.json') + ) + .query({ type: 'Light' }) .reply(204, {}); iotAgentConfig.authentication.tokenPath = '/oauth2/token'; @@ -410,29 +422,31 @@ describe('Secured access to the Context Broker with OAuth2 provider (FIWARE Keyr }); describe('When the user requests information about a device in a protected CB', function() { - var attributes = [ - 'state', - 'dimming' - ]; + const attributes = ['state', 'dimming']; beforeEach(function(done) { nock.cleanAll(); oauth2Mock = nock('http://192.168.1.1:3000') - .post('/oauth2/token', - utils.readExampleFile('./test/unit/examples/oauthRequests/getTokenFromTrust.json', true)) + .post( + '/oauth2/token', + utils.readExampleFile('./test/unit/examples/oauthRequests/getTokenFromTrust.json', true) + ) .reply( 200, utils.readExampleFile('./test/unit/examples/oauthResponses/tokenFromTrustKeyrock.json'), - {}); + {} + ); contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'electricity') .matchHeader('Authorization', 'Bearer c1b752e377680acd1349a3ed59db855a1db07605') .get('/v2/entities/light1/attrs?attrs=state,dimming&type=Light') - .reply(200, - utils.readExampleFile('./test/unit/ngsiv2/examples/contextResponses/queryContext1Success.json')); + .reply( + 200, + utils.readExampleFile('./test/unit/ngsiv2/examples/contextResponses/queryContext1Success.json') + ); iotAgentLib.activate(iotAgentConfig, done); }); @@ -451,11 +465,14 @@ describe('Secured access to the Context Broker with OAuth2 provider (FIWARE Keyr nock.cleanAll(); oauth2Mock = nock('http://192.168.1.1:3000') - .post('/oauth2/token', - utils.readExampleFile('./test/unit/examples/oauthRequests/getTokenFromTrust.json', true)) + .post( + '/oauth2/token', + utils.readExampleFile('./test/unit/examples/oauthRequests/getTokenFromTrust.json', true) + ) .reply( - 400, - utils.readExampleFile('./test/unit/examples/oauthResponses/tokenFromTrustUnauthorizedKeyrock.json')); + 400, + utils.readExampleFile('./test/unit/examples/oauthResponses/tokenFromTrustUnauthorizedKeyrock.json') + ); iotAgentLib.activate(iotAgentConfig, done); }); @@ -474,12 +491,17 @@ describe('Secured access to the Context Broker with OAuth2 provider (FIWARE Keyr nock.cleanAll(); oauth2Mock = nock('http://192.168.1.1:3000') - .post('/oauth2/token', - utils.readExampleFile('./test/unit/examples/oauthRequests/getTokenFromTrust.json', true)) + .post( + '/oauth2/token', + utils.readExampleFile('./test/unit/examples/oauthRequests/getTokenFromTrust.json', true) + ) .reply( - 400, - utils.readExampleFile('./test/unit/examples/oauthResponses/' + - 'tokenFromTrustInvalidCredentialsKeyrock.json'), {}); + 400, + utils.readExampleFile( + './test/unit/examples/oauthResponses/tokenFromTrustInvalidCredentialsKeyrock.json' + ), + {} + ); iotAgentLib.activate(iotAgentConfig, done); }); @@ -498,20 +520,25 @@ describe('Secured access to the Context Broker with OAuth2 provider (FIWARE Keyr nock.cleanAll(); oauth2Mock = nock('http://192.168.1.1:3000') - .post('/oauth2/token', - utils.readExampleFile('./test/unit/examples/oauthRequests/getTokenFromTrust.json', true)) + .post( + '/oauth2/token', + utils.readExampleFile('./test/unit/examples/oauthRequests/getTokenFromTrust.json', true) + ) .reply( 200, utils.readExampleFile('./test/unit/examples/oauthResponses/tokenFromTrustKeyrock.json'), - {}); + {} + ); contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'electricity') .matchHeader('Authorization', 'Bearer c1b752e377680acd1349a3ed59db855a1db07605') - .post('/v2/entities/light1/attrs', - utils.readExampleFile('./test/unit/ngsiv2/examples/contextRequests/updateContext1.json')) - .query({type: 'Light'}) + .post( + '/v2/entities/light1/attrs', + utils.readExampleFile('./test/unit/ngsiv2/examples/contextRequests/updateContext1.json') + ) + .query({ type: 'Light' }) .reply(401, 'Auth-token not found in request header'); iotAgentLib.activate(iotAgentConfig, done); @@ -527,271 +554,327 @@ describe('Secured access to the Context Broker with OAuth2 provider (FIWARE Keyr }); }); -describe('Secured access to the Context Broker with OAuth2 provider (FIWARE Keyrock IDM)' + - 'configured through group provisioning', function() { - var groupCreation = { - url: 'http://localhost:4041/iot/services', - method: 'POST', - json: utils.readExampleFile('./test/unit/examples/groupProvisioningRequests/provisionFullGroup.json'), - headers: { - 'fiware-service': 'TestService', - 'fiware-servicepath': '/testingPath' - } - }; - - var values = [ - { - name: 'status', - type: 'String', - value: 'STARTING' - } - ]; +describe( + 'Secured access to the Context Broker with OAuth2 provider (FIWARE Keyrock IDM)' + + 'configured through group provisioning', + function() { + const groupCreation = { + url: 'http://localhost:4041/iot/services', + method: 'POST', + json: utils.readExampleFile('./test/unit/examples/groupProvisioningRequests/provisionFullGroup.json'), + headers: { + 'fiware-service': 'TestService', + 'fiware-servicepath': '/testingPath' + } + }; - beforeEach(function() { - logger.setLevel('FATAL'); - }); + const values = [ + { + name: 'status', + type: 'String', + value: 'STARTING' + } + ]; - afterEach(function(done) { - iotAgentLib.deactivate(done); - nock.cleanAll(); - }); + beforeEach(function() { + logger.setLevel('FATAL'); + }); - describe('When a measure is sent to the Context Broker via an Update Context operation', function() { - var oauth2Mock2; - var contextBrokerMock2; - beforeEach(function(done) { + afterEach(function(done) { + iotAgentLib.deactivate(done); nock.cleanAll(); - oauth2Mock = nock('http://192.168.1.1:3000') - .post('/oauth2/token', - utils.readExampleFile('./test/unit/examples/oauthRequests/getTokenFromTrustKeyrockGroup.json', true)) - .reply( - 200, - utils.readExampleFile('./test/unit/examples/oauthResponses/tokenFromTrustKeyrock.json'), - {}); + }); - oauth2Mock2 = nock('http://192.168.1.1:3000') - .post('/oauth2/token', - utils.readExampleFile('./test/unit/examples/oauthRequests/getTokenFromTrustKeyrockGroup2.json', true)) - .reply( - 200, - utils.readExampleFile('./test/unit/examples/oauthResponses/tokenFromTrustKeyrock2.json'), - {}); + describe('When a measure is sent to the Context Broker via an Update Context operation', function() { + let oauth2Mock2; + let contextBrokerMock2; + beforeEach(function(done) { + nock.cleanAll(); + oauth2Mock = nock('http://192.168.1.1:3000') + .post( + '/oauth2/token', + utils.readExampleFile( + './test/unit/examples/oauthRequests/getTokenFromTrustKeyrockGroup.json', + true + ) + ) + .reply( + 200, + utils.readExampleFile('./test/unit/examples/oauthResponses/tokenFromTrustKeyrock.json'), + {} + ); + + oauth2Mock2 = nock('http://192.168.1.1:3000') + .post( + '/oauth2/token', + utils.readExampleFile( + './test/unit/examples/oauthRequests/getTokenFromTrustKeyrockGroup2.json', + true + ) + ) + .reply( + 200, + utils.readExampleFile('./test/unit/examples/oauthResponses/tokenFromTrustKeyrock2.json'), + {} + ); + + contextBrokerMock = nock('http://unexistentHost:1026') + .matchHeader('fiware-service', 'TestService') + .matchHeader('fiware-servicepath', '/testingPath') + .matchHeader('Authorization', 'Bearer c1b752e377680acd1349a3ed59db855a1db07605') + .post( + '/v2/entities/machine1/attrs', + utils.readExampleFile( + './test/unit/ngsiv2/examples/contextRequests/updateContext3WithStatic.json' + ) + ) + .query({ type: 'SensorMachine' }) + .reply(204, {}); + + contextBrokerMock2 = nock('http://unexistentHost:1026') + .matchHeader('fiware-service', 'TestService') + .matchHeader('fiware-servicepath', '/testingPath') + .matchHeader('Authorization', 'Bearer bbb752e377680acd1349a3ed59db855a1db076aa') + .post( + '/v2/entities/machine1/attrs', + utils.readExampleFile( + './test/unit/ngsiv2/examples/contextRequests/updateContext3WithStatic.json' + ) + ) + .query({ type: 'SensorMachine' }) + .reply(204, {}); + + iotAgentConfig.authentication.tokenPath = '/oauth2/token'; + iotAgentLib.activate(iotAgentConfig, function() { + request(groupCreation, function(error, response, body) { + done(); + }); + }); + }); + it( + 'should ask OAuth2 provider for a token based on the' + + 'trust token and send the generated token in the auth header', + function(done) { + iotAgentLib.update('machine1', 'SensorMachine', '', values, function(error) { + should.not.exist(error); + oauth2Mock.done(); + contextBrokerMock.done(); + done(); + }); + } + ); - contextBrokerMock = nock('http://unexistentHost:1026') - .matchHeader('fiware-service', 'TestService') - .matchHeader('fiware-servicepath', '/testingPath') - .matchHeader('Authorization', 'Bearer c1b752e377680acd1349a3ed59db855a1db07605') - .post('/v2/entities/machine1/attrs', - utils.readExampleFile('./test/unit/ngsiv2/examples/contextRequests/updateContext3WithStatic.json')) - .query({type: 'SensorMachine'}) - .reply(204, {}); + it('should use the updated trust token in the following requests', function(done) { + iotAgentLib.update('machine1', 'SensorMachine', '', values, function(error) { + should.not.exist(error); + oauth2Mock2.done(); + contextBrokerMock2.done(); + done(); + }); + }); + }); - contextBrokerMock2 = nock('http://unexistentHost:1026') - .matchHeader('fiware-service', 'TestService') - .matchHeader('fiware-servicepath', '/testingPath') - .matchHeader('Authorization', 'Bearer bbb752e377680acd1349a3ed59db855a1db076aa') - .post('/v2/entities/machine1/attrs', - utils.readExampleFile('./test/unit/ngsiv2/examples/contextRequests/updateContext3WithStatic.json')) - .query({type: 'SensorMachine'}) - .reply(204, {}); + describe('When a device is provisioned for a configuration contains an OAuth2 trust token', function() { + const values = [ + { + name: 'status', + type: 'String', + value: 'STARTING' + } + ]; + const deviceCreation = { + url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices', + method: 'POST', + json: utils.readExampleFile('./test/unit/examples/deviceProvisioningRequests/provisionNewDevice2.json'), + headers: { + 'fiware-service': 'TestService', + 'fiware-servicepath': '/testingPath' + } + }; + let contextBrokerMock2; + let contextBrokerMock3; + beforeEach(function(done) { + const time = new Date(1438760101468); // 2015-08-05T07:35:01.468+00:00 + timekeeper.freeze(time); + nock.cleanAll(); - iotAgentConfig.authentication.tokenPath = '/oauth2/token'; - iotAgentLib.activate(iotAgentConfig, function() { - request(groupCreation, function(error, response, body) { + oauth2Mock = nock('http://192.168.1.1:3000') + .post( + '/oauth2/token', + utils.readExampleFile( + './test/unit/examples/oauthRequests/getTokenFromTrustKeyrockGroup3.json', + true + ) + ) + .reply( + 200, + utils.readExampleFile('./test/unit/examples/oauthResponses/tokenFromTrustKeyrock3.json'), + {} + ) + .post( + '/oauth2/token', + utils.readExampleFile( + './test/unit/examples/oauthRequests/getTokenFromTrustKeyrockGroup4.json', + true + ) + ) + .reply( + 200, + utils.readExampleFile('./test/unit/examples/oauthResponses/tokenFromTrustKeyrock4.json'), + {} + ) + .post( + '/oauth2/token', + utils.readExampleFile( + './test/unit/examples/oauthRequests/getTokenFromTrustKeyrockGroup5.json', + true + ) + ) + .reply( + 200, + utils.readExampleFile('./test/unit/examples/oauthResponses/tokenFromTrustKeyrock5.json'), + {} + ); + + contextBrokerMock = nock('http://unexistenthost:1026') + .matchHeader('fiware-service', 'TestService') + .matchHeader('fiware-servicepath', '/testingPath') + .matchHeader('Authorization', 'Bearer asd752e377680acd1349a3ed59db855a1db07ere') + .post( + '/v2/registrations', + utils.readExampleFile( + './test/unit/ngsiv2/examples/contextAvailabilityRequests/registerProvisionedDeviceWithGroup2.json' + ) + ) + .reply(201, null, { Location: '/v2/registrations/6319a7f5254b05844116584d' }); + + contextBrokerMock2 = nock('http://unexistenthost:1026') + .matchHeader('fiware-service', 'TestService') + .matchHeader('fiware-servicepath', '/testingPath') + .matchHeader('authorization', 'Bearer bea752e377680acd1349a3ed59db855a1db07zxc') + .post( + '/v2/entities?options=upsert', + utils.readExampleFile( + './test/unit/ngsiv2/examples/contextRequests/createProvisionedDeviceWithGroupAndStatic2.json' + ) + ) + .reply(204, {}); + + contextBrokerMock3 = nock('http://unexistentHost:1026') + .matchHeader('fiware-service', 'TestService') + .matchHeader('fiware-servicepath', '/testingPath') + .matchHeader('authorization', 'Bearer zzz752e377680acd1349a3ed59db855a1db07bbb') + .post( + '/v2/entities/Light1/attrs', + utils.readExampleFile('./test/unit/ngsiv2/examples/contextRequests/updateContext4.json') + ) + .query({ type: 'SensorMachine' }) + .reply(204, {}); + + iotAgentConfig.authentication.tokenPath = '/oauth2/token'; + iotAgentLib.activate(iotAgentConfig, function() { done(); }); }); - }); - it('should ask OAuth2 provider for a token based on the' + - 'trust token and send the generated token in the auth header', function(done) { - iotAgentLib.update('machine1', 'SensorMachine', '', values, function(error) { - should.not.exist(error); - oauth2Mock.done(); - contextBrokerMock.done(); + + afterEach(function(done) { + timekeeper.reset(); + done(); }); - }); - it('should use the updated trust token in the following requests', function(done) { - iotAgentLib.update('machine1', 'SensorMachine', '', values, function(error) { - should.not.exist(error); - oauth2Mock2.done(); - contextBrokerMock2.done(); - done(); + it('should not raise any error', function(done) { + request(deviceCreation, function(error, response, body) { + should.not.exist(error); + response.statusCode.should.equal(201); + contextBrokerMock.done(); + contextBrokerMock2.done(); + done(); + }); }); - }); - }); + it('should send the mixed data to the Context Broker', function(done) { + iotAgentLib.update('Light1', 'SensorMachine', '', values, function(error) { + should.not.exist(error); + contextBrokerMock3.done(); + done(); + }); + }); + }); + } +); - describe('When a device is provisioned for a configuration contains an OAuth2 trust token', function() { - var values = [ - { - name: 'status', - type: 'String', - value: 'STARTING' - } - ]; - var deviceCreation = { - url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices', +describe( + 'Secured access to the Context Broker with OAuth2 provider (FIWARE Keyrock IDM)' + + 'configured through group provisioning. Permanent token', + function() { + const groupCreation = { + url: 'http://localhost:4041/iot/services', method: 'POST', - json: utils.readExampleFile('./test/unit/examples/deviceProvisioningRequests/provisionNewDevice2.json'), + json: utils.readExampleFile('./test/unit/examples/groupProvisioningRequests/provisionFullGroup.json'), headers: { 'fiware-service': 'TestService', 'fiware-servicepath': '/testingPath' } }; - var contextBrokerMock2; - var contextBrokerMock3; - beforeEach(function(done) { - var time = new Date(1438760101468); // 2015-08-05T07:35:01.468+00:00 - timekeeper.freeze(time); - nock.cleanAll(); - - oauth2Mock = nock('http://192.168.1.1:3000') - .post('/oauth2/token', - utils.readExampleFile('./test/unit/examples/oauthRequests/getTokenFromTrustKeyrockGroup3.json', true)) - .reply( - 200, - utils.readExampleFile('./test/unit/examples/oauthResponses/tokenFromTrustKeyrock3.json'), - {}) - .post('/oauth2/token', - utils.readExampleFile('./test/unit/examples/oauthRequests/getTokenFromTrustKeyrockGroup4.json', true)) - .reply( - 200, - utils.readExampleFile('./test/unit/examples/oauthResponses/tokenFromTrustKeyrock4.json'), - {}) - .post('/oauth2/token', - utils.readExampleFile('./test/unit/examples/oauthRequests/getTokenFromTrustKeyrockGroup5.json', true)) - .reply( - 200, - utils.readExampleFile('./test/unit/examples/oauthResponses/tokenFromTrustKeyrock5.json'), - {}); - - - contextBrokerMock = nock('http://unexistenthost:1026') - .matchHeader('fiware-service', 'TestService') - .matchHeader('fiware-servicepath', '/testingPath') - .matchHeader('Authorization', 'Bearer asd752e377680acd1349a3ed59db855a1db07ere') - .post('/v2/registrations', utils.readExampleFile( - './test/unit/ngsiv2/examples/contextAvailabilityRequests/registerProvisionedDeviceWithGroup2.json')) - .reply(201, null, {'Location': '/v2/registrations/6319a7f5254b05844116584d'}); - - contextBrokerMock2 = nock('http://unexistenthost:1026') - .matchHeader('fiware-service', 'TestService') - .matchHeader('fiware-servicepath', '/testingPath') - .matchHeader('authorization', 'Bearer bea752e377680acd1349a3ed59db855a1db07zxc') - .post('/v2/entities?options=upsert', utils.readExampleFile( - './test/unit/ngsiv2/examples/contextRequests/createProvisionedDeviceWithGroupAndStatic2.json')) - .reply(204, {}); - - contextBrokerMock3 = nock('http://unexistentHost:1026') - .matchHeader('fiware-service', 'TestService') - .matchHeader('fiware-servicepath', '/testingPath') - .matchHeader('authorization', 'Bearer zzz752e377680acd1349a3ed59db855a1db07bbb') - .post('/v2/entities/Light1/attrs', utils.readExampleFile( - './test/unit/ngsiv2/examples/contextRequests/updateContext4.json')) - .query({type: 'SensorMachine'}) - .reply(204, {}); + const values = [ + { + name: 'status', + type: 'String', + value: 'STARTING' + } + ]; - iotAgentConfig.authentication.tokenPath = '/oauth2/token'; - iotAgentLib.activate(iotAgentConfig, function() { - done(); - }); + beforeEach(function() { + logger.setLevel('FATAL'); + iotAgentConfig.authentication.permanentToken = true; }); afterEach(function(done) { - timekeeper.reset(); - - done(); - }); - - it('should not raise any error', function(done) { - request(deviceCreation, function(error, response, body) { - should.not.exist(error); - response.statusCode.should.equal(201); - contextBrokerMock.done(); - contextBrokerMock2.done(); - done(); - }); + iotAgentLib.deactivate(done); + nock.cleanAll(); }); - it('should send the mixed data to the Context Broker', function(done) { - iotAgentLib.update('Light1', 'SensorMachine', '', values, function(error) { - should.not.exist(error); - contextBrokerMock3.done(); - done(); + describe('When a measure is sent to the Context Broker via an Update Context operation', function() { + beforeEach(function(done) { + nock.cleanAll(); + + contextBrokerMock = nock('http://unexistentHost:1026') + .matchHeader('fiware-service', 'TestService') + .matchHeader('fiware-servicepath', '/testingPath') + .matchHeader('Authorization', 'Bearer 999210dacf913772606c95dd0b895d5506cbc988') + .post( + '/v2/entities/machine1/attrs', + utils.readExampleFile( + './test/unit/ngsiv2/examples/contextRequests/updateContext3WithStatic.json' + ) + ) + .query({ type: 'SensorMachine' }) + .reply(204, {}); + + iotAgentConfig.authentication.tokenPath = '/oauth2/token'; + iotAgentLib.activate(iotAgentConfig, function() { + request(groupCreation, function(error, response, body) { + done(); + }); + }); }); - }); - - }); -}); - -describe('Secured access to the Context Broker with OAuth2 provider (FIWARE Keyrock IDM)' + - 'configured through group provisioning. Permanent token', function() { - var groupCreation = { - url: 'http://localhost:4041/iot/services', - method: 'POST', - json: utils.readExampleFile('./test/unit/examples/groupProvisioningRequests/provisionFullGroup.json'), - headers: { - 'fiware-service': 'TestService', - 'fiware-servicepath': '/testingPath' - } - }; - - var values = [ - { - name: 'status', - type: 'String', - value: 'STARTING' - } - ]; - - beforeEach(function() { - logger.setLevel('FATAL'); - iotAgentConfig.authentication.permanentToken = true; - }); - - afterEach(function(done) { - iotAgentLib.deactivate(done); - nock.cleanAll(); - }); - - describe('When a measure is sent to the Context Broker via an Update Context operation', function() { - beforeEach(function(done) { - nock.cleanAll(); - - contextBrokerMock = nock('http://unexistentHost:1026') - .matchHeader('fiware-service', 'TestService') - .matchHeader('fiware-servicepath', '/testingPath') - .matchHeader('Authorization', 'Bearer 999210dacf913772606c95dd0b895d5506cbc988') - .post('/v2/entities/machine1/attrs', - utils.readExampleFile('./test/unit/ngsiv2/examples/contextRequests/updateContext3WithStatic.json')) - .query({type: 'SensorMachine'}) - .reply(204, {}); - - - iotAgentConfig.authentication.tokenPath = '/oauth2/token'; - iotAgentLib.activate(iotAgentConfig, function() { - request(groupCreation, function(error, response, body) { + it('should send the permanent token in the auth header', function(done) { + iotAgentLib.update('machine1', 'SensorMachine', '', values, function(error) { + should.not.exist(error); + contextBrokerMock.done(); done(); }); }); - }); - it('should send the permanent token in the auth header', function(done) { - iotAgentLib.update('machine1', 'SensorMachine', '', values, function(error) { - should.not.exist(error); - contextBrokerMock.done(); - done(); - }); - }); - it('should use the permanent trust token in the following requests', function(done) { - iotAgentLib.update('machine1', 'SensorMachine', '', values, function(error) { - should.not.exist(error); - contextBrokerMock.done(); - done(); + it('should use the permanent trust token in the following requests', function(done) { + iotAgentLib.update('machine1', 'SensorMachine', '', values, function(error) { + should.not.exist(error); + contextBrokerMock.done(); + done(); + }); }); }); - }); -}); + } +); diff --git a/test/unit/ngsiv2/general/deviceService-test.js b/test/unit/ngsiv2/general/deviceService-test.js index 280e5e2a3..eb3b1ef6f 100644 --- a/test/unit/ngsiv2/general/deviceService-test.js +++ b/test/unit/ngsiv2/general/deviceService-test.js @@ -22,154 +22,150 @@ * * Modified by: Daniel Calvo - ATOS Research & Innovation */ -'use strict'; -/* jshint camelcase: false */ +/* eslint-disable no-unused-vars */ -var iotAgentLib = require('../../../../lib/fiware-iotagent-lib'), - utils = require('../../../tools/utils'), - should = require('should'), - nock = require('nock'), - request = require('request'), - logger = require('logops'), - async = require('async'), - iotAgentConfig = { - contextBroker: { - host: '192.168.1.1', - port: '1026', - ngsiVersion: 'v2' - }, - server: { - port: 4041 +const iotAgentLib = require('../../../../lib/fiware-iotagent-lib'); +const utils = require('../../../tools/utils'); +const should = require('should'); +const nock = require('nock'); +const request = require('request'); +const logger = require('logops'); +const async = require('async'); +const iotAgentConfig = { + contextBroker: { + host: '192.168.1.1', + port: '1026', + ngsiVersion: 'v2' + }, + server: { + port: 4041 + }, + types: { + Light: { + commands: [], + type: 'Light', + lazy: [ + { + name: 'temperature', + type: 'centigrades' + } + ], + active: [ + { + name: 'pressure', + type: 'Hgmm' + } + ] }, - types: { - 'Light': { - commands: [], - type: 'Light', - lazy: [ - { - name: 'temperature', - type: 'centigrades' - } - ], - active: [ - { - name: 'pressure', - type: 'Hgmm' - } - ] - }, - 'BrokenLight': { - commands: [], - lazy: [ - { - name: 'temperature', - type: 'centigrades' - } - ], - active: [ - { - name: 'pressure', - type: 'Hgmm' - } - ] - }, - 'Termometer': { - type: 'Termometer', - commands: [], - lazy: [ - { - name: 'temp', - type: 'kelvin' - } - ], - active: [ - ] - }, - 'Humidity': { - type: 'Humidity', - cbHost: 'http://192.168.1.1:3024', - commands: [], - lazy: [], - active: [ - { - name: 'humidity', - type: 'percentage' - } - ] - }, - 'Motion': { - type: 'Motion', - commands: [], - lazy: [], - staticAttributes: [ - { - 'name': 'location', - 'type': 'Vector', - 'value': '(123,523)' - } - ], - active: [ - { - name: 'humidity', - type: 'percentage' - } - ] - } + BrokenLight: { + commands: [], + lazy: [ + { + name: 'temperature', + type: 'centigrades' + } + ], + active: [ + { + name: 'pressure', + type: 'Hgmm' + } + ] }, - iotManager: { - host: 'localhost', - port: 8082, - path: '/protocols', - protocol: 'MQTT_UL', - description: 'MQTT Ultralight 2.0 IoT Agent (Node.js version)' + Termometer: { + type: 'Termometer', + commands: [], + lazy: [ + { + name: 'temp', + type: 'kelvin' + } + ], + active: [] }, - service: 'smartGondor', - subservice: 'gardens', - providerUrl: 'http://smartGondor.com' - }, - groupCreation = { - url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/services', - method: 'POST', - json: { - services: [ + Humidity: { + type: 'Humidity', + cbHost: 'http://192.168.1.1:3024', + commands: [], + lazy: [], + active: [ { - resource: '', - apikey: '801230BJKL23Y9090DSFL123HJK09H324HV8732', - entity_type: 'TheLightType', - trust: '8970A9078A803H3BL98PINEQRW8342HBAMS', - cbHost: 'http://unexistentHost:1026', - commands: [], - lazy: [], - attributes: [ - { - name: 'status', - type: 'Boolean' - } - ], - static_attributes: [] + name: 'humidity', + type: 'percentage' } ] }, - headers: { - 'fiware-service': 'TestService', - 'fiware-servicepath': '/testingPath' + Motion: { + type: 'Motion', + commands: [], + lazy: [], + staticAttributes: [ + { + name: 'location', + type: 'Vector', + value: '(123,523)' + } + ], + active: [ + { + name: 'humidity', + type: 'percentage' + } + ] } }, - deviceCreation = { - url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices', - method: 'POST', - json: utils.readExampleFile('./test/unit/examples/deviceProvisioningRequests/provisionNewDevice.json'), - headers: { - 'fiware-service': 'TestService', - 'fiware-servicepath': '/testingPath' - } + iotManager: { + host: 'localhost', + port: 8082, + path: '/protocols', + protocol: 'MQTT_UL', + description: 'MQTT Ultralight 2.0 IoT Agent (Node.js version)' }, - contextBrokerMock, - iotamMock; - + service: 'smartGondor', + subservice: 'gardens', + providerUrl: 'http://smartGondor.com' +}; +const groupCreation = { + url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/services', + method: 'POST', + json: { + services: [ + { + resource: '', + apikey: '801230BJKL23Y9090DSFL123HJK09H324HV8732', + entity_type: 'TheLightType', + trust: '8970A9078A803H3BL98PINEQRW8342HBAMS', + cbHost: 'http://unexistentHost:1026', + commands: [], + lazy: [], + attributes: [ + { + name: 'status', + type: 'Boolean' + } + ], + static_attributes: [] + } + ] + }, + headers: { + 'fiware-service': 'TestService', + 'fiware-servicepath': '/testingPath' + } +}; +const deviceCreation = { + url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices', + method: 'POST', + json: utils.readExampleFile('./test/unit/examples/deviceProvisioningRequests/provisionNewDevice.json'), + headers: { + 'fiware-service': 'TestService', + 'fiware-servicepath': '/testingPath' + } +}; +let contextBrokerMock; +let iotamMock; -/* jshint camelcase: false */ describe('Device Service: utils', function() { beforeEach(function(done) { nock.cleanAll(); @@ -183,15 +179,11 @@ describe('Device Service: utils', function() { afterEach(function(done) { nock.cleanAll(); - async.series([ - iotAgentLib.clearAll, - iotAgentLib.deactivate - ], done); + async.series([iotAgentLib.clearAll, iotAgentLib.deactivate], done); }); describe('When an existing device tries to be retrieved with retrieveOrCreate()', function() { beforeEach(function(done) { - // This mock does not check the payload since the aim of the test is not to verify // device provisioning functionality. Appropriate verification is done in tests under // provisioning folder @@ -201,10 +193,10 @@ describe('Device Service: utils', function() { .post('/v2/entities?options=upsert') .reply(204); - async.series([ - request.bind(request, groupCreation), - request.bind(request, deviceCreation) - ], function(error, results) { + async.series([request.bind(request, groupCreation), request.bind(request, deviceCreation)], function( + error, + results + ) { done(); }); }); @@ -222,7 +214,6 @@ describe('Device Service: utils', function() { describe('When an unexisting device tries to be retrieved for an existing APIKey', function() { beforeEach(function(done) { - // This mock does not check the payload since the aim of the test is not to verify // device provisioning functionality. Appropriate verification is done in tests under // provisioning folder @@ -232,36 +223,38 @@ describe('Device Service: utils', function() { .post('/v2/entities?options=upsert') .reply(204); - async.series([ - request.bind(request, groupCreation) - ], function(error, results) { + async.series([request.bind(request, groupCreation)], function(error, results) { done(); }); }); it('should register the device and return it', function(done) { - iotAgentLib.retrieveDevice('UNEXISTENT_DEV', '801230BJKL23Y9090DSFL123HJK09H324HV8732', - function(error, device) { - should.not.exist(error); - should.exist(device); + iotAgentLib.retrieveDevice('UNEXISTENT_DEV', '801230BJKL23Y9090DSFL123HJK09H324HV8732', function( + error, + device + ) { + should.not.exist(error); + should.exist(device); - device.id.should.equal('UNEXISTENT_DEV'); - should.exist(device.protocol); - device.protocol.should.equal('MQTT_UL'); - done(); - }); + device.id.should.equal('UNEXISTENT_DEV'); + should.exist(device.protocol); + device.protocol.should.equal('MQTT_UL'); + done(); + }); }); }); describe('When an unexisting device tries to be retrieved for an unexisting APIKey', function() { it('should raise an error', function(done) { - iotAgentLib.retrieveDevice('UNEXISTENT_DEV_AND_GROUP', 'H2332Y909DSF3H346yh20JK092', - function(error, device) { - should.exist(error); - error.name.should.equal('DEVICE_GROUP_NOT_FOUND'); - should.not.exist(device); - done(); - }); + iotAgentLib.retrieveDevice('UNEXISTENT_DEV_AND_GROUP', 'H2332Y909DSF3H346yh20JK092', function( + error, + device + ) { + should.exist(error); + error.name.should.equal('DEVICE_GROUP_NOT_FOUND'); + should.not.exist(device); + done(); + }); }); }); }); diff --git a/test/unit/ngsiv2/general/https-support-test.js b/test/unit/ngsiv2/general/https-support-test.js index bee7b8bbe..92000265a 100644 --- a/test/unit/ngsiv2/general/https-support-test.js +++ b/test/unit/ngsiv2/general/https-support-test.js @@ -23,116 +23,113 @@ * Modified by: Federico M. Facca - Martel Innovate * Modified by: Daniel Calvo - ATOS Research & Innovation */ -'use strict'; -/* jshint camelcase: false */ +/* eslint-disable no-unused-vars */ -var iotAgentLib = require('../../../../lib/fiware-iotagent-lib'), - request = require('request'), - nock = require('nock'), - utils = require('../../../tools/utils'), - groupRegistryMemory = require('../../../../lib/services/groups/groupRegistryMemory'), - should = require('should'), - iotAgentConfig = { - logLevel: 'FATAL', - contextBroker: { - url: 'https://192.168.1.1:1026', - ngsiVersion: 'v2' - }, - server: { - port: 4041 - }, - types: { - 'Light': { - commands: [], - lazy: [ - { - name: 'temperature', - type: 'centigrades' - } - ], - active: [ - { - name: 'pressure', - type: 'Hgmm' - } - ], - service: 'smartGondor', - subservice: 'gardens' - }, - 'Termometer': { - commands: [], - lazy: [ - { - name: 'temp', - type: 'kelvin' - } - ], - active: [ - ], - service: 'smartGondor', - subservice: 'gardens' - } - }, - service: 'smartGondor', - subservice: 'gardens', - providerUrl: 'http://smartGondor.com', - iotManager: { - url: 'https://mockediotam.com:9876', - path: '/protocols', - protocol: 'GENERIC_PROTOCOL', - description: 'A generic protocol', - agentPath: '/iot' - }, - defaultResource: '/iot/d' +const iotAgentLib = require('../../../../lib/fiware-iotagent-lib'); +const request = require('request'); +const nock = require('nock'); +const utils = require('../../../tools/utils'); +const groupRegistryMemory = require('../../../../lib/services/groups/groupRegistryMemory'); +const should = require('should'); +const iotAgentConfig = { + logLevel: 'FATAL', + contextBroker: { + url: 'https://192.168.1.1:1026', + ngsiVersion: 'v2' + }, + server: { + port: 4041 }, - groupCreation = { - service: 'theService', - subservice: 'theSubService', - resource: '/deviceTest', - apikey: '801230BJKL23Y9090DSFL123HJK09H324HV8732', - type: 'SensorMachine', - trust: '8970A9078A803H3BL98PINEQRW8342HBAMS', - commands: [ - { - name: 'wheel1', - type: 'Wheel' - } - ], - lazy: [ - { - name: 'luminescence', - type: 'Lumens' - } - ], - attributes: [ - { - name: 'status', - type: 'Boolean' - } - ] + types: { + Light: { + commands: [], + lazy: [ + { + name: 'temperature', + type: 'centigrades' + } + ], + active: [ + { + name: 'pressure', + type: 'Hgmm' + } + ], + service: 'smartGondor', + subservice: 'gardens' + }, + Termometer: { + commands: [], + lazy: [ + { + name: 'temp', + type: 'kelvin' + } + ], + active: [], + service: 'smartGondor', + subservice: 'gardens' + } }, - device1 = { - id: 'light1', - type: 'Light', - service: 'smartGondor', - subservice: 'gardens' + service: 'smartGondor', + subservice: 'gardens', + providerUrl: 'http://smartGondor.com', + iotManager: { + url: 'https://mockediotam.com:9876', + path: '/protocols', + protocol: 'GENERIC_PROTOCOL', + description: 'A generic protocol', + agentPath: '/iot' }, - contextBrokerMock, - iotamMock; - + defaultResource: '/iot/d' +}; +const groupCreation = { + service: 'theService', + subservice: 'theSubService', + resource: '/deviceTest', + apikey: '801230BJKL23Y9090DSFL123HJK09H324HV8732', + type: 'SensorMachine', + trust: '8970A9078A803H3BL98PINEQRW8342HBAMS', + commands: [ + { + name: 'wheel1', + type: 'Wheel' + } + ], + lazy: [ + { + name: 'luminescence', + type: 'Lumens' + } + ], + attributes: [ + { + name: 'status', + type: 'Boolean' + } + ] +}; +const device1 = { + id: 'light1', + type: 'Light', + service: 'smartGondor', + subservice: 'gardens' +}; +let contextBrokerMock; +let iotamMock; describe('HTTPS support tests IOTAM', function() { - describe('When the IoT Agents is started with https "iotManager" config', function() { beforeEach(function(done) { nock.cleanAll(); iotamMock = nock('https://mockediotam.com:9876') - .post('/protocols', - utils.readExampleFile('./test/unit/examples/iotamRequests/registrationWithGroupsWithoutCB.json')) - .reply(200, - utils.readExampleFile('./test/unit/examples/iotamResponses/registrationSuccess.json')); + .post( + '/protocols', + utils.readExampleFile('./test/unit/examples/iotamRequests/registrationWithGroupsWithoutCB.json') + ) + .reply(200, utils.readExampleFile('./test/unit/examples/iotamResponses/registrationSuccess.json')); groupRegistryMemory.create(groupCreation, done); }); @@ -155,14 +152,14 @@ describe('HTTPS support tests IOTAM', function() { }); describe('HTTPS support tests', function() { - describe('When subscription is sent to HTTPS context broker', function() { beforeEach(function(done) { - var optionsProvision = { + const optionsProvision = { url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices', method: 'POST', json: utils.readExampleFile( - './test/unit/examples/deviceProvisioningRequests/provisionMinimumDevice.json'), + './test/unit/examples/deviceProvisioningRequests/provisionMinimumDevice.json' + ), headers: { 'fiware-service': 'smartGondor', 'fiware-servicepath': '/gardens' @@ -175,18 +172,24 @@ describe('HTTPS support tests', function() { contextBrokerMock = nock('https://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', '/gardens') - .post('/v2/entities?options=upsert', - utils.readExampleFile('./test/unit/ngsiv2/examples/' + - 'contextRequests/createMinimumProvisionedDevice.json')) + .post( + '/v2/entities?options=upsert', + utils.readExampleFile( + './test/unit/ngsiv2/examples/contextRequests/createMinimumProvisionedDevice.json' + ) + ) .reply(204); contextBrokerMock = nock('https://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', '/gardens') - .post('/v2/subscriptions', utils.readExampleFile('./test/unit/ngsiv2/examples' + - '/subscriptionRequests/simpleSubscriptionRequest.json')) - .reply(201, null, {'Location': '/v2/subscriptions/51c0ac9ed714fb3b37d7d5a8'}); - + .post( + '/v2/subscriptions', + utils.readExampleFile( + './test/unit/ngsiv2/examples/subscriptionRequests/simpleSubscriptionRequest.json' + ) + ) + .reply(201, null, { Location: '/v2/subscriptions/51c0ac9ed714fb3b37d7d5a8' }); iotAgentLib.clearAll(function() { request(optionsProvision, function(error, result, body) { @@ -230,14 +233,14 @@ describe('HTTPS support tests', function() { .post('/v2/entities?options=upsert') .reply(204); - var nockBody = utils.readExampleFile( - './test/unit/ngsiv2/examples/contextAvailabilityRequests/registerIoTAgent1.json'); + const nockBody = utils.readExampleFile( + './test/unit/ngsiv2/examples/contextAvailabilityRequests/registerIoTAgent1.json' + ); contextBrokerMock .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') .post('/v2/registrations', nockBody) - .reply(201, null, {'Location': '/v2/registrations/6319a7f5254b05844116584d'}); - + .reply(201, null, { Location: '/v2/registrations/6319a7f5254b05844116584d' }); iotAgentLib.activate(iotAgentConfig, function(error) { iotAgentLib.clearAll(done); @@ -246,9 +249,9 @@ describe('HTTPS support tests', function() { it('should register as ContextProvider using HTTPS', function(done) { iotAgentLib.register(device1, function(error) { - should.not.exist(error); - contextBrokerMock.done(); - done(); + should.not.exist(error); + contextBrokerMock.done(); + done(); }); }); diff --git a/test/unit/ngsiv2/general/iotam-autoregistration-test.js b/test/unit/ngsiv2/general/iotam-autoregistration-test.js index d5b23782e..44aa86f11 100644 --- a/test/unit/ngsiv2/general/iotam-autoregistration-test.js +++ b/test/unit/ngsiv2/general/iotam-autoregistration-test.js @@ -20,171 +20,170 @@ * For those usages not covered by the GNU Affero General Public License * please contact with::[contacto@tid.es] */ -'use strict'; - -/* jshint camelcase: false */ - -var iotAgentLib = require('../../../../lib/fiware-iotagent-lib'), - request = require('request'), - nock = require('nock'), - utils = require('../../../tools/utils'), - groupRegistryMemory = require('../../../../lib/services/groups/groupRegistryMemory'), - should = require('should'), - iotAgentConfig = { - logLevel: 'FATAL', - contextBroker: { - host: '192.168.1.1', - port: '1026', - ngsiVersion: 'v2' - }, - server: { - port: 4041 - }, - types: { - 'Light': { - commands: [], - type: 'Light', + +/* eslint-disable no-unused-vars */ + +const iotAgentLib = require('../../../../lib/fiware-iotagent-lib'); +const request = require('request'); +const nock = require('nock'); +const utils = require('../../../tools/utils'); +const groupRegistryMemory = require('../../../../lib/services/groups/groupRegistryMemory'); +const should = require('should'); +const iotAgentConfig = { + logLevel: 'FATAL', + contextBroker: { + host: '192.168.1.1', + port: '1026', + ngsiVersion: 'v2' + }, + server: { + port: 4041 + }, + types: { + Light: { + commands: [], + type: 'Light', + lazy: [ + { + name: 'temperature', + type: 'centigrades' + } + ], + attributes: [ + { + name: 'pressure', + type: 'Hgmm' + } + ] + } + }, + providerUrl: 'http://smartGondor.com', + iotManager: { + host: 'mockediotam.com', + port: 9876, + path: '/protocols', + protocol: 'GENERIC_PROTOCOL', + description: 'A generic protocol', + agentPath: '/iot' + }, + defaultResource: '/iot/d' +}; +const groupCreation = { + service: 'theService', + subservice: 'theSubService', + resource: '/deviceTest', + apikey: '801230BJKL23Y9090DSFL123HJK09H324HV8732', + type: 'SensorMachine', + trust: '8970A9078A803H3BL98PINEQRW8342HBAMS', + cbHost: 'http://unexistentHost:1026', + commands: [ + { + name: 'wheel1', + type: 'Wheel' + } + ], + lazy: [ + { + name: 'luminescence', + type: 'Lumens' + } + ], + attributes: [ + { + name: 'status', + type: 'Boolean' + } + ] +}; +const optionsCreation = { + url: 'http://localhost:4041/iot/services', + method: 'POST', + json: { + services: [ + { + resource: '/deviceTest', + apikey: '801230BJKL23Y9090DSFL123HJK09H324HV8732', + entity_type: 'SensorMachine', + trust: '8970A9078A803H3BL98PINEQRW8342HBAMS', + cbHost: 'http://unexistentHost:1026', + commands: [ + { + name: 'wheel1', + type: 'Wheel' + } + ], lazy: [ { - name: 'temperature', - type: 'centigrades' + name: 'luminescence', + type: 'Lumens' } ], attributes: [ { - name: 'pressure', - type: 'Hgmm' + name: 'status', + type: 'Boolean' } ] } - }, - providerUrl: 'http://smartGondor.com', - iotManager: { - host: 'mockediotam.com', - port: 9876, - path: '/protocols', - protocol: 'GENERIC_PROTOCOL', - description: 'A generic protocol', - agentPath: '/iot' - }, - defaultResource: '/iot/d' + ] }, - groupCreation = { - service: 'theService', - subservice: 'theSubService', - resource: '/deviceTest', - apikey: '801230BJKL23Y9090DSFL123HJK09H324HV8732', - type: 'SensorMachine', - trust: '8970A9078A803H3BL98PINEQRW8342HBAMS', - cbHost: 'http://unexistentHost:1026', - commands: [ - { - name: 'wheel1', - type: 'Wheel' - } - ], - lazy: [ - { - name: 'luminescence', - type: 'Lumens' - } - ], - attributes: [ + headers: { + 'fiware-service': 'theService', + 'fiware-servicepath': 'theSubService' + } +}; +const optionsCreationStatic = { + url: 'http://localhost:4041/iot/services', + method: 'POST', + json: { + services: [ { - name: 'status', - type: 'Boolean' + resource: '/deviceTest', + apikey: '801230BJKL23Y9090DSFL123HJK09H324HV8732', + entity_type: 'SensorMachine', + trust: '8970A9078A803H3BL98PINEQRW8342HBAMS', + cbHost: 'http://unexistentHost:1026', + commands: [ + { + name: 'wheel1', + type: 'Wheel' + } + ], + static_attributes: [ + { + name: 'position', + type: 'location', + values: '123,12' + } + ], + attributes: [ + { + name: 'status', + type: 'Boolean' + } + ] } ] }, - optionsCreation = { - url: 'http://localhost:4041/iot/services', - method: 'POST', - json: { - services: [ - { - resource: '/deviceTest', - apikey: '801230BJKL23Y9090DSFL123HJK09H324HV8732', - entity_type: 'SensorMachine', - trust: '8970A9078A803H3BL98PINEQRW8342HBAMS', - cbHost: 'http://unexistentHost:1026', - commands: [ - { - name: 'wheel1', - type: 'Wheel' - } - ], - lazy: [ - { - name: 'luminescence', - type: 'Lumens' - } - ], - attributes: [ - { - name: 'status', - type: 'Boolean' - } - ] - } - ] - }, - headers: { - 'fiware-service': 'theService', - 'fiware-servicepath': 'theSubService' - } + headers: { + 'fiware-service': 'theService', + 'fiware-servicepath': 'theSubService' + } +}; +const optionsDelete = { + url: 'http://localhost:4041/iot/services', + method: 'DELETE', + json: {}, + headers: { + 'fiware-service': 'theService', + 'fiware-servicepath': 'theSubService' }, - optionsCreationStatic = { - url: 'http://localhost:4041/iot/services', - method: 'POST', - json: { - services: [ - { - resource: '/deviceTest', - apikey: '801230BJKL23Y9090DSFL123HJK09H324HV8732', - entity_type: 'SensorMachine', - trust: '8970A9078A803H3BL98PINEQRW8342HBAMS', - cbHost: 'http://unexistentHost:1026', - commands: [ - { - name: 'wheel1', - type: 'Wheel' - } - ], - static_attributes: [ - { - name: 'position', - type: 'location', - values: '123,12' - } - ], - attributes: [ - { - name: 'status', - type: 'Boolean' - } - ] - } - ] - }, - headers: { - 'fiware-service': 'theService', - 'fiware-servicepath': 'theSubService' - } - }, - optionsDelete = { - url: 'http://localhost:4041/iot/services', - method: 'DELETE', - json: {}, - headers: { - 'fiware-service': 'theService', - 'fiware-servicepath': 'theSubService' - }, - qs: { - resource: '/deviceTest', - apikey: '801230BJKL23Y9090DSFL123HJK09H324HV8732' - } - }, - iotamMock; + qs: { + resource: '/deviceTest', + apikey: '801230BJKL23Y9090DSFL123HJK09H324HV8732' + } +}; +let iotamMock; describe('IoT Manager autoregistration', function() { describe('When the IoT Agent is started without a "iotManager" config parameter and empty services', function() { @@ -192,10 +191,8 @@ describe('IoT Manager autoregistration', function() { nock.cleanAll(); iotamMock = nock('http://mockediotam.com:9876') - .post('/protocols', - utils.readExampleFile('./test/unit/examples/iotamRequests/registrationEmpty.json')) - .reply(200, - utils.readExampleFile('./test/unit/examples/iotamResponses/registrationSuccess.json')); + .post('/protocols', utils.readExampleFile('./test/unit/examples/iotamRequests/registrationEmpty.json')) + .reply(200, utils.readExampleFile('./test/unit/examples/iotamResponses/registrationSuccess.json')); }); afterEach(function(done) { @@ -218,10 +215,8 @@ describe('IoT Manager autoregistration', function() { delete iotAgentConfig.providerUrl; iotamMock = nock('http://mockediotam.com:9876') - .post('/protocols', - utils.readExampleFile('./test/unit/examples/iotamRequests/registrationEmpty.json')) - .reply(200, - utils.readExampleFile('./test/unit/examples/iotamResponses/registrationSuccess.json')); + .post('/protocols', utils.readExampleFile('./test/unit/examples/iotamRequests/registrationEmpty.json')) + .reply(200, utils.readExampleFile('./test/unit/examples/iotamResponses/registrationSuccess.json')); }); afterEach(function() { @@ -242,10 +237,11 @@ describe('IoT Manager autoregistration', function() { nock.cleanAll(); iotamMock = nock('http://mockediotam.com:9876') - .post('/protocols', - utils.readExampleFile('./test/unit/examples/iotamRequests/registrationWithGroups.json')) - .reply(200, - utils.readExampleFile('./test/unit/examples/iotamResponses/registrationSuccess.json')); + .post( + '/protocols', + utils.readExampleFile('./test/unit/examples/iotamRequests/registrationWithGroups.json') + ) + .reply(200, utils.readExampleFile('./test/unit/examples/iotamResponses/registrationSuccess.json')); groupRegistryMemory.create(groupCreation, done); }); @@ -270,16 +266,15 @@ describe('IoT Manager autoregistration', function() { nock.cleanAll(); iotamMock = nock('http://mockediotam.com:9876') - .post('/protocols', - utils.readExampleFile('./test/unit/examples/iotamRequests/registrationEmpty.json')) - .reply(200, - utils.readExampleFile('./test/unit/examples/iotamResponses/registrationSuccess.json')); + .post('/protocols', utils.readExampleFile('./test/unit/examples/iotamRequests/registrationEmpty.json')) + .reply(200, utils.readExampleFile('./test/unit/examples/iotamResponses/registrationSuccess.json')); iotamMock - .post('/protocols', - utils.readExampleFile('./test/unit/examples/iotamRequests/registrationWithGroups.json')) - .reply(200, - utils.readExampleFile('./test/unit/examples/iotamResponses/registrationSuccess.json')); + .post( + '/protocols', + utils.readExampleFile('./test/unit/examples/iotamRequests/registrationWithGroups.json') + ) + .reply(200, utils.readExampleFile('./test/unit/examples/iotamResponses/registrationSuccess.json')); iotAgentLib.activate(iotAgentConfig, function(error) { done(); @@ -306,16 +301,15 @@ describe('IoT Manager autoregistration', function() { nock.cleanAll(); iotamMock = nock('http://mockediotam.com:9876') - .post('/protocols', - utils.readExampleFile('./test/unit/examples/iotamRequests/registrationWithGroups.json')) - .reply(200, - utils.readExampleFile('./test/unit/examples/iotamResponses/registrationSuccess.json')); + .post( + '/protocols', + utils.readExampleFile('./test/unit/examples/iotamRequests/registrationWithGroups.json') + ) + .reply(200, utils.readExampleFile('./test/unit/examples/iotamResponses/registrationSuccess.json')); iotamMock - .post('/protocols', - utils.readExampleFile('./test/unit/examples/iotamRequests/registrationEmpty.json')) - .reply(200, - utils.readExampleFile('./test/unit/examples/iotamResponses/registrationSuccess.json')); + .post('/protocols', utils.readExampleFile('./test/unit/examples/iotamRequests/registrationEmpty.json')) + .reply(200, utils.readExampleFile('./test/unit/examples/iotamResponses/registrationSuccess.json')); groupRegistryMemory.create(groupCreation, function() { iotAgentLib.activate(iotAgentConfig, done); @@ -342,16 +336,15 @@ describe('IoT Manager autoregistration', function() { nock.cleanAll(); iotamMock = nock('http://mockediotam.com:9876') - .post('/protocols', - utils.readExampleFile('./test/unit/examples/iotamRequests/registrationEmpty.json')) - .reply(200, - utils.readExampleFile('./test/unit/examples/iotamResponses/registrationSuccess.json')); + .post('/protocols', utils.readExampleFile('./test/unit/examples/iotamRequests/registrationEmpty.json')) + .reply(200, utils.readExampleFile('./test/unit/examples/iotamResponses/registrationSuccess.json')); iotamMock - .post('/protocols', - utils.readExampleFile('./test/unit/examples/iotamRequests/registrationWithStaticGroups.json')) - .reply(200, - utils.readExampleFile('./test/unit/examples/iotamResponses/registrationSuccess.json')); + .post( + '/protocols', + utils.readExampleFile('./test/unit/examples/iotamRequests/registrationWithStaticGroups.json') + ) + .reply(200, utils.readExampleFile('./test/unit/examples/iotamResponses/registrationSuccess.json')); iotAgentLib.activate(iotAgentConfig, function(error) { done(); diff --git a/test/unit/ngsiv2/general/startup-test.js b/test/unit/ngsiv2/general/startup-test.js index 4f25eca1b..7d52f1f83 100644 --- a/test/unit/ngsiv2/general/startup-test.js +++ b/test/unit/ngsiv2/general/startup-test.js @@ -22,45 +22,45 @@ * * Modified by: Daniel Calvo - ATOS Research & Innovation */ -'use strict'; -var iotAgentLib = require('../../../../lib/fiware-iotagent-lib'), - nock = require('nock'), - utils = require('../../../tools/utils'), - config = require('../../../../lib/commonConfig'), - iotAgentConfig = { - logLevel: 'FATAL', - contextBroker: { - host: '192.168.1.1', - port: '1026', - }, - server: { - port: 4041 - }, - types: { - 'Light': { - commands: [], - type: 'Light', - lazy: [ - { - name: 'temperature', - type: 'centigrades' - } - ], - attributes: [ - { - name: 'pressure', - type: 'Hgmm' - } - ] - } - }, - providerUrl: 'http://smartGondor.com' +/* eslint-disable no-unused-vars */ + +const iotAgentLib = require('../../../../lib/fiware-iotagent-lib'); +const nock = require('nock'); +const utils = require('../../../tools/utils'); +const config = require('../../../../lib/commonConfig'); +const iotAgentConfig = { + logLevel: 'FATAL', + contextBroker: { + host: '192.168.1.1', + port: '1026' + }, + server: { + port: 4041 }, - iotamMock; + types: { + Light: { + commands: [], + type: 'Light', + lazy: [ + { + name: 'temperature', + type: 'centigrades' + } + ], + attributes: [ + { + name: 'pressure', + type: 'Hgmm' + } + ] + } + }, + providerUrl: 'http://smartGondor.com' +}; +let iotamMock; describe('Startup tests', function() { - describe('When the IoT Agent is started with environment variables', function() { beforeEach(function() { process.env.IOTA_CB_HOST = 'cbhost'; @@ -87,8 +87,10 @@ describe('Startup tests', function() { iotamMock = nock('http://iotamhost:4444') .post('/iotampath') - .reply(200, - utils.readExampleFile('./test/unit/ngsiv2/examples/iotamResponses/registrationSuccess.json')); + .reply( + 200, + utils.readExampleFile('./test/unit/ngsiv2/examples/iotamResponses/registrationSuccess.json') + ); }); afterEach(function() { diff --git a/test/unit/ngsiv2/lazyAndCommands/active-devices-attribute-update-test.js b/test/unit/ngsiv2/lazyAndCommands/active-devices-attribute-update-test.js index be1f50e0e..52cc05521 100644 --- a/test/unit/ngsiv2/lazyAndCommands/active-devices-attribute-update-test.js +++ b/test/unit/ngsiv2/lazyAndCommands/active-devices-attribute-update-test.js @@ -22,49 +22,49 @@ * * Modified by: Daniel Calvo - ATOS Research & Innovation */ -'use strict'; -var iotAgentLib = require('../../../../lib/fiware-iotagent-lib'), - should = require('should'), - logger = require('logops'), - nock = require('nock'), - mongoUtils = require('../../mongodb/mongoDBUtils'), - request = require('request'), - contextBrokerMock, - iotAgentConfig = { - logLevel: 'FATAL', - contextBroker: { - host: '192.168.1.1', - port: '1026', - ngsiVersion: 'v2' - }, - server: { - port: 4041 - }, - types: { - 'Light': { - // commands are not defined - active: [ - { - name: 'pressure', - type: 'Hgmm' - } - ] - } - }, - service: 'smartGondor', - subservice: 'gardens', - providerUrl: 'http://smartGondor.com' +/* eslint-disable no-unused-vars */ + +const iotAgentLib = require('../../../../lib/fiware-iotagent-lib'); +const should = require('should'); +const logger = require('logops'); +const nock = require('nock'); +const mongoUtils = require('../../mongodb/mongoDBUtils'); +const request = require('request'); +let contextBrokerMock; +const iotAgentConfig = { + logLevel: 'FATAL', + contextBroker: { + host: '192.168.1.1', + port: '1026', + ngsiVersion: 'v2' }, - device = { - id: 'somelight', - type: 'Light', - service: 'smartGondor', - subservice: 'gardens' - }; + server: { + port: 4041 + }, + types: { + Light: { + // commands are not defined + active: [ + { + name: 'pressure', + type: 'Hgmm' + } + ] + } + }, + service: 'smartGondor', + subservice: 'gardens', + providerUrl: 'http://smartGondor.com' +}; +const device = { + id: 'somelight', + type: 'Light', + service: 'smartGondor', + subservice: 'gardens' +}; describe('Update attribute functionalities', function() { - beforeEach(function(done) { logger.setLevel('FATAL'); @@ -74,7 +74,7 @@ describe('Update attribute functionalities', function() { .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') .post('/v2/registrations') - .reply(201, null, {'Location': '/v2/registrations/6319a7f5254b05844116584d'}); + .reply(201, null, { Location: '/v2/registrations/6319a7f5254b05844116584d' }); contextBrokerMock .matchHeader('fiware-service', 'smartGondor') @@ -99,7 +99,7 @@ describe('Update attribute functionalities', function() { }); describe('When a attribute update arrives to the IoT Agent as Context Provider', function() { - var options = { + const options = { url: 'http://localhost:' + iotAgentConfig.server.port + '/v2/op/update', method: 'POST', json: { @@ -131,7 +131,7 @@ describe('Update attribute functionalities', function() { }); it('should call the client handler with correct values, even if commands are not defined', function(done) { - var handlerCalled = false; + let handlerCalled = false; iotAgentLib.setDataUpdateHandler(function(id, type, service, subservice, attributes, callback) { id.should.equal('Light:somelight'); @@ -143,13 +143,12 @@ describe('Update attribute functionalities', function() { handlerCalled = true; callback(null, { - id: id, - type: type, - attributes: attributes + id, + type, + attributes }); }); - request(options, function(error, response, body) { should.not.exist(error); handlerCalled.should.equal(true); diff --git a/test/unit/ngsiv2/lazyAndCommands/command-test.js b/test/unit/ngsiv2/lazyAndCommands/command-test.js index ddafff6c1..bc3cbeba9 100644 --- a/test/unit/ngsiv2/lazyAndCommands/command-test.js +++ b/test/unit/ngsiv2/lazyAndCommands/command-test.js @@ -22,108 +22,111 @@ * * Modified by: Daniel Calvo - ATOS Research & Innovation */ -'use strict'; -var iotAgentLib = require('../../../../lib/fiware-iotagent-lib'), - utils = require('../../../tools/utils'), - should = require('should'), - logger = require('logops'), - nock = require('nock'), - mongoUtils = require('../../mongodb/mongoDBUtils'), - request = require('request'), - timekeeper = require('timekeeper'), - contextBrokerMock, - statusAttributeMock, - iotAgentConfig = { - contextBroker: { - host: '192.168.1.1', - port: '1026', - ngsiVersion: 'v2' +/* eslint-disable no-unused-vars */ + +const iotAgentLib = require('../../../../lib/fiware-iotagent-lib'); +const utils = require('../../../tools/utils'); +const should = require('should'); +const logger = require('logops'); +const nock = require('nock'); +const mongoUtils = require('../../mongodb/mongoDBUtils'); +const request = require('request'); +const timekeeper = require('timekeeper'); +let contextBrokerMock; +let statusAttributeMock; +const iotAgentConfig = { + contextBroker: { + host: '192.168.1.1', + port: '1026', + ngsiVersion: 'v2' + }, + server: { + port: 4041 + }, + types: { + Light: { + commands: [], + lazy: [ + { + name: 'temperature', + type: 'centigrades' + } + ], + active: [ + { + name: 'pressure', + type: 'Hgmm' + } + ] }, - server: { - port: 4041 + Termometer: { + commands: [], + lazy: [ + { + name: 'temp', + type: 'kelvin' + } + ], + active: [] }, - types: { - 'Light': { - commands: [], - lazy: [ - { - name: 'temperature', - type: 'centigrades' - } - ], - active: [ - { - name: 'pressure', - type: 'Hgmm' - } - ] - }, - 'Termometer': { - commands: [], - lazy: [ - { - name: 'temp', - type: 'kelvin' - } - ], - active: [ - ] - }, - 'Motion': { - commands: [], - lazy: [ - { - name: 'moving', - type: 'Boolean' - } - ], - staticAttributes: [ - { - 'name': 'location', - 'type': 'Vector', - 'value': '(123,523)' - } - ], - active: [] - }, - 'Robot': { - commands: [ - { - name: 'position', - type: 'Array' - } - ], - lazy: [], - staticAttributes: [], - active: [] - } + Motion: { + commands: [], + lazy: [ + { + name: 'moving', + type: 'Boolean' + } + ], + staticAttributes: [ + { + name: 'location', + type: 'Vector', + value: '(123,523)' + } + ], + active: [] }, - service: 'smartGondor', - subservice: 'gardens', - providerUrl: 'http://smartGondor.com' + Robot: { + commands: [ + { + name: 'position', + type: 'Array' + } + ], + lazy: [], + staticAttributes: [], + active: [] + } }, - device3 = { - id: 'r2d2', - type: 'Robot', - service: 'smartGondor', - subservice: 'gardens' - }; + service: 'smartGondor', + subservice: 'gardens', + providerUrl: 'http://smartGondor.com' +}; +const device3 = { + id: 'r2d2', + type: 'Robot', + service: 'smartGondor', + subservice: 'gardens' +}; describe('Command functionalities', function() { beforeEach(function(done) { logger.setLevel('FATAL'); - var time = new Date(1438760101468); // 2015-08-05T07:35:01.468+00:00 + const time = new Date(1438760101468); // 2015-08-05T07:35:01.468+00:00 timekeeper.freeze(time); nock.cleanAll(); contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v2/registrations', + .post( + '/v2/registrations', utils.readExampleFile( - './test/unit/ngsiv2/examples/contextAvailabilityRequests/registerIoTAgentCommands.json')) - .reply(201, null,{'Location': '/v2/registrations/6319a7f5254b05844116584d'}); + './test/unit/ngsiv2/examples/contextAvailabilityRequests/registerIoTAgentCommands.json' + ) + ) + .reply(201, null, { Location: '/v2/registrations/6319a7f5254b05844116584d' }); contextBrokerMock .matchHeader('fiware-service', 'smartGondor') @@ -136,7 +139,7 @@ describe('Command functionalities', function() { afterEach(function(done) { timekeeper.reset(); - delete(device3.registrationId); + delete device3.registrationId; iotAgentLib.clearAll(function() { iotAgentLib.deactivate(function() { mongoUtils.cleanDbs(function() { @@ -159,7 +162,7 @@ describe('Command functionalities', function() { }); }); describe('When a command update arrives to the IoT Agent as Context Provider', function() { - var options = { + const options = { url: 'http://localhost:' + iotAgentConfig.server.port + '/v2/op/update', method: 'POST', json: { @@ -170,7 +173,7 @@ describe('Command functionalities', function() { type: 'Robot', position: { type: 'Array', - value:'[28, -104, 23]' + value: '[28, -104, 23]' } } ] @@ -182,14 +185,13 @@ describe('Command functionalities', function() { }; beforeEach(function(done) { - iotAgentLib.register(device3, function(error) { done(); }); }); it('should call the client handler', function(done) { - var handlerCalled = false; + let handlerCalled = false; iotAgentLib.setCommandHandler(function(id, type, service, subservice, attributes, callback) { id.should.equal(device3.type + ':' + device3.id); @@ -198,8 +200,8 @@ describe('Command functionalities', function() { attributes[0].value.should.equal('[28, -104, 23]'); handlerCalled = true; callback(null, { - id: id, - type: type, + id, + type, attributes: [ { name: 'position', @@ -219,8 +221,8 @@ describe('Command functionalities', function() { it('should create the attribute with the "_status" prefix in the Context Broker', function(done) { iotAgentLib.setCommandHandler(function(id, type, service, subservice, attributes, callback) { callback(null, { - id: id, - type: type, + id, + type, attributes: [ { name: 'position', @@ -237,13 +239,13 @@ describe('Command functionalities', function() { }); }); it('should create the attribute with the "_status" prefix in the Context Broker', function(done) { - var serviceAndSubservice = false; + let serviceAndSubservice = false; iotAgentLib.setCommandHandler(function(id, type, service, subservice, attributes, callback) { serviceAndSubservice = service === 'smartGondor' && subservice === 'gardens'; callback(null, { - id: id, - type: type, + id, + type, attributes: [ { name: 'position', @@ -265,8 +267,10 @@ describe('Command functionalities', function() { statusAttributeMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v2/entities/r2d2/attrs?type=Robot', - utils.readExampleFile('./test/unit/ngsiv2/examples/contextRequests/updateContextCommandFinish.json')) + .post( + '/v2/entities/r2d2/attrs?type=Robot', + utils.readExampleFile('./test/unit/ngsiv2/examples/contextRequests/updateContextCommandFinish.json') + ) .reply(204); iotAgentLib.register(device3, function(error) { @@ -275,12 +279,11 @@ describe('Command functionalities', function() { }); it('should update its value and status in the Context Broker', function(done) { - iotAgentLib.setCommandResult('r2d2', 'Robot', '', 'position', '[72, 368, 1]', 'FINISHED', - function(error) { - should.not.exist(error); - statusAttributeMock.done(); - done(); - }); + iotAgentLib.setCommandResult('r2d2', 'Robot', '', 'position', '[72, 368, 1]', 'FINISHED', function(error) { + should.not.exist(error); + statusAttributeMock.done(); + done(); + }); }); }); describe('When an error command arrives from the south bound for a registered command', function() { @@ -288,8 +291,10 @@ describe('Command functionalities', function() { statusAttributeMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v2/entities/r2d2/attrs?type=Robot', - utils.readExampleFile('./test/unit/ngsiv2/examples/contextRequests/updateContextCommandError.json')) + .post( + '/v2/entities/r2d2/attrs?type=Robot', + utils.readExampleFile('./test/unit/ngsiv2/examples/contextRequests/updateContextCommandError.json') + ) .reply(204); iotAgentLib.register(device3, function(error) { @@ -298,12 +303,11 @@ describe('Command functionalities', function() { }); it('should update its status in the Context Broker', function(done) { - iotAgentLib.setCommandResult('r2d2', 'Robot', '', 'position', 'Stalled', 'ERROR', - function(error) { - should.not.exist(error); - statusAttributeMock.done(); - done(); - }); + iotAgentLib.setCommandResult('r2d2', 'Robot', '', 'position', 'Stalled', 'ERROR', function(error) { + should.not.exist(error); + statusAttributeMock.done(); + done(); + }); }); }); }); diff --git a/test/unit/ngsiv2/lazyAndCommands/lazy-devices-test.js b/test/unit/ngsiv2/lazyAndCommands/lazy-devices-test.js index 850545a57..ea7212a97 100644 --- a/test/unit/ngsiv2/lazyAndCommands/lazy-devices-test.js +++ b/test/unit/ngsiv2/lazyAndCommands/lazy-devices-test.js @@ -22,130 +22,130 @@ * * Modified by: Daniel Calvo - ATOS Research & Innovation */ -'use strict'; - -var iotAgentLib = require('../../../../lib/fiware-iotagent-lib'), - utils = require('../../../tools/utils'), - async = require('async'), - apply = async.apply, - should = require('should'), - logger = require('logops'), - nock = require('nock'), - mongoUtils = require('../../mongodb/mongoDBUtils'), - request = require('request'), - timekeeper = require('timekeeper'), - contextBrokerMock, - iotAgentConfig = { - contextBroker: { - host: '192.168.1.1', - port: '1026', - ngsiVersion: 'v2' + +/* eslint-disable no-unused-vars */ + +const iotAgentLib = require('../../../../lib/fiware-iotagent-lib'); +const utils = require('../../../tools/utils'); +const async = require('async'); +const apply = async.apply; +const should = require('should'); +const logger = require('logops'); +const nock = require('nock'); +const mongoUtils = require('../../mongodb/mongoDBUtils'); +const request = require('request'); +const timekeeper = require('timekeeper'); +let contextBrokerMock; +const iotAgentConfig = { + contextBroker: { + host: '192.168.1.1', + port: '1026', + ngsiVersion: 'v2' + }, + server: { + port: 4041 + }, + types: { + Light: { + commands: [], + lazy: [ + { + name: 'temperature', + type: 'centigrades' + } + ], + active: [ + { + name: 'pressure', + type: 'Hgmm' + } + ] }, - server: { - port: 4041 + Termometer: { + commands: [], + lazy: [ + { + name: 'temp', + type: 'kelvin' + } + ], + active: [] }, - types: { - 'Light': { - commands: [], - lazy: [ - { - name: 'temperature', - type: 'centigrades' - } - ], - active: [ - { - name: 'pressure', - type: 'Hgmm' - } - ] - }, - 'Termometer': { - commands: [], - lazy: [ - { - name: 'temp', - type: 'kelvin' - } - ], - active: [ - ] - }, - 'Motion': { - commands: [], - lazy: [ - { - name: 'moving', - type: 'Boolean' - } - ], - staticAttributes: [ - { - 'name': 'location', - 'type': 'Vector', - 'value': '(123,523)' - } - ], - active: [] - }, - 'RobotPre': { - commands: [], - lazy: [ - { - name: 'moving', - type: 'Boolean' - } - ], - staticAttributes: [], - attributes: [], - internalAttributes: { - lwm2mResourceMapping: { - position: { - objectType: 9090, - objectInstance: 0, - objectResource: 0 - } + Motion: { + commands: [], + lazy: [ + { + name: 'moving', + type: 'Boolean' + } + ], + staticAttributes: [ + { + name: 'location', + type: 'Vector', + value: '(123,523)' + } + ], + active: [] + }, + RobotPre: { + commands: [], + lazy: [ + { + name: 'moving', + type: 'Boolean' + } + ], + staticAttributes: [], + attributes: [], + internalAttributes: { + lwm2mResourceMapping: { + position: { + objectType: 9090, + objectInstance: 0, + objectResource: 0 } } } - }, - service: 'smartGondor', - subservice: 'gardens', - providerUrl: 'http://smartGondor.com' - }, - device1 = { - id: 'light1', - type: 'Light', - service: 'smartGondor', - subservice: 'gardens' - }, - device2 = { - id: 'motion1', - type: 'Motion', - service: 'smartGondor', - subservice: 'gardens' + } }, - device3 = { - id: 'TestRobotPre', - type: 'RobotPre', - service: 'smartGondor', - subservice: 'gardens', - internalAttributes: { - lwm2mResourceMapping: { - position: { - objectType: 6789, - objectInstance: 0, - objectResource: 17 - } + service: 'smartGondor', + subservice: 'gardens', + providerUrl: 'http://smartGondor.com' +}; +const device1 = { + id: 'light1', + type: 'Light', + service: 'smartGondor', + subservice: 'gardens' +}; +const device2 = { + id: 'motion1', + type: 'Motion', + service: 'smartGondor', + subservice: 'gardens' +}; +const device3 = { + id: 'TestRobotPre', + type: 'RobotPre', + service: 'smartGondor', + subservice: 'gardens', + internalAttributes: { + lwm2mResourceMapping: { + position: { + objectType: 6789, + objectInstance: 0, + objectResource: 17 } } - }; + } +}; describe('IoT Agent Lazy Devices', function() { beforeEach(function(done) { logger.setLevel('FATAL'); - var time = new Date(1438760101468); // 2015-08-05T07:35:01.468+00:00 + const time = new Date(1438760101468); // 2015-08-05T07:35:01.468+00:00 timekeeper.freeze(time); mongoUtils.cleanDbs(done); @@ -154,9 +154,9 @@ describe('IoT Agent Lazy Devices', function() { afterEach(function(done) { timekeeper.reset(); - delete(device1.registrationId); - delete(device2.registrationId); - delete(device3.registrationId); + delete device1.registrationId; + delete device2.registrationId; + delete device3.registrationId; iotAgentLib.clearAll(function() { iotAgentLib.deactivate(function() { @@ -166,7 +166,7 @@ describe('IoT Agent Lazy Devices', function() { }); describe('When the IoT Agent receives an update on the device data in JSON format', function() { - var options = { + const options = { url: 'http://localhost:' + iotAgentConfig.server.port + '/v2/op/update', method: 'POST', json: { @@ -194,10 +194,13 @@ describe('IoT Agent Lazy Devices', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v2/registrations', + .post( + '/v2/registrations', utils.readExampleFile( - './test/unit/ngsiv2/examples/contextAvailabilityRequests/registerIoTAgent1.json')) - .reply(201, null, {'Location': '/v2/registrations/6319a7f5254b05844116584d'}); + './test/unit/ngsiv2/examples/contextAvailabilityRequests/registerIoTAgent1.json' + ) + ) + .reply(201, null, { Location: '/v2/registrations/6319a7f5254b05844116584d' }); contextBrokerMock .matchHeader('fiware-service', 'smartGondor') @@ -205,19 +208,15 @@ describe('IoT Agent Lazy Devices', function() { .post('/v2/entities?options=upsert') .reply(204); - async.series([ - apply(iotAgentLib.activate, iotAgentConfig), - apply(iotAgentLib.register, device1) - ], done); + async.series([apply(iotAgentLib.activate, iotAgentConfig), apply(iotAgentLib.register, device1)], done); }); it('should call the device handler with the received data', function(done) { - iotAgentLib.setDataUpdateHandler(function(id, type, service, subservice, attributes, callback) { id.should.equal(device1.type + ':' + device1.id); type.should.equal(device1.type); attributes[0].value.should.equal(12); - callback(null); + callback(null); }); request(options, function(error, response, body) { @@ -233,34 +232,33 @@ describe('IoT Agent Lazy Devices', function() { }); describe('When a context query arrives to the IoT Agent', function() { - var options = { - url: 'http://localhost:' + iotAgentConfig.server.port + '/v2/op/query', - method: 'POST', - json: true, - headers: { - 'fiware-service': 'smartGondor', - 'fiware-servicepath': 'gardens' - }, - body: { - entities: [ - { - id: 'Light:light1' - } - ], - attrs: [ 'dimming' ] - } + const options = { + url: 'http://localhost:' + iotAgentConfig.server.port + '/v2/op/query', + method: 'POST', + json: true, + headers: { + 'fiware-service': 'smartGondor', + 'fiware-servicepath': 'gardens' }, - sensorData = [ - { - id: 'Light:light1', - type: 'Light', - dimming: + body: { + entities: [ { - type: 'Percentage', - value: 19 + id: 'Light:light1' } + ], + attrs: ['dimming'] + } + }; + const sensorData = [ + { + id: 'Light:light1', + type: 'Light', + dimming: { + type: 'Percentage', + value: 19 } - ]; + } + ]; beforeEach(function(done) { nock.cleanAll(); @@ -268,10 +266,13 @@ describe('IoT Agent Lazy Devices', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v2/registrations', + .post( + '/v2/registrations', utils.readExampleFile( - './test/unit/ngsiv2/examples/contextAvailabilityRequests/registerIoTAgent1.json')) - .reply(201, null, {'Location': '/v2/registrations/6319a7f5254b05844116584d'}); + './test/unit/ngsiv2/examples/contextAvailabilityRequests/registerIoTAgent1.json' + ) + ) + .reply(201, null, { Location: '/v2/registrations/6319a7f5254b05844116584d' }); contextBrokerMock .matchHeader('fiware-service', 'smartGondor') @@ -279,15 +280,13 @@ describe('IoT Agent Lazy Devices', function() { .post('/v2/entities?options=upsert') .reply(204); - async.series([ - apply(iotAgentLib.activate, iotAgentConfig), - apply(iotAgentLib.register, device1) - ], done); + async.series([apply(iotAgentLib.activate, iotAgentConfig), apply(iotAgentLib.register, device1)], done); }); it('should return the information querying the underlying devices', function(done) { - var expectedResponse = utils - .readExampleFile('./test/unit/ngsiv2/examples/contextProviderResponses/queryInformationResponse.json'); + const expectedResponse = utils.readExampleFile( + './test/unit/ngsiv2/examples/contextProviderResponses/queryInformationResponse.json' + ); iotAgentLib.setDataQueryHandler(function(id, type, service, subservice, attributes, callback) { id.should.equal(device1.type + ':' + device1.id); @@ -305,23 +304,23 @@ describe('IoT Agent Lazy Devices', function() { }); describe('When a context query arrives to the IoT Agent and no handler is set', function() { - var options = { - url: 'http://localhost:' + iotAgentConfig.server.port + '/v2/op/query', - method: 'POST', - json: true, - headers: { - 'fiware-service': 'smartGondor', - 'fiware-servicepath': 'gardens' - }, - body: { - entities: [ - { - id: 'Light:light1' - } - ], - attrs: [ 'dimming' ] - } - }; + const options = { + url: 'http://localhost:' + iotAgentConfig.server.port + '/v2/op/query', + method: 'POST', + json: true, + headers: { + 'fiware-service': 'smartGondor', + 'fiware-servicepath': 'gardens' + }, + body: { + entities: [ + { + id: 'Light:light1' + } + ], + attrs: ['dimming'] + } + }; beforeEach(function(done) { nock.cleanAll(); @@ -329,10 +328,13 @@ describe('IoT Agent Lazy Devices', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v2/registrations', + .post( + '/v2/registrations', utils.readExampleFile( - './test/unit/ngsiv2/examples/contextAvailabilityRequests/registerIoTAgent1.json')) - .reply(201, null, {'Location': '/v2/registrations/6319a7f5254b05844116584d'}); + './test/unit/ngsiv2/examples/contextAvailabilityRequests/registerIoTAgent1.json' + ) + ) + .reply(201, null, { Location: '/v2/registrations/6319a7f5254b05844116584d' }); contextBrokerMock .matchHeader('fiware-service', 'smartGondor') @@ -340,10 +342,9 @@ describe('IoT Agent Lazy Devices', function() { .post('/v2/entities?options=upsert') .reply(204); - async.series([ - apply(iotAgentLib.activate, iotAgentConfig), - apply(iotAgentLib.register, device1) - ], function(error) { + async.series([apply(iotAgentLib.activate, iotAgentConfig), apply(iotAgentLib.register, device1)], function( + error + ) { done(); }); }); @@ -358,7 +359,7 @@ describe('IoT Agent Lazy Devices', function() { it('should return the empty value', function(done) { request(options, function(error, response, body) { - var entities = body; + const entities = body; entities[0].dimming.value.should.equal(''); done(); }); @@ -366,33 +367,32 @@ describe('IoT Agent Lazy Devices', function() { }); describe('When a query arrives to the IoT Agent without any attributes', function() { - var options = { - url: 'http://localhost:' + iotAgentConfig.server.port + '/v2/op/query', - method: 'POST', - json: true, - headers: { - 'fiware-service': 'smartGondor', - 'fiware-servicepath': 'gardens' - }, - body: { - entities: [ - { - id: 'Light:light1' - } - ] - } + const options = { + url: 'http://localhost:' + iotAgentConfig.server.port + '/v2/op/query', + method: 'POST', + json: true, + headers: { + 'fiware-service': 'smartGondor', + 'fiware-servicepath': 'gardens' }, - sensorData = [ - { - id: 'Light:light1', - type: 'Light', - temperature: + body: { + entities: [ { - type: 'centigrades', - value: 19 + id: 'Light:light1' } + ] + } + }; + const sensorData = [ + { + id: 'Light:light1', + type: 'Light', + temperature: { + type: 'centigrades', + value: 19 } - ]; + } + ]; beforeEach(function(done) { nock.cleanAll(); @@ -400,10 +400,13 @@ describe('IoT Agent Lazy Devices', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v2/registrations', + .post( + '/v2/registrations', utils.readExampleFile( - './test/unit/ngsiv2/examples/contextAvailabilityRequests/registerIoTAgent1.json')) - .reply(201, null, {'Location': '/v2/registrations/6319a7f5254b05844116584d'}); + './test/unit/ngsiv2/examples/contextAvailabilityRequests/registerIoTAgent1.json' + ) + ) + .reply(201, null, { Location: '/v2/registrations/6319a7f5254b05844116584d' }); contextBrokerMock .matchHeader('fiware-service', 'smartGondor') @@ -411,16 +414,13 @@ describe('IoT Agent Lazy Devices', function() { .post('/v2/entities?options=upsert') .reply(204); - async.series([ - apply(iotAgentLib.activate, iotAgentConfig), - apply(iotAgentLib.register, device1) - ], done); + async.series([apply(iotAgentLib.activate, iotAgentConfig), apply(iotAgentLib.register, device1)], done); }); it('should return the information of all the attributes', function(done) { - var expectedResponse = utils.readExampleFile( - './test/unit/ngsiv2/examples/contextProviderResponses/' + - 'queryInformationResponseEmptyAttributes.json'); + const expectedResponse = utils.readExampleFile( + './test/unit/ngsiv2/examples/contextProviderResponses/queryInformationResponseEmptyAttributes.json' + ); iotAgentLib.setDataQueryHandler(function(id, type, service, subservice, attributes, callback) { should.exist(attributes); @@ -438,34 +438,33 @@ describe('IoT Agent Lazy Devices', function() { }); describe('When a context query arrives to the IoT Agent for a type with static attributes', function() { - var options = { - url: 'http://localhost:' + iotAgentConfig.server.port + '/v2/op/query', - method: 'POST', - json: true, - headers: { - 'fiware-service': 'smartGondor', - 'fiware-servicepath': 'gardens' - }, - body: { - entities: [ - { - id: 'Motion:motion1' - } - ], - attrs: [ 'moving', 'location'] - } + const options = { + url: 'http://localhost:' + iotAgentConfig.server.port + '/v2/op/query', + method: 'POST', + json: true, + headers: { + 'fiware-service': 'smartGondor', + 'fiware-servicepath': 'gardens' }, - sensorData = [ - { - id: 'Motion:motion1', - type: 'Motion', - 'moving': + body: { + entities: [ { - type: 'Boolean', - value: true + id: 'Motion:motion1' } + ], + attrs: ['moving', 'location'] + } + }; + const sensorData = [ + { + id: 'Motion:motion1', + type: 'Motion', + moving: { + type: 'Boolean', + value: true } - ]; + } + ]; beforeEach(function(done) { nock.cleanAll(); @@ -473,10 +472,13 @@ describe('IoT Agent Lazy Devices', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v2/registrations', + .post( + '/v2/registrations', utils.readExampleFile( - './test/unit/ngsiv2/examples/contextAvailabilityRequests/registerIoTAgent2.json')) - .reply(201, null, {'Location': '/v2/registrations/6319a7f5254b05844116584d'}); + './test/unit/ngsiv2/examples/contextAvailabilityRequests/registerIoTAgent2.json' + ) + ) + .reply(201, null, { Location: '/v2/registrations/6319a7f5254b05844116584d' }); contextBrokerMock .matchHeader('fiware-service', 'smartGondor') @@ -484,15 +486,13 @@ describe('IoT Agent Lazy Devices', function() { .post('/v2/entities?options=upsert') .reply(204); - async.series([ - apply(iotAgentLib.activate, iotAgentConfig), - apply(iotAgentLib.register, device2) - ], done); + async.series([apply(iotAgentLib.activate, iotAgentConfig), apply(iotAgentLib.register, device2)], done); }); it('should return the information adding the static attributes', function(done) { - var expectedResponse = utils.readExampleFile( - './test/unit/ngsiv2/examples/contextProviderResponses/queryInformationStaticAttributesResponse.json'); + const expectedResponse = utils.readExampleFile( + './test/unit/ngsiv2/examples/contextProviderResponses/queryInformationStaticAttributesResponse.json' + ); iotAgentLib.setDataQueryHandler(function(id, type, service, subservice, attributes, callback) { id.should.equal('Motion:motion1'); @@ -510,114 +510,125 @@ describe('IoT Agent Lazy Devices', function() { }); }); - describe('When the IoT Agent receives an update on the device data in JSON format for a type with' + - 'internalAttributes', function() { - var options = { - url: 'http://localhost:' + iotAgentConfig.server.port + '/v2/op/update', - method: 'POST', - json: { - actionType: 'update', - entities: [ - { - id: 'RobotPre:TestRobotPre', - type: 'RobotPre', - moving: { - type: 'Boolean', - value: true - } - } - ] - }, - headers: { - 'fiware-service': 'smartGondor', - 'fiware-servicepath': 'gardens' - } - }; - - beforeEach(function(done) { - nock.cleanAll(); - - contextBrokerMock = nock('http://192.168.1.1:1026') - .matchHeader('fiware-service', 'smartGondor') - .matchHeader('fiware-servicepath', 'gardens') - .post('/v2/registrations', - utils.readExampleFile( - './test/unit/ngsiv2/examples/contextAvailabilityRequests/registerIoTAgent4.json')) - .reply(201, null, {'Location': '/v2/registrations/6319a7f5254b05844116584d'}); - - contextBrokerMock - .matchHeader('fiware-service', 'smartGondor') - .matchHeader('fiware-servicepath', 'gardens') - .post('/v2/entities?options=upsert') - .reply(204); - - async.series([ - apply(iotAgentLib.activate, iotAgentConfig), - apply(iotAgentLib.register, device3) - ], done); - }); - - it('should call the device handler with the received data', function(done) { - - iotAgentLib.setDataUpdateHandler(function(id, type, service, subservice, attributes, callback) { - id.should.equal(device3.type + ':' + device3.id); - type.should.equal(device3.type); - attributes[0].value.should.equal(true); - callback(null); - }); - - request(options, function(error, response, body) { - should.not.exist(error); - response.statusCode.should.equal(204); - done(); - }); - }); - }); - - describe('When a context query arrives to the IoT Agent and id and type query params are not present', function() { - var options = { - url: 'http://localhost:' + iotAgentConfig.server.port + '/v2/op/query', + describe( + 'When the IoT Agent receives an update on the device data in JSON format for a type with' + + 'internalAttributes', + function() { + const options = { + url: 'http://localhost:' + iotAgentConfig.server.port + '/v2/op/update', method: 'POST', - json: true, - headers: { - 'fiware-service': 'smartGondor', - 'fiware-servicepath': 'gardens' - }, - body: { + json: { + actionType: 'update', entities: [ { - idPattern: '.*' + id: 'RobotPre:TestRobotPre', + type: 'RobotPre', + moving: { + type: 'Boolean', + value: true + } } ] + }, + headers: { + 'fiware-service': 'smartGondor', + 'fiware-servicepath': 'gardens' } }; + beforeEach(function(done) { + nock.cleanAll(); + + contextBrokerMock = nock('http://192.168.1.1:1026') + .matchHeader('fiware-service', 'smartGondor') + .matchHeader('fiware-servicepath', 'gardens') + .post( + '/v2/registrations', + utils.readExampleFile( + './test/unit/ngsiv2/examples/contextAvailabilityRequests/registerIoTAgent4.json' + ) + ) + .reply(201, null, { Location: '/v2/registrations/6319a7f5254b05844116584d' }); + + contextBrokerMock + .matchHeader('fiware-service', 'smartGondor') + .matchHeader('fiware-servicepath', 'gardens') + .post('/v2/entities?options=upsert') + .reply(204); + + async.series([apply(iotAgentLib.activate, iotAgentConfig), apply(iotAgentLib.register, device3)], done); + }); + + it('should call the device handler with the received data', function(done) { + iotAgentLib.setDataUpdateHandler(function(id, type, service, subservice, attributes, callback) { + id.should.equal(device3.type + ':' + device3.id); + type.should.equal(device3.type); + attributes[0].value.should.equal(true); + callback(null); + }); + + request(options, function(error, response, body) { + should.not.exist(error); + response.statusCode.should.equal(204); + done(); + }); + }); + } + ); + + describe('When a context query arrives to the IoT Agent and id and type query params are not present', function() { + const options = { + url: 'http://localhost:' + iotAgentConfig.server.port + '/v2/op/query', + method: 'POST', + json: true, + headers: { + 'fiware-service': 'smartGondor', + 'fiware-servicepath': 'gardens' + }, + body: { + entities: [ + { + idPattern: '.*' + } + ] + } + }; + beforeEach(function(done) { nock.cleanAll(); contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v2/registrations', + .post( + '/v2/registrations', utils.readExampleFile( - './test/unit/ngsiv2/examples/contextAvailabilityRequests/registerIoTAgent1.json')) - .reply(201, null, {'Location': '/v2/registrations/6319a7f5254b05844116584d'}); + './test/unit/ngsiv2/examples/contextAvailabilityRequests/registerIoTAgent1.json' + ) + ) + .reply(201, null, { Location: '/v2/registrations/6319a7f5254b05844116584d' }); contextBrokerMock .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v2/registrations', + .post( + '/v2/registrations', utils.readExampleFile( - './test/unit/ngsiv2/examples/contextAvailabilityRequests/registerIoTAgent2.json')) - .reply(201, null, {'Location': '/v2/registrations/6319a7f5254b05844116584d'}); + './test/unit/ngsiv2/examples/contextAvailabilityRequests/registerIoTAgent2.json' + ) + ) + .reply(201, null, { Location: '/v2/registrations/6319a7f5254b05844116584d' }); contextBrokerMock .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v2/registrations', + .post( + '/v2/registrations', utils.readExampleFile( - './test/unit/ngsiv2/examples/contextAvailabilityRequests/registerIoTAgent4.json')) - .reply(201, null, {'Location': '/v2/registrations/6319a7f5254b05844116584d'}); + './test/unit/ngsiv2/examples/contextAvailabilityRequests/registerIoTAgent4.json' + ) + ) + .reply(201, null, { Location: '/v2/registrations/6319a7f5254b05844116584d' }); contextBrokerMock .matchHeader('fiware-service', 'smartGondor') @@ -626,16 +637,18 @@ describe('IoT Agent Lazy Devices', function() { .times(3) .reply(204); - async.series([ - apply(iotAgentLib.activate, iotAgentConfig), - apply(iotAgentLib.register, device1), - apply(iotAgentLib.register, device2), - apply(iotAgentLib.register, device3), - ], done); + async.series( + [ + apply(iotAgentLib.activate, iotAgentConfig), + apply(iotAgentLib.register, device1), + apply(iotAgentLib.register, device2), + apply(iotAgentLib.register, device3) + ], + done + ); }); it('should return error as idPattern is not supported', function(done) { - request(options, function(error, response, body) { should.not.exist(error); response.statusCode.should.equal(400); @@ -647,23 +660,23 @@ describe('IoT Agent Lazy Devices', function() { }); describe('When a context query arrives to the IoT Agent and id query param is not present', function() { - var options = { - url: 'http://localhost:' + iotAgentConfig.server.port + '/v2/op/query', - method: 'POST', - json: true, - headers: { - 'fiware-service': 'smartGondor', - 'fiware-servicepath': 'gardens' - }, - body: { - entities: [ - { - idPattern: '.*', - type: 'Light' - } - ] - } - }; + const options = { + url: 'http://localhost:' + iotAgentConfig.server.port + '/v2/op/query', + method: 'POST', + json: true, + headers: { + 'fiware-service': 'smartGondor', + 'fiware-servicepath': 'gardens' + }, + body: { + entities: [ + { + idPattern: '.*', + type: 'Light' + } + ] + } + }; beforeEach(function(done) { nock.cleanAll(); @@ -671,26 +684,35 @@ describe('IoT Agent Lazy Devices', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v2/registrations', + .post( + '/v2/registrations', utils.readExampleFile( - './test/unit/ngsiv2/examples/contextAvailabilityRequests/registerIoTAgent1.json')) - .reply(201, null, {'Location': '/v2/registrations/6319a7f5254b05844116584d'}); + './test/unit/ngsiv2/examples/contextAvailabilityRequests/registerIoTAgent1.json' + ) + ) + .reply(201, null, { Location: '/v2/registrations/6319a7f5254b05844116584d' }); contextBrokerMock .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v2/registrations', + .post( + '/v2/registrations', utils.readExampleFile( - './test/unit/ngsiv2/examples/contextAvailabilityRequests/registerIoTAgent2.json')) - .reply(201, null, {'Location': '/v2/registrations/6319a7f5254b05844116584d'}); + './test/unit/ngsiv2/examples/contextAvailabilityRequests/registerIoTAgent2.json' + ) + ) + .reply(201, null, { Location: '/v2/registrations/6319a7f5254b05844116584d' }); contextBrokerMock .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v2/registrations', + .post( + '/v2/registrations', utils.readExampleFile( - './test/unit/ngsiv2/examples/contextAvailabilityRequests/registerIoTAgent4.json')) - .reply(201, null, {'Location': '/v2/registrations/6319a7f5254b05844116584d'}); + './test/unit/ngsiv2/examples/contextAvailabilityRequests/registerIoTAgent4.json' + ) + ) + .reply(201, null, { Location: '/v2/registrations/6319a7f5254b05844116584d' }); contextBrokerMock .matchHeader('fiware-service', 'smartGondor') @@ -699,16 +721,18 @@ describe('IoT Agent Lazy Devices', function() { .times(3) .reply(204); - async.series([ - apply(iotAgentLib.activate, iotAgentConfig), - apply(iotAgentLib.register, device1), - apply(iotAgentLib.register, device2), - apply(iotAgentLib.register, device3), - ], done); + async.series( + [ + apply(iotAgentLib.activate, iotAgentConfig), + apply(iotAgentLib.register, device1), + apply(iotAgentLib.register, device2), + apply(iotAgentLib.register, device3) + ], + done + ); }); it('should return error as idPattern is not supported', function(done) { - request(options, function(error, response, body) { should.not.exist(error); response.statusCode.should.equal(400); @@ -720,35 +744,34 @@ describe('IoT Agent Lazy Devices', function() { }); describe('When a query arrives to the IoT Agent with id, type and attributes', function() { - var options = { - url: 'http://localhost:' + iotAgentConfig.server.port + '/v2/op/query', - method: 'POST', - json: true, - headers: { - 'fiware-service': 'smartGondor', - 'fiware-servicepath': 'gardens' - }, - body: { - entities: [ - { - id: 'Light:light1', - type: 'Light' - } - ], - attrs: [ 'temperature' ] - } + const options = { + url: 'http://localhost:' + iotAgentConfig.server.port + '/v2/op/query', + method: 'POST', + json: true, + headers: { + 'fiware-service': 'smartGondor', + 'fiware-servicepath': 'gardens' }, - sensorData = [ - { - id: 'Light:light1', - type: 'Light', - temperature: + body: { + entities: [ { - type: 'centigrades', - value: 19 + id: 'Light:light1', + type: 'Light' } + ], + attrs: ['temperature'] + } + }; + const sensorData = [ + { + id: 'Light:light1', + type: 'Light', + temperature: { + type: 'centigrades', + value: 19 } - ]; + } + ]; beforeEach(function(done) { nock.cleanAll(); @@ -756,10 +779,13 @@ describe('IoT Agent Lazy Devices', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v2/registrations', + .post( + '/v2/registrations', utils.readExampleFile( - './test/unit/ngsiv2/examples/contextAvailabilityRequests/registerIoTAgent1.json')) - .reply(201, null, {'Location': '/v2/registrations/6319a7f5254b05844116584d'}); + './test/unit/ngsiv2/examples/contextAvailabilityRequests/registerIoTAgent1.json' + ) + ) + .reply(201, null, { Location: '/v2/registrations/6319a7f5254b05844116584d' }); contextBrokerMock .matchHeader('fiware-service', 'smartGondor') @@ -767,16 +793,13 @@ describe('IoT Agent Lazy Devices', function() { .post('/v2/entities?options=upsert') .reply(204); - async.series([ - apply(iotAgentLib.activate, iotAgentConfig), - apply(iotAgentLib.register, device1) - ], done); + async.series([apply(iotAgentLib.activate, iotAgentConfig), apply(iotAgentLib.register, device1)], done); }); it('should return the information of all the attributes', function(done) { - var expectedResponse = utils.readExampleFile( - './test/unit/ngsiv2/examples/contextProviderResponses/' + - 'queryInformationResponseEmptyAttributes.json'); + const expectedResponse = utils.readExampleFile( + './test/unit/ngsiv2/examples/contextProviderResponses/queryInformationResponseEmptyAttributes.json' + ); iotAgentLib.setDataQueryHandler(function(id, type, service, subservice, attributes, callback) { should.exist(attributes); diff --git a/test/unit/ngsiv2/lazyAndCommands/polling-commands-test.js b/test/unit/ngsiv2/lazyAndCommands/polling-commands-test.js index ac473628e..1f9ad14af 100644 --- a/test/unit/ngsiv2/lazyAndCommands/polling-commands-test.js +++ b/test/unit/ngsiv2/lazyAndCommands/polling-commands-test.js @@ -22,104 +22,104 @@ * * Modified by: Daniel Calvo - ATOS Research & Innovation */ -'use strict'; - -var iotAgentLib = require('../../../../lib/fiware-iotagent-lib'), - utils = require('../../../tools/utils'), - should = require('should'), - logger = require('logops'), - nock = require('nock'), - mongoUtils = require('../../mongodb/mongoDBUtils'), - request = require('request'), - contextBrokerMock, - statusAttributeMock, - iotAgentConfig = { - contextBroker: { - host: '192.168.1.1', - port: '1026', - ngsiVersion: 'v2' + +/* eslint-disable no-unused-vars */ + +const iotAgentLib = require('../../../../lib/fiware-iotagent-lib'); +const utils = require('../../../tools/utils'); +const should = require('should'); +const logger = require('logops'); +const nock = require('nock'); +const mongoUtils = require('../../mongodb/mongoDBUtils'); +const request = require('request'); +let contextBrokerMock; +let statusAttributeMock; +const iotAgentConfig = { + contextBroker: { + host: '192.168.1.1', + port: '1026', + ngsiVersion: 'v2' + }, + server: { + port: 4041 + }, + types: { + Light: { + commands: [], + lazy: [ + { + name: 'temperature', + type: 'centigrades' + } + ], + active: [ + { + name: 'pressure', + type: 'Hgmm' + } + ] }, - server: { - port: 4041 + Termometer: { + commands: [], + lazy: [ + { + name: 'temp', + type: 'kelvin' + } + ], + active: [] }, - types: { - 'Light': { - commands: [], - lazy: [ - { - name: 'temperature', - type: 'centigrades' - } - ], - active: [ - { - name: 'pressure', - type: 'Hgmm' - } - ] - }, - 'Termometer': { - commands: [], - lazy: [ - { - name: 'temp', - type: 'kelvin' - } - ], - active: [ - ] - }, - 'Motion': { - commands: [], - lazy: [ - { - name: 'moving', - type: 'Boolean' - } - ], - staticAttributes: [ - { - 'name': 'location', - 'type': 'Vector', - 'value': '(123,523)' - } - ], - active: [] - }, - 'Robot': { - commands: [ - { - name: 'position', - type: 'Array' - } - ], - lazy: [], - staticAttributes: [], - active: [] - } - }, - deviceRegistry: { - type: 'mongodb' + Motion: { + commands: [], + lazy: [ + { + name: 'moving', + type: 'Boolean' + } + ], + staticAttributes: [ + { + name: 'location', + type: 'Vector', + value: '(123,523)' + } + ], + active: [] }, + Robot: { + commands: [ + { + name: 'position', + type: 'Array' + } + ], + lazy: [], + staticAttributes: [], + active: [] + } + }, + deviceRegistry: { + type: 'mongodb' + }, - mongodb: { - host: 'localhost', - port: '27017', - db: 'iotagent' - }, - service: 'smartGondor', - subservice: 'gardens', - providerUrl: 'http://smartGondor.com', - pollingExpiration: 200, - pollingDaemonFrequency: 20 + mongodb: { + host: 'localhost', + port: '27017', + db: 'iotagent' }, - device3 = { - id: 'r2d2', - type: 'Robot', - service: 'smartGondor', - subservice: 'gardens', - polling: true - }; + service: 'smartGondor', + subservice: 'gardens', + providerUrl: 'http://smartGondor.com', + pollingExpiration: 200, + pollingDaemonFrequency: 20 +}; +const device3 = { + id: 'r2d2', + type: 'Robot', + service: 'smartGondor', + subservice: 'gardens', + polling: true +}; describe('Polling commands', function() { beforeEach(function(done) { @@ -131,7 +131,7 @@ describe('Polling commands', function() { .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') .post('/v2/registrations') - .reply(201, null, {'Location': '/v2/registrations/6319a7f5254b05844116584d'}); + .reply(201, null, { Location: '/v2/registrations/6319a7f5254b05844116584d' }); contextBrokerMock .matchHeader('fiware-service', 'smartGondor') @@ -139,12 +139,11 @@ describe('Polling commands', function() { .post('/v2/entities?options=upsert') .reply(204); - iotAgentLib.activate(iotAgentConfig, done); }); afterEach(function(done) { - delete(device3.registrationId); + delete device3.registrationId; iotAgentLib.clearAll(function() { iotAgentLib.deactivate(function() { mongoUtils.cleanDbs(function() { @@ -158,7 +157,7 @@ describe('Polling commands', function() { }); describe('When a command update arrives to the IoT Agent for a device with polling', function() { - var options = { + const options = { url: 'http://localhost:' + iotAgentConfig.server.port + '/v2/op/update', method: 'POST', json: { @@ -184,9 +183,10 @@ describe('Polling commands', function() { statusAttributeMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v2/entities/Robot:r2d2/attrs?type=Robot', - utils.readExampleFile( - './test/unit/ngsiv2/examples/contextRequests/updateContextCommandStatus.json')) + .post( + '/v2/entities/Robot:r2d2/attrs?type=Robot', + utils.readExampleFile('./test/unit/ngsiv2/examples/contextRequests/updateContextCommandStatus.json') + ) .reply(204); iotAgentLib.register(device3, function(error) { @@ -195,13 +195,13 @@ describe('Polling commands', function() { }); it('should not call the client handler', function(done) { - var handlerCalled = false; + let handlerCalled = false; iotAgentLib.setCommandHandler(function(id, type, service, subservice, attributes, callback) { handlerCalled = true; callback(null, { - id: id, - type: type, + id, + type, attributes: [ { name: 'position', @@ -248,7 +248,7 @@ describe('Polling commands', function() { }); describe('When a command arrives with multiple values in the value field', function() { - var options = { + const options = { url: 'http://localhost:' + iotAgentConfig.server.port + '/v2/op/update', method: 'POST', json: { @@ -277,9 +277,10 @@ describe('Polling commands', function() { statusAttributeMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v2/entities/Robot:r2d2/attrs?type=Robot', - utils.readExampleFile( - './test/unit/ngsiv2/examples/contextRequests/updateContextCommandStatus.json')) + .post( + '/v2/entities/Robot:r2d2/attrs?type=Robot', + utils.readExampleFile('./test/unit/ngsiv2/examples/contextRequests/updateContextCommandStatus.json') + ) .reply(204); iotAgentLib.register(device3, function(error) { @@ -303,7 +304,7 @@ describe('Polling commands', function() { }); describe('When a polling command expires', function() { - var options = { + const options = { url: 'http://localhost:' + iotAgentConfig.server.port + '/v2/op/update', method: 'POST', json: { @@ -329,17 +330,21 @@ describe('Polling commands', function() { statusAttributeMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v2/entities/Robot:r2d2/attrs?type=Robot', - utils.readExampleFile( - './test/unit/ngsiv2/examples/contextRequests/updateContextCommandStatus.json')) + .post( + '/v2/entities/Robot:r2d2/attrs?type=Robot', + utils.readExampleFile('./test/unit/ngsiv2/examples/contextRequests/updateContextCommandStatus.json') + ) .reply(204); statusAttributeMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v2/entities/Robot:r2d2/attrs?type=Robot', + .post( + '/v2/entities/Robot:r2d2/attrs?type=Robot', utils.readExampleFile( - './test/unit//ngsiv2/examples/contextRequests/updateContextCommandExpired.json')) + './test/unit//ngsiv2/examples/contextRequests/updateContextCommandExpired.json' + ) + ) .reply(204); iotAgentLib.register(device3, function(error) { diff --git a/test/unit/ngsiv2/ngsiService/active-devices-test.js b/test/unit/ngsiv2/ngsiService/active-devices-test.js index 291fb60b9..a7218e05d 100644 --- a/test/unit/ngsiv2/ngsiService/active-devices-test.js +++ b/test/unit/ngsiv2/ngsiService/active-devices-test.js @@ -22,106 +22,106 @@ * * Modified by: Daniel Calvo - ATOS Research & Innovation */ -'use strict'; - -var iotAgentLib = require('../../../../lib/fiware-iotagent-lib'), - utils = require('../../../tools/utils'), - timekeeper = require('timekeeper'), - should = require('should'), - logger = require('logops'), - nock = require('nock'), - contextBrokerMock, - iotAgentConfig = { - contextBroker: { - host: '192.168.1.1', - port: '1026', - ngsiVersion: 'v2' + +/* eslint-disable no-useless-concat */ + +const iotAgentLib = require('../../../../lib/fiware-iotagent-lib'); +const utils = require('../../../tools/utils'); +const timekeeper = require('timekeeper'); +const should = require('should'); +const logger = require('logops'); +const nock = require('nock'); +let contextBrokerMock; +const iotAgentConfig = { + contextBroker: { + host: '192.168.1.1', + port: '1026', + ngsiVersion: 'v2' + }, + server: { + port: 4041 + }, + types: { + Light: { + commands: [], + type: 'Light', + lazy: [ + { + name: 'temperature', + type: 'centigrades' + } + ], + active: [ + { + name: 'pressure', + type: 'Hgmm' + } + ] }, - server: { - port: 4041 + BrokenLight: { + commands: [], + lazy: [ + { + name: 'temperature', + type: 'centigrades' + } + ], + active: [ + { + name: 'pressure', + type: 'Hgmm' + } + ] }, - types: { - 'Light': { - commands: [], - type: 'Light', - lazy: [ - { - name: 'temperature', - type: 'centigrades' - } - ], - active: [ - { - name: 'pressure', - type: 'Hgmm' - } - ] - }, - 'BrokenLight': { - commands: [], - lazy: [ - { - name: 'temperature', - type: 'centigrades' - } - ], - active: [ - { - name: 'pressure', - type: 'Hgmm' - } - ] - }, - 'Termometer': { - type: 'Termometer', - commands: [], - lazy: [ - { - name: 'temp', - type: 'kelvin' - } - ], - active: [ - ] - }, - 'Humidity': { - type: 'Humidity', - cbHost: 'http://192.168.1.1:3024', - commands: [], - lazy: [], - active: [ - { - name: 'humidity', - type: 'percentage' - } - ] - }, - 'Motion': { - type: 'Motion', - commands: [], - lazy: [], - staticAttributes: [ - { - 'name': 'location', - 'type': 'geo:point', - 'value': '153,523' - } - ], - active: [ - { - name: 'humidity', - type: 'percentage' - } - ] - } + Termometer: { + type: 'Termometer', + commands: [], + lazy: [ + { + name: 'temp', + type: 'kelvin' + } + ], + active: [] + }, + Humidity: { + type: 'Humidity', + cbHost: 'http://192.168.1.1:3024', + commands: [], + lazy: [], + active: [ + { + name: 'humidity', + type: 'percentage' + } + ] }, - service: 'smartGondor', - subservice: 'gardens', - providerUrl: 'http://smartGondor.com' - }; + Motion: { + type: 'Motion', + commands: [], + lazy: [], + staticAttributes: [ + { + name: 'location', + type: 'geo:point', + value: '153,523' + } + ], + active: [ + { + name: 'humidity', + type: 'percentage' + } + ] + } + }, + service: 'smartGondor', + subservice: 'gardens', + providerUrl: 'http://smartGondor.com' +}; describe('Active attributes test', function() { - var values = [ + const values = [ { name: 'state', type: 'boolean', @@ -149,9 +149,11 @@ describe('Active attributes test', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v2/entities/light1/attrs', - utils.readExampleFile('./test/unit/ngsiv2/examples/contextRequests/updateContext.json')) - .query({type: 'Light'}) + .post( + '/v2/entities/light1/attrs', + utils.readExampleFile('./test/unit/ngsiv2/examples/contextRequests/updateContext.json') + ) + .query({ type: 'Light' }) .reply(204); iotAgentLib.activate(iotAgentConfig, done); @@ -167,10 +169,10 @@ describe('Active attributes test', function() { }); describe('When the IoT Agent receives new information and the timestamp flag is on', function() { - var modifiedValues; + let modifiedValues; beforeEach(function(done) { - var time = new Date(1438760101468); // 2015-08-05T07:35:01.468+00:00 + const time = new Date(1438760101468); // 2015-08-05T07:35:01.468+00:00 modifiedValues = [ { @@ -192,9 +194,11 @@ describe('Active attributes test', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v2/entities/light1/attrs', - utils.readExampleFile('./test/unit/ngsiv2/examples/contextRequests/updateContextTimestamp.json')) - .query({type: 'Light'}) + .post( + '/v2/entities/light1/attrs', + utils.readExampleFile('./test/unit/ngsiv2/examples/contextRequests/updateContextTimestamp.json') + ) + .query({ type: 'Light' }) .reply(204); iotAgentConfig.timestamp = true; @@ -218,10 +222,9 @@ describe('Active attributes test', function() { }); describe('When the IoTA gets a set of values with a TimeInstant which are not in ISO8601 format', function() { - var modifiedValues; + let modifiedValues; beforeEach(function(done) { - modifiedValues = [ { name: 'state', @@ -256,12 +259,11 @@ describe('Active attributes test', function() { }); }); - describe('When the IoTA gets a set of values with a TimeInstant which are in ISO8601 format ' + - 'without milis', function() { - var modifiedValues; + describe('When the IoTA gets a set of values with a TimeInstant which are in ISO8601 format without milis', function() { + let modifiedValues; beforeEach(function(done) { - var time = new Date(1666477342000); // 2022-10-22T22:22:22Z + const time = new Date(1666477342000); // 2022-10-22T22:22:22Z modifiedValues = [ { @@ -283,14 +285,17 @@ describe('Active attributes test', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v2/entities/light1/attrs', utils.readExampleFile( - './test/unit/ngsiv2/examples/contextRequests/updateContextTimestampOverrideWithoutMilis.json')) - .query({type: 'Light'}) + .post( + '/v2/entities/light1/attrs', + utils.readExampleFile( + './test/unit/ngsiv2/examples/contextRequests/updateContextTimestampOverrideWithoutMilis.json' + ) + ) + .query({ type: 'Light' }) .reply(204); iotAgentConfig.timestamp = true; iotAgentLib.activate(iotAgentConfig, done); - }); afterEach(function(done) { @@ -309,12 +314,11 @@ describe('Active attributes test', function() { }); }); - describe('When the IoT Agent receives new information, the timestamp flag is on' + - 'and timezone is defined', function() { - var modifiedValues; + describe('When the IoT Agent receives new information, the timestamp flag is on and timezone is defined', function() { + let modifiedValues; beforeEach(function(done) { - var time = new Date(1438760101468); // 2015-08-05T07:35:01.468+00:00 + const time = new Date(1438760101468); // 2015-08-05T07:35:01.468+00:00 modifiedValues = [ { @@ -336,10 +340,13 @@ describe('Active attributes test', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v2/entities/light1/attrs', - utils.readExampleFile('./test/unit/ngsiv2/examples/contextRequests/' + - 'updateContextTimestampTimezone.json')) - .query({type: 'Light'}) + .post( + '/v2/entities/light1/attrs', + utils.readExampleFile( + './test/unit/ngsiv2/examples/contextRequests/ updateContextTimestampTimezone.json' + ) + ) + .query({ type: 'Light' }) .reply(204); iotAgentConfig.timestamp = true; @@ -365,10 +372,10 @@ describe('Active attributes test', function() { }); describe('When the IoTA gets a set of values with a TimeInstant and the timestamp flag is on', function() { - var modifiedValues; + let modifiedValues; beforeEach(function(done) { - var time = new Date(1438760101468); // 2015-08-05T07:35:01.468+00:00 + const time = new Date(1438760101468); // 2015-08-05T07:35:01.468+00:00 modifiedValues = [ { @@ -390,9 +397,13 @@ describe('Active attributes test', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v2/entities/light1/attrs', utils.readExampleFile( - './test/unit/ngsiv2/examples/contextRequests/updateContextTimestampOverride.json')) - .query({type: 'Light'}) + .post( + '/v2/entities/light1/attrs', + utils.readExampleFile( + './test/unit/ngsiv2/examples/contextRequests/updateContextTimestampOverride.json' + ) + ) + .query({ type: 'Light' }) .reply(204); iotAgentConfig.timestamp = true; @@ -415,12 +426,11 @@ describe('Active attributes test', function() { }); }); - describe('When the IoTA gets a set of values with a TimeInstant, the timestamp flag is on' + - 'and timezone is defined', function() { - var modifiedValues; + describe('When the IoTA gets a set of values with a TimeInstant, the timestamp flag is on and timezone is defined', function() { + let modifiedValues; beforeEach(function(done) { - var time = new Date(1438760101468); // 2015-08-05T07:35:01.468+00:00 + const time = new Date(1438760101468); // 2015-08-05T07:35:01.468+00:00 modifiedValues = [ { @@ -442,9 +452,13 @@ describe('Active attributes test', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v2/entities/light1/attrs', utils.readExampleFile( - './test/unit/ngsiv2/examples/contextRequests/updateContextTimestampOverride.json')) - .query({type: 'Light'}) + .post( + '/v2/entities/light1/attrs', + utils.readExampleFile( + './test/unit/ngsiv2/examples/contextRequests/updateContextTimestampOverride.json' + ) + ) + .query({ type: 'Light' }) .reply(204); iotAgentConfig.timestamp = true; @@ -469,7 +483,7 @@ describe('Active attributes test', function() { }); }); - describe('When the IoT Agent receives information from a device whose type doesn\'t have a type name', function() { + describe("When the IoT Agent receives information from a device whose type doesn't have a type name", function() { beforeEach(function(done) { nock.cleanAll(); @@ -493,11 +507,15 @@ describe('Active attributes test', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v2/entities/light1/attrs', - utils.readExampleFile('./test/unit/ngsiv2/examples/contextRequests/updateContext.json')) - .query({type: 'Light'}) - .reply(413, - utils.readExampleFile('./test/unit/ngsiv2/examples/contextResponses/updateContext1Failed.json')); + .post( + '/v2/entities/light1/attrs', + utils.readExampleFile('./test/unit/ngsiv2/examples/contextRequests/updateContext.json') + ) + .query({ type: 'Light' }) + .reply( + 413, + utils.readExampleFile('./test/unit/ngsiv2/examples/contextResponses/updateContext1Failed.json') + ); iotAgentLib.activate(iotAgentConfig, done); }); @@ -522,11 +540,15 @@ describe('Active attributes test', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v2/entities/light1/attrs', - utils.readExampleFile('./test/unit/ngsiv2/examples/contextRequests/updateContext.json')) - .query({type: 'Light'}) - .reply(400, - utils.readExampleFile('./test/unit/ngsiv2/examples/contextResponses/updateContext2Failed.json')); + .post( + '/v2/entities/light1/attrs', + utils.readExampleFile('./test/unit/ngsiv2/examples/contextRequests/updateContext.json') + ) + .query({ type: 'Light' }) + .reply( + 400, + utils.readExampleFile('./test/unit/ngsiv2/examples/contextResponses/updateContext2Failed.json') + ); iotAgentLib.activate(iotAgentConfig, done); }); @@ -548,11 +570,15 @@ describe('Active attributes test', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v2/entities/light1/attrs', - utils.readExampleFile('./test/unit/ngsiv2/examples/contextRequests/updateContext.json')) - .query({type: 'Light'}) - .reply(500, - utils.readExampleFile('./test/unit/ngsiv2/examples/contextResponses/updateContext2Failed.json')); + .post( + '/v2/entities/light1/attrs', + utils.readExampleFile('./test/unit/ngsiv2/examples/contextRequests/updateContext.json') + ) + .query({ type: 'Light' }) + .reply( + 500, + utils.readExampleFile('./test/unit/ngsiv2/examples/contextResponses/updateContext2Failed.json') + ); iotAgentLib.activate(iotAgentConfig, done); }); @@ -577,9 +603,11 @@ describe('Active attributes test', function() { contextBrokerMock = nock('http://192.168.1.1:3024') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v2/entities/humSensor/attrs', - utils.readExampleFile('./test/unit/ngsiv2/examples/contextRequests/updateContext.json')) - .query({type: 'Humidity'}) + .post( + '/v2/entities/humSensor/attrs', + utils.readExampleFile('./test/unit/ngsiv2/examples/contextRequests/updateContext.json') + ) + .query({ type: 'Humidity' }) .reply(204); iotAgentLib.activate(iotAgentConfig, done); @@ -595,7 +623,7 @@ describe('Active attributes test', function() { }); describe('When an IoT Agent receives information for a type with static attributes', function() { - var newValues = [ + const newValues = [ { name: 'moving', type: 'boolean', @@ -609,9 +637,13 @@ describe('Active attributes test', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v2/entities/motion1/attrs', - utils.readExampleFile('./test/unit/ngsiv2/examples/contextRequests/updateContextStaticAttributes.json')) - .query({type: 'Motion'}) + .post( + '/v2/entities/motion1/attrs', + utils.readExampleFile( + './test/unit/ngsiv2/examples/contextRequests/updateContextStaticAttributes.json' + ) + ) + .query({ type: 'Motion' }) .reply(204); iotAgentLib.activate(iotAgentConfig, done); diff --git a/test/unit/ngsiv2/ngsiService/autocast-test.js b/test/unit/ngsiv2/ngsiService/autocast-test.js index 660a66da7..619152f11 100644 --- a/test/unit/ngsiv2/ngsiService/autocast-test.js +++ b/test/unit/ngsiv2/ngsiService/autocast-test.js @@ -22,64 +22,65 @@ * * Modified by: Daniel Calvo - ATOS Research & Innovation */ -'use strict'; - -var iotAgentLib = require('../../../../lib/fiware-iotagent-lib'), - utils = require('../../../tools/utils'), - should = require('should'), - logger = require('logops'), - nock = require('nock'), - contextBrokerMock, - iotAgentConfig = { - autocast: true, - contextBroker: { - host: '192.168.1.1', - port: '1026', - ngsiVersion: 'v2' - }, - server: { - port: 4041 - }, - types: { - 'Light': { - commands: [], - type: 'Light', - active: [ - { - name: 'pressure', - type: 'Number' - }, - { - name: 'temperature', - type: 'Number' - }, - { - name: 'id', - type: 'String' - }, - { - name: 'status', - type: 'Boolean' - }, - { - name: 'keep_alive', - type: 'None' - }, - { - name: 'tags', - type: 'Array' - }, - { - name: 'configuration', - type: 'Object' - } - ] - } - }, - service: 'smartGondor', - subservice: 'gardens', - providerUrl: 'http://smartGondor.com' - }; + +/* eslint-disable no-useless-concat */ + +const iotAgentLib = require('../../../../lib/fiware-iotagent-lib'); +const utils = require('../../../tools/utils'); +const should = require('should'); +const logger = require('logops'); +const nock = require('nock'); +let contextBrokerMock; +const iotAgentConfig = { + autocast: true, + contextBroker: { + host: '192.168.1.1', + port: '1026', + ngsiVersion: 'v2' + }, + server: { + port: 4041 + }, + types: { + Light: { + commands: [], + type: 'Light', + active: [ + { + name: 'pressure', + type: 'Number' + }, + { + name: 'temperature', + type: 'Number' + }, + { + name: 'id', + type: 'String' + }, + { + name: 'status', + type: 'Boolean' + }, + { + name: 'keep_alive', + type: 'None' + }, + { + name: 'tags', + type: 'Array' + }, + { + name: 'configuration', + type: 'Object' + } + ] + } + }, + service: 'smartGondor', + subservice: 'gardens', + providerUrl: 'http://smartGondor.com' +}; describe('JSON native types autocast test', function() { beforeEach(function() { @@ -90,10 +91,8 @@ describe('JSON native types autocast test', function() { iotAgentLib.deactivate(done); }); - describe('When the IoT Agent receives new information from a device.' + - 'Observation with Number type and Integer value', function() { - - var values = [ + describe('When the IoT Agent receives new information from a device. Observation with Number type and Integer value', function() { + const values = [ { name: 'pressure', type: 'Number', @@ -107,9 +106,11 @@ describe('JSON native types autocast test', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v2/entities/light1/attrs', - utils.readExampleFile('./test/unit/ngsiv2/examples/contextRequests/updateContextAutocast1.json')) - .query({type: 'Light'}) + .post( + '/v2/entities/light1/attrs', + utils.readExampleFile('./test/unit/ngsiv2/examples/contextRequests/updateContextAutocast1.json') + ) + .query({ type: 'Light' }) .reply(204); iotAgentLib.activate(iotAgentConfig, done); @@ -124,10 +125,8 @@ describe('JSON native types autocast test', function() { }); }); - describe('When the IoT Agent receives new information from a device.' + - 'Observation with Number type and Float value', function() { - - var values = [ + describe('When the IoT Agent receives new information from a device. Observation with Number type and Float value', function() { + const values = [ { name: 'temperature', type: 'Number', @@ -141,9 +140,11 @@ describe('JSON native types autocast test', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v2/entities/light1/attrs', - utils.readExampleFile('./test/unit/ngsiv2/examples/contextRequests/updateContextAutocast2.json')) - .query({type: 'Light'}) + .post( + '/v2/entities/light1/attrs', + utils.readExampleFile('./test/unit/ngsiv2/examples/contextRequests/updateContextAutocast2.json') + ) + .query({ type: 'Light' }) .reply(204); iotAgentLib.activate(iotAgentConfig, done); @@ -158,10 +159,8 @@ describe('JSON native types autocast test', function() { }); }); - describe('When the IoT Agent receives new information from a device.' + - 'Observation with Boolean type and True value', function() { - - var values = [ + describe('When the IoT Agent receives new information from a device. Observation with Boolean type and True value', function() { + const values = [ { name: 'status', type: 'Boolean', @@ -175,9 +174,11 @@ describe('JSON native types autocast test', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v2/entities/light1/attrs', - utils.readExampleFile('./test/unit/ngsiv2/examples/contextRequests/updateContextAutocast3.json')) - .query({type: 'Light'}) + .post( + '/v2/entities/light1/attrs', + utils.readExampleFile('./test/unit/ngsiv2/examples/contextRequests/updateContextAutocast3.json') + ) + .query({ type: 'Light' }) .reply(204); iotAgentLib.activate(iotAgentConfig, done); @@ -192,10 +193,8 @@ describe('JSON native types autocast test', function() { }); }); - describe('When the IoT Agent receives new information from a device.' + - 'Observation with Boolean type and False value', function() { - - var values = [ + describe('When the IoT Agent receives new information from a device. Observation with Boolean type and False value', function() { + const values = [ { name: 'status', type: 'Boolean', @@ -209,9 +208,11 @@ describe('JSON native types autocast test', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v2/entities/light1/attrs', - utils.readExampleFile('./test/unit/ngsiv2/examples/contextRequests/updateContextAutocast4.json')) - .query({type: 'Light'}) + .post( + '/v2/entities/light1/attrs', + utils.readExampleFile('./test/unit/ngsiv2/examples/contextRequests/updateContextAutocast4.json') + ) + .query({ type: 'Light' }) .reply(204); iotAgentLib.activate(iotAgentConfig, done); @@ -227,8 +228,7 @@ describe('JSON native types autocast test', function() { }); describe('When the IoT Agent receives new information from a device. Observation with None type', function() { - - var values = [ + const values = [ { name: 'keep_alive', type: 'None', @@ -242,9 +242,11 @@ describe('JSON native types autocast test', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v2/entities/light1/attrs', - utils.readExampleFile('./test/unit/ngsiv2/examples/contextRequests/updateContextAutocast5.json')) - .query({type: 'Light'}) + .post( + '/v2/entities/light1/attrs', + utils.readExampleFile('./test/unit/ngsiv2/examples/contextRequests/updateContextAutocast5.json') + ) + .query({ type: 'Light' }) .reply(204); iotAgentLib.activate(iotAgentConfig, done); @@ -260,8 +262,7 @@ describe('JSON native types autocast test', function() { }); describe('When the IoT Agent receives new information from a device. Observation with Array type', function() { - - var values = [ + const values = [ { name: 'tags', type: 'Array', @@ -275,9 +276,11 @@ describe('JSON native types autocast test', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v2/entities/light1/attrs', - utils.readExampleFile('./test/unit/ngsiv2/examples/contextRequests/updateContextAutocast6.json')) - .query({type: 'Light'}) + .post( + '/v2/entities/light1/attrs', + utils.readExampleFile('./test/unit/ngsiv2/examples/contextRequests/updateContextAutocast6.json') + ) + .query({ type: 'Light' }) .reply(204); iotAgentLib.activate(iotAgentConfig, done); @@ -293,8 +296,7 @@ describe('JSON native types autocast test', function() { }); describe('When the IoT Agent receives new information from a device. Observation with Object type', function() { - - var values = [ + const values = [ { name: 'configuration', type: 'Object', @@ -308,9 +310,11 @@ describe('JSON native types autocast test', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v2/entities/light1/attrs', - utils.readExampleFile('./test/unit/ngsiv2/examples/contextRequests/updateContextAutocast7.json')) - .query({type: 'Light'}) + .post( + '/v2/entities/light1/attrs', + utils.readExampleFile('./test/unit/ngsiv2/examples/contextRequests/updateContextAutocast7.json') + ) + .query({ type: 'Light' }) .reply(204); iotAgentLib.activate(iotAgentConfig, done); diff --git a/test/unit/ngsiv2/ngsiService/staticAttributes-test.js b/test/unit/ngsiv2/ngsiService/staticAttributes-test.js index 463308f05..7c86b33d4 100644 --- a/test/unit/ngsiv2/ngsiService/staticAttributes-test.js +++ b/test/unit/ngsiv2/ngsiService/staticAttributes-test.js @@ -22,68 +22,68 @@ * * Modified by: Daniel Calvo - ATOS Research & Innovation */ -'use strict'; -var iotAgentLib = require('../../../../lib/fiware-iotagent-lib'), - async = require('async'), - should = require('should'), - logger = require('logops'), - nock = require('nock'), - contextBrokerMock, - iotAgentConfig = { - contextBroker: { - host: '192.168.1.1', - port: '1026', - ngsiVersion: 'v2' - }, - server: { - port: 4041 - }, - types: { - 'Light': { - commands: [], - type: 'Light', - lazy: [ - { - name: 'temperature', - type: 'centigrades' - } - ], - active: [ - { - name: 'pressure', - type: 'Hgmm' - } - ], - staticAttributes: [ - { - name: 'attr1', - type: 'type1' - }, - { - name: 'attr2', - type: 'type2' - }, - { - name: 'attr3', - type: 'type3' - }, - { - name: 'attr4', - type: 'type4' - }, - ] - } - }, - timestamp: true, - service: 'smartGondor', - subservice: 'gardens', - providerUrl: 'http://smartGondor.com' - }; +/* eslint-disable no-unused-vars */ +const iotAgentLib = require('../../../../lib/fiware-iotagent-lib'); +const async = require('async'); +const should = require('should'); +const logger = require('logops'); +const nock = require('nock'); +let contextBrokerMock; +const iotAgentConfig = { + contextBroker: { + host: '192.168.1.1', + port: '1026', + ngsiVersion: 'v2' + }, + server: { + port: 4041 + }, + types: { + Light: { + commands: [], + type: 'Light', + lazy: [ + { + name: 'temperature', + type: 'centigrades' + } + ], + active: [ + { + name: 'pressure', + type: 'Hgmm' + } + ], + staticAttributes: [ + { + name: 'attr1', + type: 'type1' + }, + { + name: 'attr2', + type: 'type2' + }, + { + name: 'attr3', + type: 'type3' + }, + { + name: 'attr4', + type: 'type4' + } + ] + } + }, + timestamp: true, + service: 'smartGondor', + subservice: 'gardens', + providerUrl: 'http://smartGondor.com' +}; describe('Static attributes test', function() { - var values = [ + const values = [ { name: 'state', type: 'boolean', @@ -112,36 +112,39 @@ describe('Static attributes test', function() { .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') .post('/v2/entities/light1/attrs') - .query({type: 'Light'}) + .query({ type: 'Light' }) .times(4) .reply(204) .post('/v2/entities/light1/attrs', function(body) { - var metadatas = 0; - for (var i in body) { + let metadatas = 0; + for (const i in body) { if (body[i].metadata) { metadatas += Object.keys(body[i].metadata).length; } } return metadatas === Object.keys(body).length - 1; }) - .query({type: 'Light'}) + .query({ type: 'Light' }) .reply(204); iotAgentLib.activate(iotAgentConfig, done); }); it('should send a single TimeInstant per attribute', function(done) { - async.series([ - async.apply(iotAgentLib.update, 'light1', 'Light', '', values), - async.apply(iotAgentLib.update, 'light1', 'Light', '', values), - async.apply(iotAgentLib.update, 'light1', 'Light', '', values), - async.apply(iotAgentLib.update, 'light1', 'Light', '', values), - async.apply(iotAgentLib.update, 'light1', 'Light', '', values) - ], function(error, results) { - should.not.exist(error); - contextBrokerMock.done(); - done(); - }); + async.series( + [ + async.apply(iotAgentLib.update, 'light1', 'Light', '', values), + async.apply(iotAgentLib.update, 'light1', 'Light', '', values), + async.apply(iotAgentLib.update, 'light1', 'Light', '', values), + async.apply(iotAgentLib.update, 'light1', 'Light', '', values), + async.apply(iotAgentLib.update, 'light1', 'Light', '', values) + ], + function(error, results) { + should.not.exist(error); + contextBrokerMock.done(); + done(); + } + ); }); }); }); diff --git a/test/unit/ngsiv2/ngsiService/subscriptions-test.js b/test/unit/ngsiv2/ngsiService/subscriptions-test.js index 240506a7a..05e1ddbd9 100644 --- a/test/unit/ngsiv2/ngsiService/subscriptions-test.js +++ b/test/unit/ngsiv2/ngsiService/subscriptions-test.js @@ -22,33 +22,34 @@ * * Modified by: Daniel Calvo - ATOS Research & Innovation */ -'use strict'; - -var iotAgentLib = require('../../../../lib/fiware-iotagent-lib'), - utils = require('../../../tools/utils'), - should = require('should'), - request = require('request'), - nock = require('nock'), - contextBrokerMock, - iotAgentConfig = { - logLevel: 'FATAL', - contextBroker: { - host: '192.168.1.1', - port: '1026', - ngsiVersion: 'v2' - }, - server: { - port: 4041 - }, - types: {}, - service: 'smartGondor', - subservice: 'gardens', - providerUrl: 'http://smartGondor.com' - }; + +/* eslint-disable no-unused-vars */ + +const iotAgentLib = require('../../../../lib/fiware-iotagent-lib'); +const utils = require('../../../tools/utils'); +const should = require('should'); +const request = require('request'); +const nock = require('nock'); +let contextBrokerMock; +const iotAgentConfig = { + logLevel: 'FATAL', + contextBroker: { + host: '192.168.1.1', + port: '1026', + ngsiVersion: 'v2' + }, + server: { + port: 4041 + }, + types: {}, + service: 'smartGondor', + subservice: 'gardens', + providerUrl: 'http://smartGondor.com' +}; describe('Subscription tests', function() { beforeEach(function(done) { - var optionsProvision = { + const optionsProvision = { url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices', method: 'POST', json: utils.readExampleFile('./test/unit/examples/deviceProvisioningRequests/provisionMinimumDevice.json'), @@ -64,17 +65,24 @@ describe('Subscription tests', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', '/gardens') - .post('/v2/entities?options=upsert', - utils.readExampleFile('./test/unit/ngsiv2/examples/' + - 'contextRequests/createMinimumProvisionedDevice.json')) + .post( + '/v2/entities?options=upsert', + utils.readExampleFile( + './test/unit/ngsiv2/examples/contextRequests/createMinimumProvisionedDevice.json' + ) + ) .reply(204); contextBrokerMock .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', '/gardens') - .post('/v2/subscriptions', utils.readExampleFile('./test/unit/ngsiv2/examples' + - '/subscriptionRequests/simpleSubscriptionRequest.json')) - .reply(201, null, {'Location': '/v2/subscriptions/51c0ac9ed714fb3b37d7d5a8'}); + .post( + '/v2/subscriptions', + utils.readExampleFile( + './test/unit/ngsiv2/examples/subscriptionRequests/simpleSubscriptionRequest.json' + ) + ) + .reply(201, null, { Location: '/v2/subscriptions/51c0ac9ed714fb3b37d7d5a8' }); iotAgentLib.clearAll(function() { request(optionsProvision, function(error, result, body) { @@ -95,7 +103,6 @@ describe('Subscription tests', function() { describe('When a client invokes the subscribe() function for device', function() { it('should send the appropriate request to the Context Broker', function(done) { iotAgentLib.getDevice('MicroLight1', 'smartGondor', '/gardens', function(error, device) { - iotAgentLib.subscribe(device, ['attr_name'], null, function(error) { should.not.exist(error); @@ -136,7 +143,6 @@ describe('Subscription tests', function() { iotAgentLib.subscribe(device, ['attr_name'], null, function(error) { iotAgentLib.unsubscribe(device, '51c0ac9ed714fb3b37d7d5a8', function(error) { iotAgentLib.getDevice('MicroLight1', 'smartGondor', '/gardens', function(error, device) { - contextBrokerMock.done(); done(); }); @@ -192,18 +198,16 @@ describe('Subscription tests', function() { }); it('should invoke the user defined callback', function(done) { - var notificationOptions = { - url: 'http://localhost:' + iotAgentConfig.server.port + '/notify', - method: 'POST', - json: utils.readExampleFile('./test/unit/ngsiv2/examples/subscriptionRequests' + - '/simpleNotification.json'), - headers: { - 'fiware-service': 'smartGondor', - 'fiware-servicepath': '/gardens' - } - }, - - executedHandler = false; + const notificationOptions = { + url: 'http://localhost:' + iotAgentConfig.server.port + '/notify', + method: 'POST', + json: utils.readExampleFile('./test/unit/ngsiv2/examples/subscriptionRequests/simpleNotification.json'), + headers: { + 'fiware-service': 'smartGondor', + 'fiware-servicepath': '/gardens' + } + }; + let executedHandler = false; function mockedHandler(device, notification, callback) { executedHandler = true; @@ -220,19 +224,18 @@ describe('Subscription tests', function() { }); }); it('should invoke all the notification middlewares before the user defined callback', function(done) { - var notificationOptions = { - url: 'http://localhost:' + iotAgentConfig.server.port + '/notify', - method: 'POST', - json: utils.readExampleFile('./test/unit/ngsiv2/examples/subscriptionRequests' + - '/simpleNotification.json'), - headers: { - 'fiware-service': 'smartGondor', - 'fiware-servicepath': '/gardens' - } - }, - executedMiddlewares = false, - executedHandler = false, - modifiedData = false; + const notificationOptions = { + url: 'http://localhost:' + iotAgentConfig.server.port + '/notify', + method: 'POST', + json: utils.readExampleFile('./test/unit/ngsiv2/examples/subscriptionRequests/simpleNotification.json'), + headers: { + 'fiware-service': 'smartGondor', + 'fiware-servicepath': '/gardens' + } + }; + let executedMiddlewares = false; + let executedHandler = false; + let modifiedData = false; function mockedHandler(device, notification, callback) { executedHandler = true; @@ -263,21 +266,26 @@ describe('Subscription tests', function() { }); }); it('should get the correspondent device information', function(done) { - var notificationOptions = { - url: 'http://localhost:' + iotAgentConfig.server.port + '/notify', - method: 'POST', - json: utils.readExampleFile('./test/unit/ngsiv2/examples/subscriptionRequests/' + - 'simpleNotification.json'), - headers: { - 'fiware-service': 'smartGondor', - 'fiware-servicepath': '/gardens' - } - }, - rightFields = false; + const notificationOptions = { + url: 'http://localhost:' + iotAgentConfig.server.port + '/notify', + method: 'POST', + json: utils.readExampleFile('./test/unit/ngsiv2/examples/subscriptionRequests/simpleNotification.json'), + headers: { + 'fiware-service': 'smartGondor', + 'fiware-servicepath': '/gardens' + } + }; + let rightFields = false; function mockedHandler(device, data, callback) { - if (device && device.id === 'MicroLight1' && device.name === 'FirstMicroLight' && - data && data.length === 1 && data[0].name === 'attr_name') { + if ( + device && + device.id === 'MicroLight1' && + device.name === 'FirstMicroLight' && + data && + data.length === 1 && + data[0].name === 'attr_name' + ) { rightFields = true; } @@ -296,18 +304,16 @@ describe('Subscription tests', function() { }); describe('When a wrong notification arrives at the IOTA', function() { it('should not call the handler', function(done) { - var notificationOptions = { - url: 'http://localhost:' + iotAgentConfig.server.port + '/notify', - method: 'POST', - json: utils.readExampleFile('./test/unit/ngsiv2/examples/subscriptionRequests/' + - 'errorNotification.json'), - headers: { - 'fiware-service': 'smartGondor', - 'fiware-servicepath': '/gardens' - } - }, - - executedHandler = false; + const notificationOptions = { + url: 'http://localhost:' + iotAgentConfig.server.port + '/notify', + method: 'POST', + json: utils.readExampleFile('./test/unit/ngsiv2/examples/subscriptionRequests/errorNotification.json'), + headers: { + 'fiware-service': 'smartGondor', + 'fiware-servicepath': '/gardens' + } + }; + let executedHandler = false; function mockedHandler(device, notification, callback) { executedHandler = true; diff --git a/test/unit/ngsiv2/plugins/alias-plugin_test.js b/test/unit/ngsiv2/plugins/alias-plugin_test.js index d63d63b77..a858f2599 100644 --- a/test/unit/ngsiv2/plugins/alias-plugin_test.js +++ b/test/unit/ngsiv2/plugins/alias-plugin_test.js @@ -22,90 +22,87 @@ * * Modified by: Daniel Calvo - ATOS Research & Innovation */ -'use strict'; - -/* jshint camelcase: false */ - -var iotAgentLib = require('../../../../lib/fiware-iotagent-lib'), - utils = require('../../../tools/utils'), - should = require('should'), - logger = require('logops'), - nock = require('nock'), - contextBrokerMock, - iotAgentConfig = { - autocast: true, - contextBroker: { - host: '192.168.1.1', - port: '1026', - ngsiVersion: 'v2' - }, - server: { - port: 4041 - }, - types: { - 'Light': { - commands: [], - type: 'Light', - lazy: [ - { - object_id: 't', - name: 'temperature', - type: 'centigrades' - } - ], - active: [ - { - object_id: 'p', - name: 'pressure', - type: 'Hgmm' - }, - { - object_id: 'l', - name: 'luminance', - type: 'lumens' - }, - { - object_id: 'ut', - name: 'unix_timestamp', - type: 'Number' - }, - { - object_id: 'ap', - name: 'active_power', - type: 'Number' - }, - { - object_id: 'ap', - name: 'active_power', - type: 'Number' - }, - { - object_id: 's', - name: 'status', - type: 'Boolean' - }, - { - object_id: 'al', - name: 'keep_alive', - type: 'None' - }, - { - object_id: 'ta', - name: 'tags', - type: 'Array' - }, - { - object_id: 'c', - name: 'configuration', - type: 'Object' - } - ] - } - }, - service: 'smartGondor', - subservice: 'gardens', - providerUrl: 'http://smartGondor.com' - }; + +const iotAgentLib = require('../../../../lib/fiware-iotagent-lib'); +const utils = require('../../../tools/utils'); +const should = require('should'); +const logger = require('logops'); +const nock = require('nock'); +let contextBrokerMock; +const iotAgentConfig = { + autocast: true, + contextBroker: { + host: '192.168.1.1', + port: '1026', + ngsiVersion: 'v2' + }, + server: { + port: 4041 + }, + types: { + Light: { + commands: [], + type: 'Light', + lazy: [ + { + object_id: 't', + name: 'temperature', + type: 'centigrades' + } + ], + active: [ + { + object_id: 'p', + name: 'pressure', + type: 'Hgmm' + }, + { + object_id: 'l', + name: 'luminance', + type: 'lumens' + }, + { + object_id: 'ut', + name: 'unix_timestamp', + type: 'Number' + }, + { + object_id: 'ap', + name: 'active_power', + type: 'Number' + }, + { + object_id: 'ap', + name: 'active_power', + type: 'Number' + }, + { + object_id: 's', + name: 'status', + type: 'Boolean' + }, + { + object_id: 'al', + name: 'keep_alive', + type: 'None' + }, + { + object_id: 'ta', + name: 'tags', + type: 'Array' + }, + { + object_id: 'c', + name: 'configuration', + type: 'Object' + } + ] + } + }, + service: 'smartGondor', + subservice: 'gardens', + providerUrl: 'http://smartGondor.com' +}; describe('Attribute alias plugin', function() { beforeEach(function(done) { @@ -126,7 +123,7 @@ describe('Attribute alias plugin', function() { }); }); describe('When an update comes for attributes with aliases', function() { - var values = [ + const values = [ { name: 't', type: 'centigrades', @@ -145,14 +142,15 @@ describe('Attribute alias plugin', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v2/entities/light1/attrs', utils.readExampleFile( - './test/unit/ngsiv2/examples/contextRequests/updateContextAliasPlugin1.json')) - .query({type: 'Light'}) + .post( + '/v2/entities/light1/attrs', + utils.readExampleFile('./test/unit/ngsiv2/examples/contextRequests/updateContextAliasPlugin1.json') + ) + .query({ type: 'Light' }) .reply(204); }); - it('should rename the attributes as expected by the alias mappings' + - 'and cast values to JSON native types', function(done) { + it('should rename the attributes as expected by the alias mappings and cast values to JSON native types', function(done) { iotAgentLib.update('light1', 'Light', '', values, function(error) { should.not.exist(error); contextBrokerMock.done(); @@ -161,7 +159,7 @@ describe('Attribute alias plugin', function() { }); }); describe('When an update comes for attributes with aliases and a different type', function() { - var values = [ + const values = [ { name: 'l', type: 'lums', @@ -175,14 +173,15 @@ describe('Attribute alias plugin', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v2/entities/light1/attrs', utils.readExampleFile( - './test/unit/ngsiv2/examples/contextRequests/updateContextAliasPlugin2.json')) - .query({type: 'Light'}) + .post( + '/v2/entities/light1/attrs', + utils.readExampleFile('./test/unit/ngsiv2/examples/contextRequests/updateContextAliasPlugin2.json') + ) + .query({ type: 'Light' }) .reply(204); }); - it('should rename the attributes as expected by the alias mappings' + - 'and cast values to JSON native types', function(done) { + it('should rename the attributes as expected by the alias mappings and cast values to JSON native types', function(done) { iotAgentLib.update('light1', 'Light', '', values, function(error) { should.not.exist(error); contextBrokerMock.done(); @@ -191,7 +190,7 @@ describe('Attribute alias plugin', function() { }); }); describe('When an update comes for attributes with aliases and integer type', function() { - var values = [ + const values = [ { name: 'ut', type: 'Number', @@ -205,9 +204,11 @@ describe('Attribute alias plugin', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v2/entities/light1/attrs', utils.readExampleFile( - './test/unit/ngsiv2/examples/contextRequests/updateContextAliasPlugin3.json')) - .query({type: 'Light'}) + .post( + '/v2/entities/light1/attrs', + utils.readExampleFile('./test/unit/ngsiv2/examples/contextRequests/updateContextAliasPlugin3.json') + ) + .query({ type: 'Light' }) .reply(204); }); @@ -221,7 +222,7 @@ describe('Attribute alias plugin', function() { }); describe('When an update comes for attributes with aliases and integer type.', function() { - var values = [ + const values = [ { name: 'ut', type: 'Number', @@ -235,14 +236,15 @@ describe('Attribute alias plugin', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v2/entities/light1/attrs', utils.readExampleFile( - './test/unit/ngsiv2/examples/contextRequests/updateContextAliasPlugin3.json')) - .query({type: 'Light'}) + .post( + '/v2/entities/light1/attrs', + utils.readExampleFile('./test/unit/ngsiv2/examples/contextRequests/updateContextAliasPlugin3.json') + ) + .query({ type: 'Light' }) .reply(204); }); - it('should rename the attributes as expected by the alias mappings' + - 'and cast values to JSON native types', function(done) { + it('should rename the attributes as expected by the alias mappings and cast values to JSON native types', function(done) { iotAgentLib.update('light1', 'Light', '', values, function(error) { should.not.exist(error); contextBrokerMock.done(); @@ -252,7 +254,7 @@ describe('Attribute alias plugin', function() { }); describe('When an update comes for attributes with aliases and float type', function() { - var values = [ + const values = [ { name: 'ap', type: 'Number', @@ -266,14 +268,15 @@ describe('Attribute alias plugin', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v2/entities/light1/attrs', utils.readExampleFile( - './test/unit/ngsiv2/examples/contextRequests/updateContextAliasPlugin4.json')) - .query({type: 'Light'}) + .post( + '/v2/entities/light1/attrs', + utils.readExampleFile('./test/unit/ngsiv2/examples/contextRequests/updateContextAliasPlugin4.json') + ) + .query({ type: 'Light' }) .reply(204); }); - it('should rename the attributes as expected by the alias mappings' + - 'and cast values to JSON native types', function(done) { + it('should rename the attributes as expected by the alias mappings and cast values to JSON native types', function(done) { iotAgentLib.update('light1', 'Light', '', values, function(error) { should.not.exist(error); contextBrokerMock.done(); @@ -283,7 +286,7 @@ describe('Attribute alias plugin', function() { }); describe('When an update comes for attributes with aliases and boolean type', function() { - var values = [ + const values = [ { name: 's', type: 'Boolean', @@ -297,14 +300,15 @@ describe('Attribute alias plugin', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v2/entities/light1/attrs', utils.readExampleFile( - './test/unit/ngsiv2/examples/contextRequests/updateContextAliasPlugin5.json')) - .query({type: 'Light'}) + .post( + '/v2/entities/light1/attrs', + utils.readExampleFile('./test/unit/ngsiv2/examples/contextRequests/updateContextAliasPlugin5.json') + ) + .query({ type: 'Light' }) .reply(204); }); - it('should rename the attributes as expected by the alias mappings' + - 'and cast values to JSON native types', function(done) { + it('should rename the attributes as expected by the alias mappings and cast values to JSON native types', function(done) { iotAgentLib.update('light1', 'Light', '', values, function(error) { should.not.exist(error); contextBrokerMock.done(); @@ -314,7 +318,7 @@ describe('Attribute alias plugin', function() { }); describe('When an update comes for attributes with aliases and None type', function() { - var values = [ + const values = [ { name: 'al', type: 'None', @@ -328,14 +332,15 @@ describe('Attribute alias plugin', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v2/entities/light1/attrs', utils.readExampleFile( - './test/unit/ngsiv2/examples/contextRequests/updateContextAliasPlugin6.json')) - .query({type: 'Light'}) + .post( + '/v2/entities/light1/attrs', + utils.readExampleFile('./test/unit/ngsiv2/examples/contextRequests/updateContextAliasPlugin6.json') + ) + .query({ type: 'Light' }) .reply(204); }); - it('should rename the attributes as expected by the alias mappings' + - 'and cast values to JSON native types', function(done) { + it('should rename the attributes as expected by the alias mappings and cast values to JSON native types', function(done) { iotAgentLib.update('light1', 'Light', '', values, function(error) { should.not.exist(error); contextBrokerMock.done(); @@ -345,7 +350,7 @@ describe('Attribute alias plugin', function() { }); describe('When an update comes for attributes with aliases and Array type', function() { - var values = [ + const values = [ { name: 'ta', type: 'Array', @@ -359,14 +364,15 @@ describe('Attribute alias plugin', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v2/entities/light1/attrs', utils.readExampleFile( - './test/unit/ngsiv2/examples/contextRequests/updateContextAliasPlugin7.json')) - .query({type: 'Light'}) + .post( + '/v2/entities/light1/attrs', + utils.readExampleFile('./test/unit/ngsiv2/examples/contextRequests/updateContextAliasPlugin7.json') + ) + .query({ type: 'Light' }) .reply(204); }); - it('should rename the attributes as expected by the alias mappings' + - 'and cast values to JSON native types', function(done) { + it('should rename the attributes as expected by the alias mappings and cast values to JSON native types', function(done) { iotAgentLib.update('light1', 'Light', '', values, function(error) { should.not.exist(error); contextBrokerMock.done(); @@ -376,7 +382,7 @@ describe('Attribute alias plugin', function() { }); describe('When an update comes for attributes with aliases and Object type', function() { - var values = [ + const values = [ { name: 'c', type: 'Object', @@ -390,14 +396,15 @@ describe('Attribute alias plugin', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v2/entities/light1/attrs', utils.readExampleFile( - './test/unit/ngsiv2/examples/contextRequests/updateContextAliasPlugin8.json')) - .query({type: 'Light'}) + .post( + '/v2/entities/light1/attrs', + utils.readExampleFile('./test/unit/ngsiv2/examples/contextRequests/updateContextAliasPlugin8.json') + ) + .query({ type: 'Light' }) .reply(204); }); - it('should rename the attributes as expected by the alias mappings' + - 'and cast values to JSON native types', function(done) { + it('should rename the attributes as expected by the alias mappings and cast values to JSON native types', function(done) { iotAgentLib.update('light1', 'Light', '', values, function(error) { should.not.exist(error); contextBrokerMock.done(); @@ -406,9 +413,8 @@ describe('Attribute alias plugin', function() { }); }); - describe('When an update comes for attributes with aliases and Object type, but value is String', function() { - var values = [ + const values = [ { name: 'c', type: 'Object', @@ -422,14 +428,15 @@ describe('Attribute alias plugin', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v2/entities/light1/attrs', utils.readExampleFile( - './test/unit/ngsiv2/examples/contextRequests/updateContextAliasPlugin9.json')) - .query({type: 'Light'}) + .post( + '/v2/entities/light1/attrs', + utils.readExampleFile('./test/unit/ngsiv2/examples/contextRequests/updateContextAliasPlugin9.json') + ) + .query({ type: 'Light' }) .reply(204); }); - it('should rename the attributes as expected by the alias mappings' + - 'and cast values to JSON native types', function(done) { + it('should rename the attributes as expected by the alias mappings and cast values to JSON native types', function(done) { iotAgentLib.update('light1', 'Light', '', values, function(error) { should.not.exist(error); contextBrokerMock.done(); diff --git a/test/unit/ngsiv2/plugins/bidirectional-plugin_test.js b/test/unit/ngsiv2/plugins/bidirectional-plugin_test.js index e6c368ee6..eb55dbc50 100644 --- a/test/unit/ngsiv2/plugins/bidirectional-plugin_test.js +++ b/test/unit/ngsiv2/plugins/bidirectional-plugin_test.js @@ -23,37 +23,37 @@ * Modified by: Daniel Calvo - ATOS Research & Innovation */ -'use strict'; - -var iotAgentLib = require('../../../../lib/fiware-iotagent-lib'), - utils = require('../../../tools/utils'), - should = require('should'), - logger = require('logops'), - nock = require('nock'), - request = require('request'), - contextBrokerMock, - iotAgentConfig = { - contextBroker: { - host: '192.168.1.1', - port: '1026', - ngsiVersion: 'v2' - }, - server: { - port: 4041 - }, - types: { - }, - service: 'smartGondor', - subservice: 'gardens', - providerUrl: 'http://smartGondor.com' - }; +/* eslint-disable no-unused-vars */ + +const iotAgentLib = require('../../../../lib/fiware-iotagent-lib'); +const utils = require('../../../tools/utils'); +const should = require('should'); +const logger = require('logops'); +const nock = require('nock'); +const request = require('request'); +let contextBrokerMock; +const iotAgentConfig = { + contextBroker: { + host: '192.168.1.1', + port: '1026', + ngsiVersion: 'v2' + }, + server: { + port: 4041 + }, + types: {}, + service: 'smartGondor', + subservice: 'gardens', + providerUrl: 'http://smartGondor.com' +}; describe('Bidirectional data plugin', function() { - var options = { + const options = { url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices', method: 'POST', - json: - utils.readExampleFile('./test/unit/examples/deviceProvisioningRequests/provisionBidirectionalDevice.json'), + json: utils.readExampleFile( + './test/unit/examples/deviceProvisioningRequests/provisionBidirectionalDevice.json' + ), headers: { 'fiware-service': 'smartGondor', 'fiware-servicepath': '/gardens' @@ -65,12 +65,11 @@ describe('Bidirectional data plugin', function() { iotAgentLib.activate(iotAgentConfig, function() { iotAgentLib.clearAll(function() { - iotAgentLib.addDeviceProvisionMiddleware( - iotAgentLib.dataPlugins.bidirectionalData.deviceProvision); + iotAgentLib.addDeviceProvisionMiddleware(iotAgentLib.dataPlugins.bidirectionalData.deviceProvision); iotAgentLib.addConfigurationProvisionMiddleware( - iotAgentLib.dataPlugins.bidirectionalData.groupProvision); - iotAgentLib.addNotificationMiddleware( - iotAgentLib.dataPlugins.bidirectionalData.notification); + iotAgentLib.dataPlugins.bidirectionalData.groupProvision + ); + iotAgentLib.addNotificationMiddleware(iotAgentLib.dataPlugins.bidirectionalData.notification); done(); }); }); @@ -87,17 +86,22 @@ describe('Bidirectional data plugin', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', '/gardens') - .post('/v2/subscriptions', utils.readExampleFile( - './test/unit/ngsiv2/examples/subscriptionRequests/bidirectionalSubscriptionRequest.json')) - .reply(201, null, {'Location': '/v2/subscriptions/51c0ac9ed714fb3b37d7d5a8'}); + .post( + '/v2/subscriptions', + utils.readExampleFile( + './test/unit/ngsiv2/examples/subscriptionRequests/bidirectionalSubscriptionRequest.json' + ) + ) + .reply(201, null, { Location: '/v2/subscriptions/51c0ac9ed714fb3b37d7d5a8' }); contextBrokerMock .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', '/gardens') - .post('/v2/entities?options=upsert', utils.readExampleFile( - './test/unit/ngsiv2/examples/contextRequests/createBidirectionalDevice.json')) + .post( + '/v2/entities?options=upsert', + utils.readExampleFile('./test/unit/ngsiv2/examples/contextRequests/createBidirectionalDevice.json') + ) .reply(204); - }); it('should subscribe to the modification of the combined attribute with all the variables', function(done) { @@ -110,7 +114,7 @@ describe('Bidirectional data plugin', function() { }); describe('When a device with bidirectionality subscriptions is removed', function() { - var deleteRequest = { + const deleteRequest = { url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices/Light1', method: 'DELETE', headers: { @@ -123,15 +127,21 @@ describe('Bidirectional data plugin', function() { contextBrokerMock .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', '/gardens') - .post('/v2/subscriptions', utils.readExampleFile( - './test/unit/ngsiv2/examples/subscriptionRequests/bidirectionalSubscriptionRequest.json')) - .reply(201, null, {'Location': '/v2/subscriptions/51c0ac9ed714fb3b37d7d5a8'}); + .post( + '/v2/subscriptions', + utils.readExampleFile( + './test/unit/ngsiv2/examples/subscriptionRequests/bidirectionalSubscriptionRequest.json' + ) + ) + .reply(201, null, { Location: '/v2/subscriptions/51c0ac9ed714fb3b37d7d5a8' }); contextBrokerMock .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', '/gardens') - .post('/v2/entities?options=upsert', utils.readExampleFile( - './test/unit/ngsiv2/examples/contextRequests/createBidirectionalDevice.json')) + .post( + '/v2/entities?options=upsert', + utils.readExampleFile('./test/unit/ngsiv2/examples/contextRequests/createBidirectionalDevice.json') + ) .reply(204); contextBrokerMock @@ -153,31 +163,38 @@ describe('Bidirectional data plugin', function() { }); describe('When a notification arrives for a bidirectional attribute', function() { - var notificationOptions = { - url: 'http://localhost:' + iotAgentConfig.server.port + '/notify', - method: 'POST', - json: utils.readExampleFile('./test/unit/ngsiv2/examples/subscriptionRequests/' + - 'bidirectionalNotification.json'), - headers: { - 'fiware-service': 'smartGondor', - 'fiware-servicepath': '/gardens' - } - }, - executedHandler = false; + const notificationOptions = { + url: 'http://localhost:' + iotAgentConfig.server.port + '/notify', + method: 'POST', + json: utils.readExampleFile( + './test/unit/ngsiv2/examples/subscriptionRequests/bidirectionalNotification.json' + ), + headers: { + 'fiware-service': 'smartGondor', + 'fiware-servicepath': '/gardens' + } + }; + let executedHandler = false; beforeEach(function() { contextBrokerMock .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', '/gardens') - .post('/v2/subscriptions', utils.readExampleFile( - './test/unit/ngsiv2/examples/subscriptionRequests/bidirectionalSubscriptionRequest.json')) - .reply(201, null, {'Location': '/v2/subscriptions/51c0ac9ed714fb3b37d7d5a8'}); + .post( + '/v2/subscriptions', + utils.readExampleFile( + './test/unit/ngsiv2/examples/subscriptionRequests/bidirectionalSubscriptionRequest.json' + ) + ) + .reply(201, null, { Location: '/v2/subscriptions/51c0ac9ed714fb3b37d7d5a8' }); contextBrokerMock .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', '/gardens') - .post('/v2/entities?options=upsert', utils.readExampleFile( - './test/unit/ngsiv2/examples/contextRequests/createBidirectionalDevice.json')) + .post( + '/v2/entities?options=upsert', + utils.readExampleFile('./test/unit/ngsiv2/examples/contextRequests/createBidirectionalDevice.json') + ) .reply(204); }); @@ -220,13 +237,13 @@ describe('Bidirectional data plugin', function() { }); it('should return the transformed values', function(done) { - var transformedHandler = false; + let transformedHandler = false; function mockedHandler(device, values, callback) { - var latitudeFound = false, - longitudeFound = false; + let latitudeFound = false; + let longitudeFound = false; - for (var i = 0; i < values.length; i++) { + for (let i = 0; i < values.length; i++) { if (values[i].name === 'latitude' && values[i].type === 'string' && values[i].value === '-9.6') { latitudeFound = true; } @@ -236,7 +253,7 @@ describe('Bidirectional data plugin', function() { } } - transformedHandler = (values.length >= 2 && longitudeFound && latitudeFound); + transformedHandler = values.length >= 2 && longitudeFound && latitudeFound; callback(); } @@ -253,42 +270,47 @@ describe('Bidirectional data plugin', function() { }); describe('When a new Group provisioning request arrives with bidirectional attributes', function() { - var provisionGroup = { - url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/services', - method: 'POST', - json: - utils.readExampleFile('./test/unit/examples/groupProvisioningRequests/bidirectionalGroup.json'), - headers: { - 'fiware-service': 'smartGondor', - 'fiware-servicepath': '/gardens' - } - }, - provisionDevice = { - url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices', - method: 'POST', - json: utils.readExampleFile( - './test/unit/examples/deviceProvisioningRequests/provisionDeviceBidirectionalGroup.json'), - headers: { - 'fiware-service': 'smartGondor', - 'fiware-servicepath': '/gardens' - } - }; + const provisionGroup = { + url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/services', + method: 'POST', + json: utils.readExampleFile('./test/unit/examples/groupProvisioningRequests/bidirectionalGroup.json'), + headers: { + 'fiware-service': 'smartGondor', + 'fiware-servicepath': '/gardens' + } + }; + const provisionDevice = { + url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices', + method: 'POST', + json: utils.readExampleFile( + './test/unit/examples/deviceProvisioningRequests/provisionDeviceBidirectionalGroup.json' + ), + headers: { + 'fiware-service': 'smartGondor', + 'fiware-servicepath': '/gardens' + } + }; beforeEach(function() { contextBrokerMock .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', '/gardens') - .post('/v2/subscriptions', utils.readExampleFile( - './test/unit/ngsiv2/examples/subscriptionRequests/bidirectionalSubscriptionRequest.json')) - .reply(201, null, {'Location': '/v2/subscriptions/51c0ac9ed714fb3b37d7d5a8'}); + .post( + '/v2/subscriptions', + utils.readExampleFile( + './test/unit/ngsiv2/examples/subscriptionRequests/bidirectionalSubscriptionRequest.json' + ) + ) + .reply(201, null, { Location: '/v2/subscriptions/51c0ac9ed714fb3b37d7d5a8' }); contextBrokerMock .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', '/gardens') - .post('/v2/entities?options=upsert', utils.readExampleFile( - './test/unit/ngsiv2/examples/contextRequests/createBidirectionalDevice.json')) + .post( + '/v2/entities?options=upsert', + utils.readExampleFile('./test/unit/ngsiv2/examples/contextRequests/createBidirectionalDevice.json') + ) .reply(204); - }); it('should subscribe to the modification of the combined attribute with all the variables', function(done) { request(provisionGroup, function(error, response, body) { @@ -302,50 +324,57 @@ describe('Bidirectional data plugin', function() { }); describe('When a notification arrives for a bidirectional attribute in a Configuration Group', function() { - var provisionGroup = { - url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/services', - method: 'POST', - json: - utils.readExampleFile('./test/unit/examples/groupProvisioningRequests/bidirectionalGroup.json'), - headers: { - 'fiware-service': 'smartGondor', - 'fiware-servicepath': '/gardens' - } - }, - notificationOptions = { - url: 'http://localhost:' + iotAgentConfig.server.port + '/notify', - method: 'POST', - json: utils.readExampleFile('./test/unit/ngsiv2/examples/subscriptionRequests/' + - 'bidirectionalNotification.json'), - headers: { - 'fiware-service': 'smartGondor', - 'fiware-servicepath': '/gardens' - } - }, - provisionDevice = { - url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices', - method: 'POST', - json: utils.readExampleFile( - './test/unit/examples/deviceProvisioningRequests/provisionDeviceBidirectionalGroup.json'), - headers: { - 'fiware-service': 'smartGondor', - 'fiware-servicepath': '/gardens' - } - }; + const provisionGroup = { + url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/services', + method: 'POST', + json: utils.readExampleFile('./test/unit/examples/groupProvisioningRequests/bidirectionalGroup.json'), + headers: { + 'fiware-service': 'smartGondor', + 'fiware-servicepath': '/gardens' + } + }; + const notificationOptions = { + url: 'http://localhost:' + iotAgentConfig.server.port + '/notify', + method: 'POST', + json: utils.readExampleFile( + './test/unit/ngsiv2/examples/subscriptionRequests/bidirectionalNotification.json' + ), + headers: { + 'fiware-service': 'smartGondor', + 'fiware-servicepath': '/gardens' + } + }; + const provisionDevice = { + url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices', + method: 'POST', + json: utils.readExampleFile( + './test/unit/examples/deviceProvisioningRequests/provisionDeviceBidirectionalGroup.json' + ), + headers: { + 'fiware-service': 'smartGondor', + 'fiware-servicepath': '/gardens' + } + }; beforeEach(function() { contextBrokerMock .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', '/gardens') - .post('/v2/subscriptions', utils.readExampleFile( - './test/unit/ngsiv2/examples/subscriptionRequests/bidirectionalSubscriptionRequest.json')) - .reply(201, null, {'Location': '/v2/subscriptions/51c0ac9ed714fb3b37d7d5a8'}); + .post( + '/v2/subscriptions', + utils.readExampleFile( + './test/unit/ngsiv2/examples/subscriptionRequests/bidirectionalSubscriptionRequest.json' + ) + ) + .reply(201, null, { Location: '/v2/subscriptions/51c0ac9ed714fb3b37d7d5a8' }); contextBrokerMock .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', '/gardens') - .post('/v2/entities?options=upsert', utils.readExampleFile( - './test/unit/ngsiv2/examples/contextRequests/createBidirectionalDevice.json')) + .post( + '/v2/entities?options=upsert', + utils.readExampleFile('./test/unit/ngsiv2/examples/contextRequests/createBidirectionalDevice.json') + ) .reply(204); }); @@ -354,13 +383,13 @@ describe('Bidirectional data plugin', function() { }); it('should return the transformed values', function(done) { - var transformedHandler = false; + let transformedHandler = false; function mockedHandler(device, values, callback) { - var latitudeFound = false, - longitudeFound = false; + let latitudeFound = false; + let longitudeFound = false; - for (var i = 0; i < values.length; i++) { + for (let i = 0; i < values.length; i++) { if (values[i].name === 'latitude' && values[i].type === 'string' && values[i].value === '-9.6') { latitudeFound = true; } @@ -370,7 +399,7 @@ describe('Bidirectional data plugin', function() { } } - transformedHandler = (values.length >= 2 && longitudeFound && latitudeFound); + transformedHandler = values.length >= 2 && longitudeFound && latitudeFound; callback(); } @@ -389,11 +418,12 @@ describe('Bidirectional data plugin', function() { }); describe('Bidirectional data plugin and CB is defined using environment variables', function() { - var options = { + const options = { url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices', method: 'POST', - json: - utils.readExampleFile('./test/unit/examples/deviceProvisioningRequests/provisionBidirectionalDevice.json'), + json: utils.readExampleFile( + './test/unit/examples/deviceProvisioningRequests/provisionBidirectionalDevice.json' + ), headers: { 'fiware-service': 'smartGondor', 'fiware-servicepath': '/gardens' @@ -405,12 +435,11 @@ describe('Bidirectional data plugin and CB is defined using environment variable process.env.IOTA_CB_HOST = 'cbhost'; iotAgentLib.activate(iotAgentConfig, function() { iotAgentLib.clearAll(function() { - iotAgentLib.addDeviceProvisionMiddleware( - iotAgentLib.dataPlugins.bidirectionalData.deviceProvision); + iotAgentLib.addDeviceProvisionMiddleware(iotAgentLib.dataPlugins.bidirectionalData.deviceProvision); iotAgentLib.addConfigurationProvisionMiddleware( - iotAgentLib.dataPlugins.bidirectionalData.groupProvision); - iotAgentLib.addNotificationMiddleware( - iotAgentLib.dataPlugins.bidirectionalData.notification); + iotAgentLib.dataPlugins.bidirectionalData.groupProvision + ); + iotAgentLib.addNotificationMiddleware(iotAgentLib.dataPlugins.bidirectionalData.notification); done(); }); }); @@ -428,17 +457,22 @@ describe('Bidirectional data plugin and CB is defined using environment variable contextBrokerMock = nock('http://cbhost:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', '/gardens') - .post('/v2/subscriptions', utils.readExampleFile( - './test/unit/ngsiv2/examples/subscriptionRequests/bidirectionalSubscriptionRequest.json')) - .reply(201, null, {'Location': '/v2/subscriptions/51c0ac9ed714fb3b37d7d5a8'}); + .post( + '/v2/subscriptions', + utils.readExampleFile( + './test/unit/ngsiv2/examples/subscriptionRequests/bidirectionalSubscriptionRequest.json' + ) + ) + .reply(201, null, { Location: '/v2/subscriptions/51c0ac9ed714fb3b37d7d5a8' }); contextBrokerMock .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', '/gardens') - .post('/v2/entities?options=upsert', utils.readExampleFile( - './test/unit/ngsiv2/examples/contextRequests/createBidirectionalDevice.json')) + .post( + '/v2/entities?options=upsert', + utils.readExampleFile('./test/unit/ngsiv2/examples/contextRequests/createBidirectionalDevice.json') + ) .reply(204); - }); it('should subscribe to the modification of the combined attribute with all the variables', function(done) { @@ -449,5 +483,4 @@ describe('Bidirectional data plugin and CB is defined using environment variable }); }); }); - }); diff --git a/test/unit/ngsiv2/plugins/compress-timestamp-plugin_test.js b/test/unit/ngsiv2/plugins/compress-timestamp-plugin_test.js index 078e4777b..eaacf4727 100644 --- a/test/unit/ngsiv2/plugins/compress-timestamp-plugin_test.js +++ b/test/unit/ngsiv2/plugins/compress-timestamp-plugin_test.js @@ -23,102 +23,99 @@ * Modified by: Daniel Calvo - ATOS Research & Innovation */ -'use strict'; - -var iotAgentLib = require('../../../../lib/fiware-iotagent-lib'), - utils = require('../../../tools/utils'), - should = require('should'), - logger = require('logops'), - nock = require('nock'), - contextBrokerMock, - iotAgentConfig = { - contextBroker: { - host: '192.168.1.1', - port: '1026', - ngsiVersion: 'v2' +const iotAgentLib = require('../../../../lib/fiware-iotagent-lib'); +const utils = require('../../../tools/utils'); +const should = require('should'); +const logger = require('logops'); +const nock = require('nock'); +let contextBrokerMock; +const iotAgentConfig = { + contextBroker: { + host: '192.168.1.1', + port: '1026', + ngsiVersion: 'v2' + }, + server: { + port: 4041 + }, + types: { + Light: { + commands: [], + type: 'Light', + lazy: [ + { + name: 'temperature', + type: 'centigrades' + } + ], + active: [ + { + name: 'pressure', + type: 'Hgmm' + } + ] }, - server: { - port: 4041 + BrokenLight: { + commands: [], + lazy: [ + { + name: 'temperature', + type: 'centigrades' + } + ], + active: [ + { + name: 'pressure', + type: 'Hgmm' + } + ] }, - types: { - 'Light': { - commands: [], - type: 'Light', - lazy: [ - { - name: 'temperature', - type: 'centigrades' - } - ], - active: [ - { - name: 'pressure', - type: 'Hgmm' - } - ] - }, - 'BrokenLight': { - commands: [], - lazy: [ - { - name: 'temperature', - type: 'centigrades' - } - ], - active: [ - { - name: 'pressure', - type: 'Hgmm' - } - ] - }, - 'Termometer': { - type: 'Termometer', - commands: [], - lazy: [ - { - name: 'temp', - type: 'kelvin' - } - ], - active: [ - ] - }, - 'Humidity': { - type: 'Humidity', - cbHost: 'http://192.168.1.1:3024', - commands: [], - lazy: [], - active: [ - { - name: 'humidity', - type: 'percentage' - } - ] - }, - 'Motion': { - type: 'Motion', - commands: [], - lazy: [], - staticAttributes: [ - { - 'name': 'location', - 'type': 'Vector', - 'value': '(123,523)' - } - ], - active: [ - { - name: 'humidity', - type: 'percentage' - } - ] - } + Termometer: { + type: 'Termometer', + commands: [], + lazy: [ + { + name: 'temp', + type: 'kelvin' + } + ], + active: [] }, - service: 'smartGondor', - subservice: 'gardens', - providerUrl: 'http://smartGondor.com' - }; + Humidity: { + type: 'Humidity', + cbHost: 'http://192.168.1.1:3024', + commands: [], + lazy: [], + active: [ + { + name: 'humidity', + type: 'percentage' + } + ] + }, + Motion: { + type: 'Motion', + commands: [], + lazy: [], + staticAttributes: [ + { + name: 'location', + type: 'Vector', + value: '(123,523)' + } + ], + active: [ + { + name: 'humidity', + type: 'percentage' + } + ] + } + }, + service: 'smartGondor', + subservice: 'gardens', + providerUrl: 'http://smartGondor.com' +}; describe('Timestamp compression plugin', function() { beforeEach(function(done) { @@ -138,7 +135,7 @@ describe('Timestamp compression plugin', function() { }); }); describe('When an update comes with a timestamp through the plugin', function() { - var values = [ + const values = [ { name: 'state', type: 'Boolean', @@ -157,9 +154,13 @@ describe('Timestamp compression plugin', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v2/entities/light1/attrs', utils.readExampleFile( - './test/unit/ngsiv2/examples/contextRequests/updateContextCompressTimestamp1.json')) - .query({type: 'Light'}) + .post( + '/v2/entities/light1/attrs', + utils.readExampleFile( + './test/unit/ngsiv2/examples/contextRequests/updateContextCompressTimestamp1.json' + ) + ) + .query({ type: 'Light' }) .reply(204); }); @@ -173,7 +174,7 @@ describe('Timestamp compression plugin', function() { }); describe('When an update comes with a timestamp through the plugin with metadata', function() { - var values = [ + const values = [ { name: 'state', type: 'Boolean', @@ -199,9 +200,13 @@ describe('Timestamp compression plugin', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v2/entities/light1/attrs', utils.readExampleFile( - './test/unit/ngsiv2/examples/contextRequests/updateContextCompressTimestamp2.json')) - .query({type: 'Light'}) + .post( + '/v2/entities/light1/attrs', + utils.readExampleFile( + './test/unit/ngsiv2/examples/contextRequests/updateContextCompressTimestamp2.json' + ) + ) + .query({ type: 'Light' }) .reply(204); }); @@ -215,10 +220,7 @@ describe('Timestamp compression plugin', function() { }); describe('When a query comes for a timestamp through the plugin', function() { - var values = [ - 'state', - 'TheTargetValue' - ]; + const values = ['state', 'TheTargetValue']; beforeEach(function() { nock.cleanAll(); @@ -227,8 +229,12 @@ describe('Timestamp compression plugin', function() { .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') .get('/v2/entities/light1/attrs?attrs=state,TheTargetValue&type=Light') - .reply(200, utils.readExampleFile( - './test/unit/ngsiv2/examples/contextResponses/queryContextCompressTimestamp1Success.json')); + .reply( + 200, + utils.readExampleFile( + './test/unit/ngsiv2/examples/contextResponses/queryContextCompressTimestamp1Success.json' + ) + ); }); it('should return an entity with all its timestamps without separators (basic format)', function(done) { @@ -242,5 +248,4 @@ describe('Timestamp compression plugin', function() { }); }); }); - }); diff --git a/test/unit/ngsiv2/plugins/event-plugin_test.js b/test/unit/ngsiv2/plugins/event-plugin_test.js index 6a64963e4..fc5e89ee8 100644 --- a/test/unit/ngsiv2/plugins/event-plugin_test.js +++ b/test/unit/ngsiv2/plugins/event-plugin_test.js @@ -23,44 +23,42 @@ * Modified by: Daniel Calvo - ATOS Research & Innovation */ -'use strict'; - -var iotAgentLib = require('../../../../lib/fiware-iotagent-lib'), - should = require('should'), - logger = require('logops'), - nock = require('nock'), - contextBrokerMock, - iotAgentConfig = { - contextBroker: { - host: '192.168.1.1', - port: '1026', - ngsiVersion: 'v2' - }, - server: { - port: 4041 - }, - types: { - 'Light': { - commands: [], - type: 'Light', - lazy: [ - { - name: 'temperature', - type: 'centigrades' - } - ], - active: [ - { - name: 'pressure', - type: 'Hgmm' - } - ] - } - }, - service: 'smartGondor', - subservice: 'gardens', - providerUrl: 'http://smartGondor.com' - }; +const iotAgentLib = require('../../../../lib/fiware-iotagent-lib'); +const should = require('should'); +const logger = require('logops'); +const nock = require('nock'); +let contextBrokerMock; +const iotAgentConfig = { + contextBroker: { + host: '192.168.1.1', + port: '1026', + ngsiVersion: 'v2' + }, + server: { + port: 4041 + }, + types: { + Light: { + commands: [], + type: 'Light', + lazy: [ + { + name: 'temperature', + type: 'centigrades' + } + ], + active: [ + { + name: 'pressure', + type: 'Hgmm' + } + ] + } + }, + service: 'smartGondor', + subservice: 'gardens', + providerUrl: 'http://smartGondor.com' +}; describe('Event plugin', function() { beforeEach(function(done) { @@ -81,7 +79,7 @@ describe('Event plugin', function() { }); }); describe('When an update comes with an event to the plugin', function() { - var values = [ + const values = [ { name: 'state', type: 'Boolean', @@ -101,11 +99,11 @@ describe('Event plugin', function() { .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') .post('/v2/entities/light1/attrs', function(body) { - var dateRegex = /\d{4}-\d\d-\d\dT\d\d:\d\d:\d\d.\d{3}Z/; + const dateRegex = /\d{4}-\d\d-\d\dT\d\d:\d\d:\d\d.\d{3}Z/; return body.activation.value.match(dateRegex); }) - .query({type: 'Light'}) + .query({ type: 'Light' }) .reply(204); }); diff --git a/test/unit/ngsiv2/plugins/multientity-plugin_test.js b/test/unit/ngsiv2/plugins/multientity-plugin_test.js index ff3701f2f..262574caf 100644 --- a/test/unit/ngsiv2/plugins/multientity-plugin_test.js +++ b/test/unit/ngsiv2/plugins/multientity-plugin_test.js @@ -22,182 +22,179 @@ * * Modified by: Daniel Calvo - ATOS Research & Innovation */ -'use strict'; - -/* jshint camelcase: false */ - -var iotAgentLib = require('../../../../lib/fiware-iotagent-lib'), - utils = require('../../../tools/utils'), - should = require('should'), - logger = require('logops'), - nock = require('nock'), - moment = require('moment'), - timekeeper = require('timekeeper'), - contextBrokerMock, - iotAgentConfig = { - contextBroker: { - host: '192.168.1.1', - port: '1026', - ngsiVersion: 'v2' + +/* eslint-disable no-useless-concat */ + +const iotAgentLib = require('../../../../lib/fiware-iotagent-lib'); +const utils = require('../../../tools/utils'); +const should = require('should'); +const logger = require('logops'); +const nock = require('nock'); +const moment = require('moment'); +const timekeeper = require('timekeeper'); +let contextBrokerMock; +const iotAgentConfig = { + contextBroker: { + host: '192.168.1.1', + port: '1026', + ngsiVersion: 'v2' + }, + server: { + port: 4041 + }, + types: { + WeatherStation: { + commands: [], + type: 'WeatherStation', + lazy: [], + active: [ + { + object_id: 'p', + name: 'pressure', + type: 'Hgmm' + }, + { + object_id: 'h', + name: 'humidity', + type: 'Percentage', + entity_name: 'Higro2000', + entity_type: 'Higrometer' + } + ] }, - server: { - port: 4041 + WeatherStation2: { + commands: [], + type: 'WeatherStation', + lazy: [], + active: [ + { + object_id: 'p', + name: 'pressure', + type: 'Hgmm' + }, + { + object_id: 'h', + name: 'humidity', + type: 'Percentage', + entity_name: 'Higro2000' + } + ] }, - types: { - 'WeatherStation': { - commands: [], - type: 'WeatherStation', - lazy: [], - active: [ - { - object_id: 'p', - name: 'pressure', - type: 'Hgmm' - }, - { - object_id: 'h', - name: 'humidity', - type: 'Percentage', - entity_name: 'Higro2000', - entity_type: 'Higrometer' - } - ] - }, - 'WeatherStation2': { - commands: [], - type: 'WeatherStation', - lazy: [], - active: [ - { - object_id: 'p', - name: 'pressure', - type: 'Hgmm' - }, - { - object_id: 'h', - name: 'humidity', - type: 'Percentage', - entity_name: 'Higro2000', - } - ] - }, - 'WeatherStation3': { - commands: [], - type: 'WeatherStation', - lazy: [], - active: [ - { - object_id: 'p', - name: 'pressure', - type: 'Hgmm' - }, - { - object_id: 'h', - name: 'humidity', - type: 'Percentage', - entity_name: 'Station Number ${@sn * 10}', - } - ] - }, - 'WeatherStation5': { - commands: [], - type: 'WeatherStation', - lazy: [], - active: [ - { - object_id: 'p', - name: 'pressure', - type: 'Hgmm' - }, - { - object_id: 'h', - name: 'pressure', - type: 'Hgmm', - entity_name: 'Higro2000', - entity_type: 'Higrometer' - } - ] - }, - 'WeatherStation6': { - commands: [], - type: 'WeatherStation', - lazy: [], - active: [ - { - object_id: 'p', - name: 'pressure', - type: 'Hgmm', - entity_name: 'Higro2002', - entity_type: 'Higrometer' - }, - { - object_id: 'h', - name: 'pressure', - type: 'Hgmm', - entity_name: 'Higro2000', - entity_type: 'Higrometer' - } - ] - }, - 'Sensor001': { - commands: [], - type: 'Sensor', - lazy: [], - active: [ - { - type : 'number', - name : 'vol', - object_id : 'cont1', - entity_name : 'SO1', - entity_type : 'WM' - }, - { - type : 'number', - name : 'vol', - object_id : 'cont2', - entity_name : 'SO2', - entity_type : 'WM' - }, - { - type : 'number', - name : 'vol', - object_id : 'cont3', - entity_name : 'SO3', - entity_type : 'WM' - }, - { - type : 'number', - name : 'vol', - object_id : 'cont4', - entity_name : 'SO4', - entity_type : 'WM' - }, - { - type : 'number', - name : 'vol', - object_id : 'cont5', - entity_name : 'SO5', - entity_type : 'WM' - } - ] - - }, - 'SensorCommand':{ - commands: [ - { - name: 'PING', - type: 'command' - } - ], - type: 'SensorCommand', - lazy: [] - } - + WeatherStation3: { + commands: [], + type: 'WeatherStation', + lazy: [], + active: [ + { + object_id: 'p', + name: 'pressure', + type: 'Hgmm' + }, + { + object_id: 'h', + name: 'humidity', + type: 'Percentage', + entity_name: 'Station Number ${@sn * 10}' + } + ] + }, + WeatherStation5: { + commands: [], + type: 'WeatherStation', + lazy: [], + active: [ + { + object_id: 'p', + name: 'pressure', + type: 'Hgmm' + }, + { + object_id: 'h', + name: 'pressure', + type: 'Hgmm', + entity_name: 'Higro2000', + entity_type: 'Higrometer' + } + ] + }, + WeatherStation6: { + commands: [], + type: 'WeatherStation', + lazy: [], + active: [ + { + object_id: 'p', + name: 'pressure', + type: 'Hgmm', + entity_name: 'Higro2002', + entity_type: 'Higrometer' + }, + { + object_id: 'h', + name: 'pressure', + type: 'Hgmm', + entity_name: 'Higro2000', + entity_type: 'Higrometer' + } + ] }, - service: 'smartGondor', - subservice: 'gardens', - providerUrl: 'http://smartGondor.com' - }; + Sensor001: { + commands: [], + type: 'Sensor', + lazy: [], + active: [ + { + type: 'number', + name: 'vol', + object_id: 'cont1', + entity_name: 'SO1', + entity_type: 'WM' + }, + { + type: 'number', + name: 'vol', + object_id: 'cont2', + entity_name: 'SO2', + entity_type: 'WM' + }, + { + type: 'number', + name: 'vol', + object_id: 'cont3', + entity_name: 'SO3', + entity_type: 'WM' + }, + { + type: 'number', + name: 'vol', + object_id: 'cont4', + entity_name: 'SO4', + entity_type: 'WM' + }, + { + type: 'number', + name: 'vol', + object_id: 'cont5', + entity_name: 'SO5', + entity_type: 'WM' + } + ] + }, + SensorCommand: { + commands: [ + { + name: 'PING', + type: 'command' + } + ], + type: 'SensorCommand', + lazy: [] + } + }, + service: 'smartGondor', + subservice: 'gardens', + providerUrl: 'http://smartGondor.com' +}; describe('Multi-entity plugin', function() { beforeEach(function(done) { @@ -220,7 +217,7 @@ describe('Multi-entity plugin', function() { }); describe('When an update comes for a multientity measurement', function() { - var values = [ + const values = [ { name: 'p', type: 'centigrades', @@ -239,8 +236,12 @@ describe('Multi-entity plugin', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v2/op/update', utils.readExampleFile( - './test/unit/ngsiv2/examples/contextRequests/updateContextMultientityPlugin1.json')) + .post( + '/v2/op/update', + utils.readExampleFile( + './test/unit/ngsiv2/examples/contextRequests/updateContextMultientityPlugin1.json' + ) + ) .reply(204); }); @@ -254,7 +255,7 @@ describe('Multi-entity plugin', function() { }); describe('When an update comes for a multientity measurement with same attribute name', function() { - var values = [ + const values = [ { name: 'h', type: 'Hgmm', @@ -268,8 +269,12 @@ describe('Multi-entity plugin', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v2/op/update', utils.readExampleFile( - './test/unit/ngsiv2/examples/contextRequests/updateContextMultientityPlugin4.json')) + .post( + '/v2/op/update', + utils.readExampleFile( + './test/unit/ngsiv2/examples/contextRequests/updateContextMultientityPlugin4.json' + ) + ) .reply(204); }); @@ -283,7 +288,7 @@ describe('Multi-entity plugin', function() { }); describe('When an update comes for a multientity multi measurement with same attribute name', function() { - var values = [ + const values = [ { name: 'h', type: 'Hgmm', @@ -302,8 +307,12 @@ describe('Multi-entity plugin', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v2/op/update', utils.readExampleFile( - './test/unit/ngsiv2/examples/contextRequests/updateContextMultientityPlugin5.json')) + .post( + '/v2/op/update', + utils.readExampleFile( + './test/unit/ngsiv2/examples/contextRequests/updateContextMultientityPlugin5.json' + ) + ) .reply(204); }); @@ -316,9 +325,8 @@ describe('Multi-entity plugin', function() { }); }); - describe('When an update comes for a multientity defined with an expression', function() { - var values = [ + const values = [ { name: 'p', type: 'centigrades', @@ -342,8 +350,12 @@ describe('Multi-entity plugin', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v2/op/update', utils.readExampleFile( - './test/unit/ngsiv2/examples/contextRequests/updateContextMultientityPlugin3.json')) + .post( + '/v2/op/update', + utils.readExampleFile( + './test/unit/ngsiv2/examples/contextRequests/updateContextMultientityPlugin3.json' + ) + ) .reply(204); }); @@ -357,7 +369,7 @@ describe('Multi-entity plugin', function() { }); describe('When an update comes for a multientity measurement without type for one entity', function() { - var values = [ + const values = [ { name: 'p', type: 'centigrades', @@ -376,8 +388,12 @@ describe('Multi-entity plugin', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v2/op/update', utils.readExampleFile( - './test/unit/ngsiv2/examples/contextRequests/updateContextMultientityPlugin2.json')) + .post( + '/v2/op/update', + utils.readExampleFile( + './test/unit/ngsiv2/examples/contextRequests/updateContextMultientityPlugin2.json' + ) + ) .reply(204); }); @@ -390,81 +406,94 @@ describe('Multi-entity plugin', function() { }); }); - describe('When an update comes for a multientity measurement and there are attributes with' + - ' the same name but different alias and mapped to different CB entities', function() { - var values = [ - { - name: 'cont1', - type: 'number', - value: '38' - } - ]; - - beforeEach(function() { - nock.cleanAll(); - - contextBrokerMock = nock('http://192.168.1.1:1026') - .matchHeader('fiware-service', 'smartGondor') - .matchHeader('fiware-servicepath', 'gardens') - .post('/v2/op/update', utils.readExampleFile( - './test/unit/ngsiv2/examples/contextRequests/updateContextMultientityPlugin6.json')) - .reply(204); - }); + describe( + 'When an update comes for a multientity measurement and there are attributes with' + + ' the same name but different alias and mapped to different CB entities', + function() { + const values = [ + { + name: 'cont1', + type: 'number', + value: '38' + } + ]; - it('should update only the appropriate CB entity', function(done) { - iotAgentLib.update('Sensor', 'Sensor001', '', values, function(error) { - should.not.exist(error); - contextBrokerMock.done(); - done(); + beforeEach(function() { + nock.cleanAll(); + + contextBrokerMock = nock('http://192.168.1.1:1026') + .matchHeader('fiware-service', 'smartGondor') + .matchHeader('fiware-servicepath', 'gardens') + .post( + '/v2/op/update', + utils.readExampleFile( + './test/unit/ngsiv2/examples/contextRequests/updateContextMultientityPlugin6.json' + ) + ) + .reply(204); }); - }); - }); - - describe('When an update comes for a multientity multi measurement and there are attributes with' + - ' the same name but different alias and mapped to different CB entities', function() { - var values = [ - { - name: 'cont1', - type: 'number', - value: '38' - }, - { - name: 'cont2', - type: 'number', - value: '39' - }, - { - name: 'cont3', - type: 'number', - value: '40' - }, - { - name: 'cont5', - type: 'number', - value: '42' - } - ]; - beforeEach(function() { - nock.cleanAll(); + it('should update only the appropriate CB entity', function(done) { + iotAgentLib.update('Sensor', 'Sensor001', '', values, function(error) { + should.not.exist(error); + contextBrokerMock.done(); + done(); + }); + }); + } + ); + + describe( + 'When an update comes for a multientity multi measurement and there are attributes with' + + ' the same name but different alias and mapped to different CB entities', + function() { + const values = [ + { + name: 'cont1', + type: 'number', + value: '38' + }, + { + name: 'cont2', + type: 'number', + value: '39' + }, + { + name: 'cont3', + type: 'number', + value: '40' + }, + { + name: 'cont5', + type: 'number', + value: '42' + } + ]; - contextBrokerMock = nock('http://192.168.1.1:1026') - .matchHeader('fiware-service', 'smartGondor') - .matchHeader('fiware-servicepath', 'gardens') - .post('/v2/op/update', utils.readExampleFile( - './test/unit/ngsiv2/examples/contextRequests/updateContextMultientityPlugin7.json')) - .reply(204); - }); + beforeEach(function() { + nock.cleanAll(); + + contextBrokerMock = nock('http://192.168.1.1:1026') + .matchHeader('fiware-service', 'smartGondor') + .matchHeader('fiware-servicepath', 'gardens') + .post( + '/v2/op/update', + utils.readExampleFile( + './test/unit/ngsiv2/examples/contextRequests/updateContextMultientityPlugin7.json' + ) + ) + .reply(204); + }); - it('should update only the appropriate CB entity', function(done) { - iotAgentLib.update('Sensor', 'Sensor001', '', values, function(error) { - should.not.exist(error); - contextBrokerMock.done(); - done(); + it('should update only the appropriate CB entity', function(done) { + iotAgentLib.update('Sensor', 'Sensor001', '', values, function(error) { + should.not.exist(error); + contextBrokerMock.done(); + done(); + }); }); - }); - }); - + } + ); }); describe('Multi-entity plugin is executed before timestamp process plugin', function() { @@ -490,7 +519,7 @@ describe('Multi-entity plugin is executed before timestamp process plugin', func }); describe('When an update comes for a multientity measurement and timestamp is enabled in config file', function() { - var values = [ + const values = [ { name: 'p', type: 'centigrades', @@ -508,7 +537,7 @@ describe('Multi-entity plugin is executed before timestamp process plugin', func } ]; - var singleValue = [ + const singleValue = [ { name: 'h', type: 'Percentage', @@ -521,36 +550,32 @@ describe('Multi-entity plugin is executed before timestamp process plugin', func }); it('should send two context elements, one for each entity', function(done) { - contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') .post('/v2/op/update', function(body) { - var expectedBody = utils.readExampleFile('./test/unit/ngsiv2/examples' + - '/contextRequests/updateContextMultientityTimestampPlugin1.json'); + const expectedBody = utils.readExampleFile( + './test/unit/ngsiv2/examples/contextRequests/updateContextMultientityTimestampPlugin1.json' + ); // Note that TimeInstant fields are not included in the json used by this mock as they are dynamic // fields. The following code just checks that TimeInstant fields are present. - if (!body.entities[1].TimeInstant || !body.entities[1].humidity.metadata.TimeInstant) - { + if (!body.entities[1].TimeInstant || !body.entities[1].humidity.metadata.TimeInstant) { return false; } - else { - var timeInstantEntity = body.entities[1].TimeInstant; - var timeInstantAtt = body.entities[1].humidity.metadata.TimeInstant; - if (moment(timeInstantEntity, 'YYYY-MM-DDTHH:mm:ss.SSSZ').isValid && - moment(timeInstantAtt, 'YYYY-MM-DDTHH:mm:ss.SSSZ').isValid) { - - delete body.entities[1].TimeInstant; - delete body.entities[1].humidity.metadata.TimeInstant; - - delete expectedBody.entities[1].TimeInstant; - delete expectedBody.entities[1].humidity.metadata.TimeInstant; - return JSON.stringify(body) === JSON.stringify(expectedBody); - - } else { - return false; - } + const timeInstantEntity = body.entities[1].TimeInstant; + const timeInstantAtt = body.entities[1].humidity.metadata.TimeInstant; + if ( + moment(timeInstantEntity, 'YYYY-MM-DDTHH:mm:ss.SSSZ').isValid && + moment(timeInstantAtt, 'YYYY-MM-DDTHH:mm:ss.SSSZ').isValid + ) { + delete body.entities[1].TimeInstant; + delete body.entities[1].humidity.metadata.TimeInstant; + + delete expectedBody.entities[1].TimeInstant; + delete expectedBody.entities[1].humidity.metadata.TimeInstant; + return JSON.stringify(body) === JSON.stringify(expectedBody); } + return false; }) .reply(204); @@ -566,32 +591,28 @@ describe('Multi-entity plugin is executed before timestamp process plugin', func .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') .post('/v2/op/update', function(body) { - var expectedBody = utils.readExampleFile('./test/unit/ngsiv2/examples' + - '/contextRequests/updateContextMultientityTimestampPlugin2.json'); + const expectedBody = utils.readExampleFile( + './test/unit/ngsiv2/examples/contextRequests/updateContextMultientityTimestampPlugin2.json' + ); // Note that TimeInstant fields are not included in the json used by this mock as they are dynamic // fields. The following code just checks that TimeInstant fields are present. - if (!body.entities[1].TimeInstant || - !body.entities[1].humidity.metadata.TimeInstant) - { + if (!body.entities[1].TimeInstant || !body.entities[1].humidity.metadata.TimeInstant) { return false; } - else { - var timeInstantEntity2 = body.entities[1].TimeInstant; - var timeInstantAtt = body.entities[1].humidity.metadata.TimeInstant; - if (moment(timeInstantEntity2, 'YYYY-MM-DDTHH:mm:ss.SSSZ').isValid && - moment(timeInstantAtt, 'YYYY-MM-DDTHH:mm:ss.SSSZ').isValid) { - - delete body.entities[1].TimeInstant; - delete body.entities[1].humidity.metadata.TimeInstant; - - delete expectedBody.entities[1].TimeInstant; - delete expectedBody.entities[1].humidity.metadata.TimeInstant; - return JSON.stringify(body) === JSON.stringify(expectedBody); - - } else { - return false; - } + const timeInstantEntity2 = body.entities[1].TimeInstant; + const timeInstantAtt = body.entities[1].humidity.metadata.TimeInstant; + if ( + moment(timeInstantEntity2, 'YYYY-MM-DDTHH:mm:ss.SSSZ').isValid && + moment(timeInstantAtt, 'YYYY-MM-DDTHH:mm:ss.SSSZ').isValid + ) { + delete body.entities[1].TimeInstant; + delete body.entities[1].humidity.metadata.TimeInstant; + + delete expectedBody.entities[1].TimeInstant; + delete expectedBody.entities[1].humidity.metadata.TimeInstant; + return JSON.stringify(body) === JSON.stringify(expectedBody); } + return false; }) .reply(204); @@ -606,11 +627,15 @@ describe('Multi-entity plugin is executed before timestamp process plugin', func contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v2/op/update', utils.readExampleFile('./test/unit/ngsiv2/examples' + - '/contextRequests/updateContextMultientityTimestampPlugin3.json')) + .post( + '/v2/op/update', + utils.readExampleFile( + './test/unit/ngsiv2/examples/contextRequests/updateContextMultientityTimestampPlugin3.json' + ) + ) .reply(204); - var tsValue = [ + const tsValue = [ { name: 'h', type: 'Percentage', @@ -633,12 +658,12 @@ describe('Multi-entity plugin is executed before timestamp process plugin', func }); }); -describe('Multi-entity plugin is executed for a command update for a regular entity ', function () { +describe('Multi-entity plugin is executed for a command update for a regular entity ', function() { beforeEach(function(done) { logger.setLevel('FATAL'); iotAgentConfig.timestamp = true; - var time = new Date(1438760101468); // 2015-08-05T07:35:01.468+00:00 + const time = new Date(1438760101468); // 2015-08-05T07:35:01.468+00:00 timekeeper.freeze(time); iotAgentLib.activate(iotAgentConfig, function() { iotAgentLib.clearAll(function() { @@ -659,23 +684,26 @@ describe('Multi-entity plugin is executed for a command update for a regular ent }); it('Should send the update to the context broker', function(done) { - contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v2/op/update', utils.readExampleFile('./test/unit/ngsiv2/examples' + - '/contextRequests/updateContextMultientityTimestampPlugin4.json')) + .post( + '/v2/op/update', + utils.readExampleFile( + './test/unit/ngsiv2/examples/contextRequests/updateContextMultientityTimestampPlugin4.json' + ) + ) .reply(204); - var commands = [ + const commands = [ { name: 'PING_status', type: 'commandStatus', - value: 'OK', + value: 'OK' }, { name: 'PING_info', type: 'commandResult', - value:'1234567890' + value: '1234567890' } ]; @@ -685,4 +713,4 @@ describe('Multi-entity plugin is executed for a command update for a regular ent done(); }); }); -}); \ No newline at end of file +}); diff --git a/test/unit/ngsiv2/plugins/timestamp-processing-plugin_test.js b/test/unit/ngsiv2/plugins/timestamp-processing-plugin_test.js index 5727a6e1f..88885a610 100644 --- a/test/unit/ngsiv2/plugins/timestamp-processing-plugin_test.js +++ b/test/unit/ngsiv2/plugins/timestamp-processing-plugin_test.js @@ -23,45 +23,43 @@ * Modified by: Daniel Calvo - ATOS Research & Innovation */ -'use strict'; - -var iotAgentLib = require('../../../../lib/fiware-iotagent-lib'), - utils = require('../../../tools/utils'), - should = require('should'), - logger = require('logops'), - nock = require('nock'), - contextBrokerMock, - iotAgentConfig = { - contextBroker: { - host: '192.168.1.1', - port: '1026', - ngsiVersion: 'v2' - }, - server: { - port: 4041 - }, - types: { - 'Light': { - commands: [], - type: 'Light', - lazy: [ - { - name: 'temperature', - type: 'centigrades' - } - ], - active: [ - { - name: 'pressure', - type: 'Hgmm' - } - ] - } - }, - service: 'smartGondor', - subservice: 'gardens', - providerUrl: 'http://smartGondor.com' - }; +const iotAgentLib = require('../../../../lib/fiware-iotagent-lib'); +const utils = require('../../../tools/utils'); +const should = require('should'); +const logger = require('logops'); +const nock = require('nock'); +let contextBrokerMock; +const iotAgentConfig = { + contextBroker: { + host: '192.168.1.1', + port: '1026', + ngsiVersion: 'v2' + }, + server: { + port: 4041 + }, + types: { + Light: { + commands: [], + type: 'Light', + lazy: [ + { + name: 'temperature', + type: 'centigrades' + } + ], + active: [ + { + name: 'pressure', + type: 'Hgmm' + } + ] + } + }, + service: 'smartGondor', + subservice: 'gardens', + providerUrl: 'http://smartGondor.com' +}; describe('Timestamp processing plugin', function() { beforeEach(function(done) { @@ -81,7 +79,7 @@ describe('Timestamp processing plugin', function() { }); }); describe('When an update comes with a timestamp through the plugin', function() { - var values = [ + const values = [ { name: 'state', type: 'Boolean', @@ -100,9 +98,13 @@ describe('Timestamp processing plugin', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v2/entities/light1/attrs', utils.readExampleFile( - './test/unit/ngsiv2/examples/contextRequests/updateContextProcessTimestamp.json')) - .query({type: 'Light'}) + .post( + '/v2/entities/light1/attrs', + utils.readExampleFile( + './test/unit/ngsiv2/examples/contextRequests/updateContextProcessTimestamp.json' + ) + ) + .query({ type: 'Light' }) .reply(204); }); diff --git a/test/unit/ngsiv2/provisioning/device-provisioning-api_test.js b/test/unit/ngsiv2/provisioning/device-provisioning-api_test.js index 905e81645..f932bd34c 100644 --- a/test/unit/ngsiv2/provisioning/device-provisioning-api_test.js +++ b/test/unit/ngsiv2/provisioning/device-provisioning-api_test.js @@ -22,31 +22,32 @@ * * Modified by: Daniel Calvo - ATOS Research & Innovation */ -'use strict'; - -var iotAgentLib = require('../../../../lib/fiware-iotagent-lib'), - utils = require('../../../tools/utils'), - should = require('should'), - nock = require('nock'), - request = require('request'), - moment = require('moment'), - contextBrokerMock, - iotAgentConfig = { - logLevel: 'FATAL', - contextBroker: { - host: '192.168.1.1', - port: '1026', - ngsiVersion: 'v2' - }, - server: { - port: 4041, - baseRoot: '/' - }, - types: {}, - service: 'smartGondor', - subservice: 'gardens', - providerUrl: 'http://smartGondor.com' - }; + +/* eslint-disable no-unused-vars */ + +const iotAgentLib = require('../../../../lib/fiware-iotagent-lib'); +const utils = require('../../../tools/utils'); +const should = require('should'); +const nock = require('nock'); +const request = require('request'); +const moment = require('moment'); +let contextBrokerMock; +const iotAgentConfig = { + logLevel: 'FATAL', + contextBroker: { + host: '192.168.1.1', + port: '1026', + ngsiVersion: 'v2' + }, + server: { + port: 4041, + baseRoot: '/' + }, + types: {}, + service: 'smartGondor', + subservice: 'gardens', + providerUrl: 'http://smartGondor.com' +}; describe('Device provisioning API: Provision devices', function() { beforeEach(function(done) { @@ -56,9 +57,13 @@ describe('Device provisioning API: Provision devices', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', '/gardens') - .post('/v2/registrations', utils.readExampleFile('./test/unit/ngsiv2/examples' + - '/contextAvailabilityRequests/registerProvisionedDevice.json')) - .reply(201, null, {'Location': '/v2/registrations/6319a7f5254b05844116584d'}); + .post( + '/v2/registrations', + utils.readExampleFile( + './test/unit/ngsiv2/examples/contextAvailabilityRequests/registerProvisionedDevice.json' + ) + ) + .reply(201, null, { Location: '/v2/registrations/6319a7f5254b05844116584d' }); // This mock does not check the payload since the aim of the test is not to verify // device provisioning functionality. Appropriate verification is done in tests under @@ -85,19 +90,25 @@ describe('Device provisioning API: Provision devices', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', '/gardens') - .post('/v2/registrations', utils.readExampleFile('./test/unit/ngsiv2/examples' + - '/contextAvailabilityRequests/registerProvisionedDevice.json')) - .reply(201, null, {'Location': '/v2/registrations/6319a7f5254b05844116584d'}); + .post( + '/v2/registrations', + utils.readExampleFile( + './test/unit/ngsiv2/examples/contextAvailabilityRequests/registerProvisionedDevice.json' + ) + ) + .reply(201, null, { Location: '/v2/registrations/6319a7f5254b05844116584d' }); contextBrokerMock .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', '/gardens') - .post('/v2/entities?options=upsert', utils.readExampleFile( - './test/unit/ngsiv2/examples/contextRequests/createProvisionedDevice.json')) + .post( + '/v2/entities?options=upsert', + utils.readExampleFile('./test/unit/ngsiv2/examples/contextRequests/createProvisionedDevice.json') + ) .reply(204); }); - var options = { + const options = { url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices', method: 'POST', json: utils.readExampleFile('./test/unit/examples/deviceProvisioningRequests/provisionNewDevice.json'), @@ -120,7 +131,7 @@ describe('Device provisioning API: Provision devices', function() { }); it('should call the device provisioning handler if present', function(done) { - var handlerCalled = false; + let handlerCalled = false; iotAgentLib.setProvisioningHandler(function(device, callback) { handlerCalled = true; @@ -175,7 +186,6 @@ describe('Device provisioning API: Provision devices', function() { }); it('should store fill the device ID in case only the name is provided', function(done) { - /* jshint camelcase:false */ request(options, function(error, response, body) { response.statusCode.should.equal(201); iotAgentLib.listDevices('smartGondor', '/gardens', function(error, results) { @@ -211,7 +221,7 @@ describe('Device provisioning API: Provision devices', function() { }); }); describe('When a device provisioning request with a TimeInstant attribute arrives to the IoTA', function() { - var options = { + const options = { url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices', method: 'POST', json: utils.readExampleFile('./test/unit/examples/deviceProvisioningRequests/provisionTimeInstant.json'), @@ -237,8 +247,10 @@ describe('Device provisioning API: Provision devices', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', '/gardens') - .post('/v2/entities?options=upsert', - utils.readExampleFile('./test/unit/ngsiv2/examples/contextRequests/createTimeinstantDevice.json')) + .post( + '/v2/entities?options=upsert', + utils.readExampleFile('./test/unit/ngsiv2/examples/contextRequests/createTimeinstantDevice.json') + ) .reply(204); done(); @@ -252,9 +264,8 @@ describe('Device provisioning API: Provision devices', function() { }); }); - describe('When a device provisioning request with a timestamp provision attribute arrives to the IoTA', function() { - var options = { + const options = { url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices', method: 'POST', json: utils.readExampleFile('./test/unit/examples/deviceProvisioningRequests/provisionTimeInstant2.json'), @@ -280,8 +291,10 @@ describe('Device provisioning API: Provision devices', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', '/gardens') - .post('/v2/entities?options=upsert', - utils.readExampleFile('./test/unit/ngsiv2/examples/contextRequests/createTimeinstantDevice.json')) + .post( + '/v2/entities?options=upsert', + utils.readExampleFile('./test/unit/ngsiv2/examples/contextRequests/createTimeinstantDevice.json') + ) .reply(204); done(); @@ -296,7 +309,7 @@ describe('Device provisioning API: Provision devices', function() { }); describe('When a device provisioning request with a autoprovision attribute arrives to the IoTA', function() { - var options = { + const options = { url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices', method: 'POST', json: utils.readExampleFile('./test/unit/examples/deviceProvisioningRequests/provisionAutoprovision.json'), @@ -322,8 +335,10 @@ describe('Device provisioning API: Provision devices', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', '/gardens') - .post('/v2/entities?options=upsert', - utils.readExampleFile('./test/unit/ngsiv2/examples/contextRequests/createAutoprovisionDevice.json')) + .post( + '/v2/entities?options=upsert', + utils.readExampleFile('./test/unit/ngsiv2/examples/contextRequests/createAutoprovisionDevice.json') + ) .reply(204); done(); }); @@ -336,9 +351,8 @@ describe('Device provisioning API: Provision devices', function() { }); }); - describe('When a device provisioning request arrives to the IoTA' + - 'and timestamp is enabled in configuration', function() { - var options = { + describe('When a device provisioning request arrives to the IoTAand timestamp is enabled in configuration', function() { + const options = { url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices', method: 'POST', json: utils.readExampleFile('./test/unit/examples/deviceProvisioningRequests/provisionMinimumDevice.json'), @@ -365,15 +379,13 @@ describe('Device provisioning API: Provision devices', function() { .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', '/gardens') .post('/v2/entities?options=upsert', function(body) { - var expectedBody = utils.readExampleFile('./test/unit/ngsiv2/examples/' + - 'contextRequests/createTimeInstantMinimumDevice.json'); - if (!body.TimeInstant.value) - { + const expectedBody = utils.readExampleFile( + './test/unit/ngsiv2/examples/contextRequests/createTimeInstantMinimumDevice.json' + ); + if (!body.TimeInstant.value) { return false; - } - else if (moment(body.TimeInstant.value, 'YYYY-MM-DDTHH:mm:ss.SSSZ').isValid()) - { - var timeInstantDiff = moment().diff(body.TimeInstant.value, 'milliseconds'); + } else if (moment(body.TimeInstant.value, 'YYYY-MM-DDTHH:mm:ss.SSSZ').isValid()) { + const timeInstantDiff = moment().diff(body.TimeInstant.value, 'milliseconds'); if (timeInstantDiff < 500) { delete body.TimeInstant; @@ -382,9 +394,7 @@ describe('Device provisioning API: Provision devices', function() { return false; } - else { - return false; - } + return false; }) .reply(204); @@ -400,7 +410,7 @@ describe('Device provisioning API: Provision devices', function() { }); describe('When a device provisioning request with the minimum required data arrives to the IoT Agent', function() { - var options = { + const options = { url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices', method: 'POST', json: utils.readExampleFile('./test/unit/examples/deviceProvisioningRequests/provisionMinimumDevice.json'), @@ -415,9 +425,12 @@ describe('Device provisioning API: Provision devices', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', '/gardens') - .post('/v2/entities?options=upsert', - utils.readExampleFile('./test/unit/ngsiv2/examples/' + - 'contextRequests/createMinimumProvisionedDevice.json')) + .post( + '/v2/entities?options=upsert', + utils.readExampleFile( + './test/unit/ngsiv2/examples/contextRequests/createMinimumProvisionedDevice.json' + ) + ) .reply(204); done(); @@ -456,7 +469,7 @@ describe('Device provisioning API: Provision devices', function() { }); describe('When a device provisioning request with geo:point attributes arrives', function() { - var options = { + const options = { url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices', method: 'POST', json: utils.readExampleFile('./test/unit/examples/deviceProvisioningRequests/provisionGeopointDevice.json'), @@ -471,9 +484,12 @@ describe('Device provisioning API: Provision devices', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', '/gardens') - .post('/v2/entities?options=upsert', + .post( + '/v2/entities?options=upsert', utils.readExampleFile( - './test/unit/ngsiv2/examples/contextRequests/createGeopointProvisionedDevice.json')) + './test/unit/ngsiv2/examples/contextRequests/createGeopointProvisionedDevice.json' + ) + ) .reply(204); done(); @@ -488,7 +504,7 @@ describe('Device provisioning API: Provision devices', function() { }); describe('When a device provisioning request with DateTime attributes arrives', function() { - var options = { + const options = { url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices', method: 'POST', json: utils.readExampleFile('./test/unit/examples/deviceProvisioningRequests/provisionDatetimeDevice.json'), @@ -503,9 +519,12 @@ describe('Device provisioning API: Provision devices', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', '/gardens') - .post('/v2/entities?options=upsert', + .post( + '/v2/entities?options=upsert', utils.readExampleFile( - './test/unit/ngsiv2/examples/contextRequests/createDatetimeProvisionedDevice.json')) + './test/unit/ngsiv2/examples/contextRequests/createDatetimeProvisionedDevice.json' + ) + ) .reply(204); done(); @@ -519,42 +538,44 @@ describe('Device provisioning API: Provision devices', function() { }); }); - describe('When two devices with the same ID but different services arrive to the agent', function() { - var options1 = { - url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices', - method: 'POST', - json: utils.readExampleFile( - './test/unit/examples/deviceProvisioningRequests/provisionMinimumDevice.json'), - headers: { - 'fiware-service': 'smartGondor', - 'fiware-servicepath': '/gardens' - } - }, - options2 = { - url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices', - method: 'POST', - json: utils.readExampleFile( - './test/unit/examples/deviceProvisioningRequests/provisionMinimumDevice.json'), - headers: { - 'fiware-service': 'smartMordor', - 'fiware-servicepath': '/electricity' - } - }; + const options1 = { + url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices', + method: 'POST', + json: utils.readExampleFile('./test/unit/examples/deviceProvisioningRequests/provisionMinimumDevice.json'), + headers: { + 'fiware-service': 'smartGondor', + 'fiware-servicepath': '/gardens' + } + }; + const options2 = { + url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices', + method: 'POST', + json: utils.readExampleFile('./test/unit/examples/deviceProvisioningRequests/provisionMinimumDevice.json'), + headers: { + 'fiware-service': 'smartMordor', + 'fiware-servicepath': '/electricity' + } + }; beforeEach(function(done) { nock.cleanAll(); contextBrokerMock = nock('http://192.168.1.1:1026') - .post('/v2/entities?options=upsert', - utils.readExampleFile('./test/unit/ngsiv2/examples/' + - 'contextRequests/createMinimumProvisionedDevice.json')) + .post( + '/v2/entities?options=upsert', + utils.readExampleFile( + './test/unit/ngsiv2/examples/contextRequests/createMinimumProvisionedDevice.json' + ) + ) .reply(204); - contextBrokerMock - .post('/v2/entities?options=upsert', - utils.readExampleFile('./test/unit/ngsiv2/examples/' + - 'contextRequests/createMinimumProvisionedDevice.json')) + .post( + '/v2/entities?options=upsert', + utils.readExampleFile( + './test/unit/ngsiv2/examples/contextRequests/createMinimumProvisionedDevice.json' + ) + ) .reply(204); done(); @@ -590,7 +611,7 @@ describe('Device provisioning API: Provision devices', function() { }); describe('When there is a connection error with a String code connecting the CB', function() { - var options = { + const options = { url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices', method: 'POST', json: utils.readExampleFile('./test/unit/examples/deviceProvisioningRequests/provisionMinimumDevice.json'), @@ -607,7 +628,7 @@ describe('Device provisioning API: Provision devices', function() { .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', '/gardens') .post('/v2/registrations') - .reply(201, null, {'Location': '/v2/registrations/6319a7f5254b05844116584d'}); + .reply(201, null, { Location: '/v2/registrations/6319a7f5254b05844116584d' }); // This mock does not check the payload since the aim of the test is not to verify // device provisioning functionality. Appropriate verification is done in tests under @@ -616,7 +637,7 @@ describe('Device provisioning API: Provision devices', function() { .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', '/gardens') .post('/v2/entities?options=upsert') - .replyWithError({'message': 'Description of the error', 'code': 'STRING_CODE'}); + .replyWithError({ message: 'Description of the error', code: 'STRING_CODE' }); done(); }); @@ -632,7 +653,7 @@ describe('Device provisioning API: Provision devices', function() { }); describe('When there is a connection error with a Number code connecting the CB', function() { - var options = { + const options = { url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices', method: 'POST', json: utils.readExampleFile('./test/unit/examples/deviceProvisioningRequests/provisionMinimumDevice.json'), @@ -649,7 +670,7 @@ describe('Device provisioning API: Provision devices', function() { .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', '/gardens') .post('/v2/registrations') - .reply(201, null, {'Location': '/v2/registrations/6319a7f5254b05844116584d'}); + .reply(201, null, { Location: '/v2/registrations/6319a7f5254b05844116584d' }); // This mock does not check the payload since the aim of the test is not to verify // device provisioning functionality. Appropriate verification is done in tests under @@ -658,7 +679,7 @@ describe('Device provisioning API: Provision devices', function() { .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', '/gardens') .post('/v2/entities?options=upsert') - .replyWithError({'message': 'Description of the error', 'code': 123456789}); + .replyWithError({ message: 'Description of the error', code: 123456789 }); done(); }); @@ -674,7 +695,7 @@ describe('Device provisioning API: Provision devices', function() { }); describe('When a device provisioning request with missing data arrives to the IoT Agent', function() { - var options = { + const options = { url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices', method: 'POST', headers: { @@ -682,7 +703,8 @@ describe('Device provisioning API: Provision devices', function() { 'fiware-servicepath': '/gardens' }, json: utils.readExampleFile( - './test/unit/examples/deviceProvisioningRequests/provisionDeviceMissingParameters.json') + './test/unit/examples/deviceProvisioningRequests/provisionDeviceMissingParameters.json' + ) }; it('should raise a MISSING_ATTRIBUTES error, indicating the missing attributes', function(done) { @@ -696,7 +718,7 @@ describe('Device provisioning API: Provision devices', function() { }); }); describe('When two device provisioning requests with the same service and Device ID arrive', function() { - var options = { + const options = { url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices', method: 'POST', json: utils.readExampleFile('./test/unit/examples/deviceProvisioningRequests/provisionNewDevice.json'), @@ -711,7 +733,7 @@ describe('Device provisioning API: Provision devices', function() { .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', '/gardens') .post('/v2/registrations') - .reply(201, null, {'Location': '/v2/registrations/6319a7f5254b05844116584d'}); + .reply(201, null, { Location: '/v2/registrations/6319a7f5254b05844116584d' }); // This mock does not check the payload since the aim of the test is not to verify // device provisioning functionality. Appropriate verification is done in tests under @@ -737,11 +759,12 @@ describe('Device provisioning API: Provision devices', function() { }); }); describe('When a device provisioning request is malformed', function() { - var options = { + const options = { url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices', method: 'POST', json: utils.readExampleFile( - './test/unit/examples/deviceProvisioningRequests/provisionNewDeviceMalformed1.json'), + './test/unit/examples/deviceProvisioningRequests/provisionNewDeviceMalformed1.json' + ), headers: { 'fiware-service': 'smartGondor', 'fiware-servicepath': '/gardens' @@ -760,7 +783,7 @@ describe('Device provisioning API: Provision devices', function() { }); }); describe('When an agent is activated with a different base root', function() { - var options = { + const options = { url: 'http://localhost:' + iotAgentConfig.server.port + '/newBaseRoot/iot/devices', method: 'POST', headers: { @@ -794,12 +817,13 @@ describe('Device provisioning API: Provision devices', function() { }); }); describe('When a device provisioning request without the mandatory headers arrives to the Agent', function() { - var options = { + const options = { url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices', method: 'POST', headers: {}, json: utils.readExampleFile( - './test/unit/examples/deviceProvisioningRequests/provisionDeviceMissingParameters.json') + './test/unit/examples/deviceProvisioningRequests/provisionDeviceMissingParameters.json' + ) }; it('should raise a MISSING_HEADERS error, indicating the missing attributes', function(done) { @@ -812,21 +836,21 @@ describe('Device provisioning API: Provision devices', function() { }); }); describe('When a device delete request arrives to the Agent for a not existing device', function() { - var options = { - url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices/Light84', - headers: { - 'fiware-service': 'smartGondor', - 'fiware-servicepath': '/gardens' - }, - method: 'DELETE' - }; - - it('should return a 404 error', function(done) { - request(options, function(error, response, body) { - should.not.exist(error); - response.statusCode.should.equal(404); - done(); - }); - }); + const options = { + url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices/Light84', + headers: { + 'fiware-service': 'smartGondor', + 'fiware-servicepath': '/gardens' + }, + method: 'DELETE' + }; + + it('should return a 404 error', function(done) { + request(options, function(error, response, body) { + should.not.exist(error); + response.statusCode.should.equal(404); + done(); + }); + }); }); }); diff --git a/test/unit/ngsiv2/provisioning/device-registration_test.js b/test/unit/ngsiv2/provisioning/device-registration_test.js index 60ca9e684..48d1f776f 100644 --- a/test/unit/ngsiv2/provisioning/device-registration_test.js +++ b/test/unit/ngsiv2/provisioning/device-registration_test.js @@ -22,72 +22,72 @@ * * Modified by: Daniel Calvo - ATOS Research & Innovation */ -'use strict'; - -var iotAgentLib = require('../../../../lib/fiware-iotagent-lib'), - utils = require('../../../tools/utils'), - should = require('should'), - logger = require('logops'), - nock = require('nock'), - async = require('async'), - contextBrokerMock, - iotAgentConfig = { - contextBroker: { - host: '192.168.1.1', - port: '1026', - ngsiVersion: 'v2' - }, - server: { - port: 4041 - }, - types: { - 'Light': { - commands: [], - lazy: [ - { - name: 'temperature', - type: 'centigrades' - } - ], - active: [ - { - name: 'pressure', - type: 'Hgmm' - } - ], - service: 'smartGondor', - subservice: 'gardens' - }, - 'Termometer': { - commands: [], - lazy: [ - { - name: 'temp', - type: 'kelvin' - } - ], - active: [ - ], - service: 'smartGondor', - subservice: 'gardens' - } - }, - service: 'smartGondor', - subservice: 'gardens', - providerUrl: 'http://smartGondor.com' + +/* eslint-disable no-unused-vars */ + +const iotAgentLib = require('../../../../lib/fiware-iotagent-lib'); +const utils = require('../../../tools/utils'); +const should = require('should'); +const logger = require('logops'); +const nock = require('nock'); +const async = require('async'); +let contextBrokerMock; +const iotAgentConfig = { + contextBroker: { + host: '192.168.1.1', + port: '1026', + ngsiVersion: 'v2' }, - device1 = { - id: 'light1', - type: 'Light', - service: 'smartGondor', - subservice: 'gardens' + server: { + port: 4041 }, - device2 = { - id: 'term2', - type: 'Termometer', - service: 'smartGondor', - subservice: 'gardens' - }; + types: { + Light: { + commands: [], + lazy: [ + { + name: 'temperature', + type: 'centigrades' + } + ], + active: [ + { + name: 'pressure', + type: 'Hgmm' + } + ], + service: 'smartGondor', + subservice: 'gardens' + }, + Termometer: { + commands: [], + lazy: [ + { + name: 'temp', + type: 'kelvin' + } + ], + active: [], + service: 'smartGondor', + subservice: 'gardens' + } + }, + service: 'smartGondor', + subservice: 'gardens', + providerUrl: 'http://smartGondor.com' +}; +const device1 = { + id: 'light1', + type: 'Light', + service: 'smartGondor', + subservice: 'gardens' +}; +const device2 = { + id: 'term2', + type: 'Termometer', + service: 'smartGondor', + subservice: 'gardens' +}; describe('IoT Agent Device Registration', function() { beforeEach(function() { @@ -116,14 +116,14 @@ describe('IoT Agent Device Registration', function() { .post('/v2/entities?options=upsert') .reply(204); - var nockBody = utils.readExampleFile( - './test/unit/ngsiv2/examples/contextAvailabilityRequests/registerIoTAgent1.json'); + const nockBody = utils.readExampleFile( + './test/unit/ngsiv2/examples/contextAvailabilityRequests/registerIoTAgent1.json' + ); contextBrokerMock .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') .post('/v2/registrations', nockBody) - .reply(201, null, {'Location': '/v2/registrations/6319a7f5254b05844116584d'}); - + .reply(201, null, { Location: '/v2/registrations/6319a7f5254b05844116584d' }); iotAgentLib.activate(iotAgentConfig, function(error) { iotAgentLib.clearAll(done); @@ -132,9 +132,9 @@ describe('IoT Agent Device Registration', function() { it('should register as ContextProvider of its lazy attributes', function(done) { iotAgentLib.register(device1, function(error) { - should.not.exist(error); - contextBrokerMock.done(); - done(); + should.not.exist(error); + contextBrokerMock.done(); + done(); }); }); }); @@ -143,8 +143,9 @@ describe('IoT Agent Device Registration', function() { beforeEach(function(done) { nock.cleanAll(); - var nockBody = utils.readExampleFile( - './test/unit/ngsiv2/examples/contextAvailabilityRequests/registerIoTAgent1.json'); + const nockBody = utils.readExampleFile( + './test/unit/ngsiv2/examples/contextAvailabilityRequests/registerIoTAgent1.json' + ); contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') @@ -169,8 +170,9 @@ describe('IoT Agent Device Registration', function() { describe('When the Context Broker returns an HTTP transport error while registering a device', function() { beforeEach(function(done) { nock.cleanAll(); - var nockBody = utils.readExampleFile( - './test/unit/ngsiv2/examples/contextAvailabilityRequests/registerIoTAgent1.json'); + const nockBody = utils.readExampleFile( + './test/unit/ngsiv2/examples/contextAvailabilityRequests/registerIoTAgent1.json' + ); contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') @@ -198,13 +200,14 @@ describe('IoT Agent Device Registration', function() { beforeEach(function(done) { nock.cleanAll(); - var nockBody = utils.readExampleFile( - './test/unit/ngsiv2/examples/contextAvailabilityRequests/registerIoTAgent1.json'); + const nockBody = utils.readExampleFile( + './test/unit/ngsiv2/examples/contextAvailabilityRequests/registerIoTAgent1.json' + ); contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') .post('/v2/registrations', nockBody) - .reply(201, null, {'Location': '/v2/registrations/6319a7f5254b05844116584d'}); + .reply(201, null, { Location: '/v2/registrations/6319a7f5254b05844116584d' }); // This mock does not check the payload since the aim of the test is not to verify // device provisioning functionality. Appropriate verification is done in tests under @@ -220,7 +223,7 @@ describe('IoT Agent Device Registration', function() { }); }); - it('should return all the device\'s information', function(done) { + it("should return all the device's information", function(done) { iotAgentLib.register(device1, function(error) { iotAgentLib.getDevice('light1', 'smartGondor', 'gardens', function(error, data) { should.not.exist(error); @@ -237,13 +240,14 @@ describe('IoT Agent Device Registration', function() { beforeEach(function(done) { nock.cleanAll(); - var nockBody = utils.readExampleFile( - './test/unit/ngsiv2/examples/contextAvailabilityRequests/registerIoTAgent1.json'); + const nockBody = utils.readExampleFile( + './test/unit/ngsiv2/examples/contextAvailabilityRequests/registerIoTAgent1.json' + ); contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') .post('/v2/registrations', nockBody) - .reply(201, null, {'Location': '/v2/registrations/6319a7f5254b05844116584d'}); + .reply(201, null, { Location: '/v2/registrations/6319a7f5254b05844116584d' }); iotAgentLib.activate(iotAgentConfig, function(error) { iotAgentLib.clearAll(done); @@ -265,41 +269,38 @@ describe('IoT Agent Device Registration', function() { describe('When a device is removed from the IoT Agent', function() { beforeEach(function(done) { - nock.cleanAll(); contextBrokerMock = nock('http://192.168.1.1:1026') .post('/v2/registrations') - .reply(201, null, {'Location': '/v2/registrations/6319a7f5254b05844116584d'}); + .reply(201, null, { Location: '/v2/registrations/6319a7f5254b05844116584d' }); // This mock does not check the payload since the aim of the test is not to verify // device provisioning functionality. Appropriate verification is done in tests under // provisioning folder - contextBrokerMock - .post('/v2/entities?options=upsert') - .reply(204); + contextBrokerMock.post('/v2/entities?options=upsert').reply(204); contextBrokerMock .post('/v2/registrations') - .reply(201, null, {'Location': '/v2/registrations/6319a7f5254b05844116584d'}); + .reply(201, null, { Location: '/v2/registrations/6319a7f5254b05844116584d' }); // This mock does not check the payload since the aim of the test is not to verify // device provisioning functionality. Appropriate verification is done in tests under // provisioning folder - contextBrokerMock - .post('/v2/entities?options=upsert') - .reply(204); + contextBrokerMock.post('/v2/entities?options=upsert').reply(204); contextBrokerMock .delete('/v2/registrations/6319a7f5254b05844116584d') - .reply(204, null, {'Location': '/v2/registrations/6319a7f5254b05844116584d'}); - + .reply(204, null, { Location: '/v2/registrations/6319a7f5254b05844116584d' }); iotAgentLib.activate(iotAgentConfig, function(error) { - async.series([ - async.apply(iotAgentLib.clearAll), - async.apply(iotAgentLib.register, device1), - async.apply(iotAgentLib.register, device2) - ], done); + async.series( + [ + async.apply(iotAgentLib.clearAll), + async.apply(iotAgentLib.register, device1), + async.apply(iotAgentLib.register, device2) + ], + done + ); }); }); @@ -317,36 +318,33 @@ describe('IoT Agent Device Registration', function() { nock.cleanAll(); contextBrokerMock = nock('http://192.168.1.1:1026') .post('/v2/registrations') - .reply(201, null, {'Location': '/v2/registrations/6319a7f5254b05844116584d'}); + .reply(201, null, { Location: '/v2/registrations/6319a7f5254b05844116584d' }); // This mock does not check the payload since the aim of the test is not to verify // device provisioning functionality. Appropriate verification is done in tests under // provisioning folder - contextBrokerMock - .post('/v2/entities?options=upsert') - .reply(204); + contextBrokerMock.post('/v2/entities?options=upsert').reply(204); contextBrokerMock = nock('http://192.168.1.1:1026') .post('/v2/registrations') - .reply(201, null, {'Location': '/v2/registrations/8254b65a7d11650f45844319'}); + .reply(201, null, { Location: '/v2/registrations/8254b65a7d11650f45844319' }); // This mock does not check the payload since the aim of the test is not to verify // device provisioning functionality. Appropriate verification is done in tests under // provisioning folder - contextBrokerMock - .post('/v2/entities?options=upsert') - .reply(204); + contextBrokerMock.post('/v2/entities?options=upsert').reply(204); - contextBrokerMock - .delete('/v2/registrations/6319a7f5254b05844116584d') - .reply(500); + contextBrokerMock.delete('/v2/registrations/6319a7f5254b05844116584d').reply(500); iotAgentLib.activate(iotAgentConfig, function(error) { - async.series([ - async.apply(iotAgentLib.clearAll), - async.apply(iotAgentLib.register, device1), - async.apply(iotAgentLib.register, device2) - ], done); + async.series( + [ + async.apply(iotAgentLib.clearAll), + async.apply(iotAgentLib.register, device1), + async.apply(iotAgentLib.register, device2) + ], + done + ); }); }); diff --git a/test/unit/ngsiv2/provisioning/device-update-registration_test.js b/test/unit/ngsiv2/provisioning/device-update-registration_test.js index 534bd6ab9..6327bcfac 100644 --- a/test/unit/ngsiv2/provisioning/device-update-registration_test.js +++ b/test/unit/ngsiv2/provisioning/device-update-registration_test.js @@ -22,116 +22,116 @@ * * Modified by: Daniel Calvo - ATOS Research & Innovation */ -'use strict'; -var iotAgentLib = require('../../../../lib/fiware-iotagent-lib'), - utils = require('../../../tools/utils'), - should = require('should'), - logger = require('logops'), - nock = require('nock'), - contextBrokerMock, - iotAgentConfig = { - contextBroker: { - host: '192.168.1.1', - port: '1026', - ngsiVersion: 'v2' - }, - server: { - port: 4041 - }, - types: { - 'Light': { - commands: [], - lazy: [ - { - name: 'temperature', - type: 'centigrades' - } - ], - active: [ - { - name: 'pressure', - type: 'Hgmm' - } - ], - service: 'smartGondor', - subservice: 'gardens' - }, - 'Termometer': { - commands: [], - lazy: [ - { - name: 'temp', - type: 'kelvin' - } - ], - active: [ - ], - service: 'smartGondor', - subservice: 'gardens' - } - }, - service: 'smartGondor', - subservice: 'gardens', - providerUrl: 'http://smartGondor.com' - }, - device1 = { - id: 'light1', - type: 'Light', - service: 'smartGondor', - subservice: 'gardens', +/* eslint-disable no-unused-vars */ + +const iotAgentLib = require('../../../../lib/fiware-iotagent-lib'); +const utils = require('../../../tools/utils'); +const should = require('should'); +const logger = require('logops'); +const nock = require('nock'); +let contextBrokerMock; +const iotAgentConfig = { + contextBroker: { + host: '192.168.1.1', + port: '1026', + ngsiVersion: 'v2' }, - deviceUpdated = { - id: 'light1', - type: 'Light', - name: 'light1', - service: 'smartGondor', - subservice: 'gardens', - internalId: 'newInternalId', - lazy: [ - { - name: 'pressure', - type: 'Hgmm' - } - ], - active: [ - { - name: 'temperature', - type: 'centigrades' - } - ] + server: { + port: 4041 }, - deviceCommandUpdated = { - id: 'light1', - type: 'Light', - name: 'light1', - service: 'smartGondor', - subservice: 'gardens', - internalId: 'newInternalId', - commands: [ - { - name: 'move', - type: 'command' - } - ], - active: [ - { - name: 'temperature', - type: 'centigrades' - } - ] + types: { + Light: { + commands: [], + lazy: [ + { + name: 'temperature', + type: 'centigrades' + } + ], + active: [ + { + name: 'pressure', + type: 'Hgmm' + } + ], + service: 'smartGondor', + subservice: 'gardens' + }, + Termometer: { + commands: [], + lazy: [ + { + name: 'temp', + type: 'kelvin' + } + ], + active: [], + service: 'smartGondor', + subservice: 'gardens' + } }, - unknownDevice = { - id: 'rotationSensor4', - type: 'Rotation', - name: 'Rotation4', - service: 'dumbMordor', - subservice: 'gardens', - internalId: 'unknownInternalId', + service: 'smartGondor', + subservice: 'gardens', + providerUrl: 'http://smartGondor.com' +}; +const device1 = { + id: 'light1', + type: 'Light', + service: 'smartGondor', + subservice: 'gardens' +}; +const deviceUpdated = { + id: 'light1', + type: 'Light', + name: 'light1', + service: 'smartGondor', + subservice: 'gardens', + internalId: 'newInternalId', + lazy: [ + { + name: 'pressure', + type: 'Hgmm' + } + ], + active: [ + { + name: 'temperature', + type: 'centigrades' + } + ] +}; +const deviceCommandUpdated = { + id: 'light1', + type: 'Light', + name: 'light1', + service: 'smartGondor', + subservice: 'gardens', + internalId: 'newInternalId', + commands: [ + { + name: 'move', + type: 'command' + } + ], + active: [ + { + name: 'temperature', + type: 'centigrades' + } + ] +}; +const unknownDevice = { + id: 'rotationSensor4', + type: 'Rotation', + name: 'Rotation4', + service: 'dumbMordor', + subservice: 'gardens', + internalId: 'unknownInternalId', - lazy: [], - active: [] - }; + lazy: [], + active: [] +}; describe('IoT Agent Device Update Registration', function() { beforeEach(function(done) { @@ -143,8 +143,8 @@ describe('IoT Agent Device Update Registration', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v2/registrations') - .reply(201, null, {'Location': '/v2/registrations/6319a7f5254b05844116584d'}); + .post('/v2/registrations') + .reply(201, null, { Location: '/v2/registrations/6319a7f5254b05844116584d' }); // This mock does not check the payload since the aim of the test is not to verify // device provisioning functionality. Appropriate verification is done in tests under @@ -174,8 +174,12 @@ describe('IoT Agent Device Update Registration', function() { contextBrokerMock .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v2/entities/Light:light1/attrs?type=Light', utils.readExampleFile( - './test/unit/ngsiv2/examples/contextRequests/updateProvisionActiveAttributes1.json')) + .post( + '/v2/entities/Light:light1/attrs?type=Light', + utils.readExampleFile( + './test/unit/ngsiv2/examples/contextRequests/updateProvisionActiveAttributes1.json' + ) + ) .reply(204); // FIXME: When https://github.com/telefonicaid/fiware-orion/issues/3007 is merged into master branch, @@ -190,10 +194,13 @@ describe('IoT Agent Device Update Registration', function() { contextBrokerMock .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v2/registrations', utils.readExampleFile('./test/unit/ngsiv2/examples' + - '/contextAvailabilityRequests/updateIoTAgent1.json')) - .reply(201, null, {'Location': '/v2/registrations/6319a7f5254b05844116584d'}); - + .post( + '/v2/registrations', + utils.readExampleFile( + './test/unit/ngsiv2/examples/contextAvailabilityRequests/updateIoTAgent1.json' + ) + ) + .reply(201, null, { Location: '/v2/registrations/6319a7f5254b05844116584d' }); }); it('should register as ContextProvider of its lazy attributes', function(done) { @@ -219,13 +226,14 @@ describe('IoT Agent Device Update Registration', function() { describe('When a device is preregistered and it is updated with new commands', function() { beforeEach(function() { - delete deviceCommandUpdated.registrationId; contextBrokerMock .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v2/entities/Light:light1/attrs?type=Light', utils.readExampleFile( - './test/unit/ngsiv2/examples/contextRequests/updateProvisionCommands1.json')) + .post( + '/v2/entities/Light:light1/attrs?type=Light', + utils.readExampleFile('./test/unit/ngsiv2/examples/contextRequests/updateProvisionCommands1.json') + ) .reply(204); // FIXME: When https://github.com/telefonicaid/fiware-orion/issues/3007 is merged into master branch, @@ -241,9 +249,13 @@ describe('IoT Agent Device Update Registration', function() { contextBrokerMock .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v2/registrations', utils.readExampleFile('./test/unit/ngsiv2/examples' + - '/contextAvailabilityRequests/updateCommands1.json')) - .reply(201, null, {'Location': '/v2/registrations/6319a7f5254b05844116584d'}); + .post( + '/v2/registrations', + utils.readExampleFile( + './test/unit/ngsiv2/examples/contextAvailabilityRequests/updateCommands1.json' + ) + ) + .reply(201, null, { Location: '/v2/registrations/6319a7f5254b05844116584d' }); }); it('should register as ContextProvider of its commands and create the additional attributes', function(done) { @@ -268,7 +280,6 @@ describe('IoT Agent Device Update Registration', function() { }); describe('When a update action is executed in a non registered device', function() { - it('should return a DEVICE_NOT_FOUND error', function(done) { iotAgentLib.updateRegister(unknownDevice, function(error) { should.exist(error); @@ -279,13 +290,10 @@ describe('IoT Agent Device Update Registration', function() { }); describe('When a device register is updated in the Context Broker and the request fail to connect', function() { beforeEach(function() { - // FIXME: When https://github.com/telefonicaid/fiware-orion/issues/3007 is merged into master branch, // this function should use the new API. This is just a temporary solution which implies deleting the // registration and creating a new one. - contextBrokerMock - .delete('/v2/registrations/6319a7f5254b05844116584d') - .reply(500, {}); + contextBrokerMock.delete('/v2/registrations/6319a7f5254b05844116584d').reply(500, {}); contextBrokerMock .matchHeader('fiware-service', 'smartGondor') diff --git a/test/unit/ngsiv2/provisioning/listProvisionedDevices-test.js b/test/unit/ngsiv2/provisioning/listProvisionedDevices-test.js index 21ebe07d6..2fd47bea2 100644 --- a/test/unit/ngsiv2/provisioning/listProvisionedDevices-test.js +++ b/test/unit/ngsiv2/provisioning/listProvisionedDevices-test.js @@ -23,39 +23,37 @@ * Modified by: Daniel Calvo - ATOS Research & Innovation */ - /* jshint camelcase: false */ - -'use strict'; - -var iotAgentLib = require('../../../../lib/fiware-iotagent-lib'), - utils = require('../../../tools/utils'), - should = require('should'), - nock = require('nock'), - async = require('async'), - request = require('request'), - contextBrokerMock, - iotAgentConfig = { - logLevel: 'FATAL', - contextBroker: { - host: '192.168.1.1', - port: '1026', - ngsiVersion: 'v2' - }, - server: { - port: 4041, - baseRoot: '/' - }, - types: {}, - service: 'smartGondor', - subservice: 'gardens', - providerUrl: 'http://smartGondor.com' - }; +/* eslint-disable no-unused-vars */ + +const iotAgentLib = require('../../../../lib/fiware-iotagent-lib'); +const utils = require('../../../tools/utils'); +const should = require('should'); +const nock = require('nock'); +const async = require('async'); +const request = require('request'); +let contextBrokerMock; +const iotAgentConfig = { + logLevel: 'FATAL', + contextBroker: { + host: '192.168.1.1', + port: '1026', + ngsiVersion: 'v2' + }, + server: { + port: 4041, + baseRoot: '/' + }, + types: {}, + service: 'smartGondor', + subservice: 'gardens', + providerUrl: 'http://smartGondor.com' +}; describe('Device provisioning API: List provisioned devices', function() { - var provisioning1Options, - provisioning2Options, - provisioning3Options, - provisioning4Options; + let provisioning1Options; + let provisioning2Options; + let provisioning3Options; + let provisioning4Options; beforeEach(function(done) { provisioning1Options = { @@ -91,45 +89,42 @@ describe('Device provisioning API: List provisioned devices', function() { iotAgentLib.activate(iotAgentConfig, function() { contextBrokerMock = nock('http://192.168.1.1:1026') .post('/v2/registrations') - .reply(201, null, {'Location': '/v2/registrations/6319a7f5254b05844116584d'}); + .reply(201, null, { Location: '/v2/registrations/6319a7f5254b05844116584d' }); // This mock does not check the payload since the aim of the test is not to verify // device provisioning functionality. Appropriate verification is done in tests under // provisioning folder - contextBrokerMock - .post('/v2/entities?options=upsert') - .reply(204); + contextBrokerMock.post('/v2/entities?options=upsert').reply(204); contextBrokerMock .post('/v2/registrations') - .reply(201, null, {'Location': '/v2/registrations/6319a7f5254b05844116584d'}); + .reply(201, null, { Location: '/v2/registrations/6319a7f5254b05844116584d' }); // This mock does not check the payload since the aim of the test is not to verify // device provisioning functionality. Appropriate verification is done in tests under // provisioning folder - contextBrokerMock - .post('/v2/entities?options=upsert') - .reply(204); + contextBrokerMock.post('/v2/entities?options=upsert').reply(204); contextBrokerMock .post('/v2/registrations') - .reply(201, null, {'Location': '/v2/registrations/6319a7f5254b05844116584d'}); + .reply(201, null, { Location: '/v2/registrations/6319a7f5254b05844116584d' }); // This mock does not check the payload since the aim of the test is not to verify // device provisioning functionality. Appropriate verification is done in tests under // provisioning folder - contextBrokerMock - .post('/v2/entities?options=upsert') - .reply(204); - - async.series([ - iotAgentLib.clearAll, - async.apply(request, provisioning1Options), - async.apply(request, provisioning2Options), - async.apply(request, provisioning4Options) - ], function(error, results) { - done(); - }); + contextBrokerMock.post('/v2/entities?options=upsert').reply(204); + + async.series( + [ + iotAgentLib.clearAll, + async.apply(request, provisioning1Options), + async.apply(request, provisioning2Options), + async.apply(request, provisioning4Options) + ], + function(error, results) { + done(); + } + ); }); }); @@ -138,7 +133,7 @@ describe('Device provisioning API: List provisioned devices', function() { }); describe('When a request for the list of provisioned devices arrive', function() { - var options = { + const options = { url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices', headers: { 'fiware-service': 'smartGondor', @@ -149,7 +144,7 @@ describe('Device provisioning API: List provisioned devices', function() { it('should return all the provisioned devices', function(done) { request(options, function(error, response, body) { - var parsedBody = JSON.parse(body); + const parsedBody = JSON.parse(body); should.not.exist(error); should.exist(parsedBody.devices); response.statusCode.should.equal(200); @@ -160,10 +155,8 @@ describe('Device provisioning API: List provisioned devices', function() { }); it('should return all the appropriate field names', function(done) { - /* jshint camelcase:false */ - request(options, function(error, response, body) { - var parsedBody = JSON.parse(body); + const parsedBody = JSON.parse(body); should.exist(parsedBody.devices[0].attributes); parsedBody.devices[0].attributes.length.should.equal(1); @@ -186,8 +179,7 @@ describe('Device provisioning API: List provisioned devices', function() { it('should return all the plugin attributes', function(done) { request(options, function(error, response, body) { - var parsedBody = JSON.parse(body); - + const parsedBody = JSON.parse(body); should.exist(parsedBody.devices[2].attributes[0].entity_name); should.exist(parsedBody.devices[2].attributes[0].entity_type); @@ -202,7 +194,7 @@ describe('Device provisioning API: List provisioned devices', function() { }); }); describe('When a request for the information about a specific device arrives', function() { - var options = { + const options = { url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices/Light1', headers: { 'fiware-service': 'smartGondor', @@ -213,14 +205,10 @@ describe('Device provisioning API: List provisioned devices', function() { it('should return all the information on that particular device', function(done) { request(options, function(error, response, body) { - /* jshint camelcase:false */ - - var parsedBody; - should.not.exist(error); response.statusCode.should.equal(200); - parsedBody = JSON.parse(body); + const parsedBody = JSON.parse(body); parsedBody.entity_name.should.equal('TheFirstLight'); parsedBody.device_id.should.equal('Light1'); done(); @@ -229,13 +217,9 @@ describe('Device provisioning API: List provisioned devices', function() { it('should return the appropriate attribute fields', function(done) { request(options, function(error, response, body) { - /* jshint camelcase:false */ - - var parsedBody; - should.not.exist(error); - parsedBody = JSON.parse(body); + const parsedBody = JSON.parse(body); should.exist(parsedBody.attributes[0].object_id); parsedBody.attributes[0].object_id.should.equal('attr_name'); parsedBody.attributes[0].name.should.equal('attr_name'); @@ -245,7 +229,7 @@ describe('Device provisioning API: List provisioned devices', function() { }); }); describe('When a request for a device with plugin attributes arrives', function() { - var options = { + const options = { url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices/LightFull', headers: { 'fiware-service': 'smartGondor', @@ -256,13 +240,9 @@ describe('Device provisioning API: List provisioned devices', function() { it('should return the appropriate attribute fields', function(done) { request(options, function(error, response, body) { - /* jshint camelcase:false */ - - var parsedBody; - should.not.exist(error); - parsedBody = JSON.parse(body); + const parsedBody = JSON.parse(body); should.exist(parsedBody.attributes[0].entity_name); should.exist(parsedBody.attributes[0].entity_type); should.exist(parsedBody.attributes[1].expression); @@ -276,7 +256,7 @@ describe('Device provisioning API: List provisioned devices', function() { }); }); describe('When a request for an unexistent device arrives', function() { - var options = { + const options = { url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices/Light84', headers: { 'fiware-service': 'smartGondor', @@ -295,7 +275,7 @@ describe('Device provisioning API: List provisioned devices', function() { }); describe('When a request for listing all the devices with a limit of 3 arrives', function() { - var options = { + const options = { url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices?limit=3', headers: { 'fiware-service': 'smartGondor', @@ -305,9 +285,7 @@ describe('Device provisioning API: List provisioned devices', function() { }; function createDeviceRequest(i, callback) { - /* jshint camelcase: false */ - - var provisioningDeviceOptions = { + const provisioningDeviceOptions = { url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices', method: 'POST', headers: { @@ -331,7 +309,7 @@ describe('Device provisioning API: List provisioned devices', function() { .matchHeader('fiware-servicepath', '/gardens') .post('/v2/registrations') .times(10) - .reply(201, null, {'Location': '/v2/registrations/6319a7f5254b05844116584d'}); + .reply(201, null, { Location: '/v2/registrations/6319a7f5254b05844116584d' }); // This mock does not check the payload since the aim of the test is not to verify // device provisioning functionality. Appropriate verification is done in tests under @@ -350,7 +328,7 @@ describe('Device provisioning API: List provisioned devices', function() { it('should return just 3 devices', function(done) { request(options, function(error, response, body) { - var parsedBody = JSON.parse(body); + const parsedBody = JSON.parse(body); should.not.exist(error); parsedBody.devices.length.should.equal(3); done(); @@ -359,7 +337,7 @@ describe('Device provisioning API: List provisioned devices', function() { it('should return a count with the complete number of devices', function(done) { request(options, function(error, response, body) { - var parsedBody = JSON.parse(body); + const parsedBody = JSON.parse(body); should.not.exist(error); parsedBody.count.should.equal(10); done(); @@ -368,7 +346,7 @@ describe('Device provisioning API: List provisioned devices', function() { }); describe('When a request for listing all the devices with a offset of 3 arrives', function() { - var options = { + const options = { url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices?offset=3', headers: { 'fiware-service': 'smartGondor', @@ -378,7 +356,7 @@ describe('Device provisioning API: List provisioned devices', function() { }; function createDeviceRequest(i, callback) { - var provisioningDeviceOptions = { + const provisioningDeviceOptions = { url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices', method: 'POST', headers: { @@ -404,7 +382,7 @@ describe('Device provisioning API: List provisioned devices', function() { .matchHeader('fiware-servicepath', '/gardens') .post('/v2/registrations') .times(10) - .reply(201, null, {'Location': '/v2/registrations/6319a7f5254b05844116584d'}); + .reply(201, null, { Location: '/v2/registrations/6319a7f5254b05844116584d' }); iotAgentLib.clearAll(function() { async.timesSeries(10, createDeviceRequest, function(error, results) { @@ -415,10 +393,10 @@ describe('Device provisioning API: List provisioned devices', function() { it('should skip the first 3 devices', function(done) { request(options, function(error, response, body) { - var parsedBody = JSON.parse(body); + const parsedBody = JSON.parse(body); should.not.exist(error); - for (var i = 0; i < parsedBody.devices.length; i++) { + for (let i = 0; i < parsedBody.devices.length; i++) { ['Light1_0', 'Light1_1', 'Light1_2'].indexOf(parsedBody.devices[i].id).should.equal(-1); } @@ -428,7 +406,7 @@ describe('Device provisioning API: List provisioned devices', function() { }); describe('When a listing request arrives and there are devices in other service and servicepath', function() { - var options = { + const options = { url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices', headers: { 'fiware-service': 'smartGondor', @@ -446,12 +424,13 @@ describe('Device provisioning API: List provisioned devices', function() { 'fiware-servicepath': '/gardens' }, json: utils.readExampleFile( - './test/unit/examples/deviceProvisioningRequests/provisionYetAnotherDevice.json') + './test/unit/examples/deviceProvisioningRequests/provisionYetAnotherDevice.json' + ) }; contextBrokerMock .post('/v2/registrations') - .reply(201, null, {'Location': '/v2/registrations/6319a7f5254b05844116584d'}); + .reply(201, null, { Location: '/v2/registrations/6319a7f5254b05844116584d' }); request(provisioning3Options, function(error) { done(); @@ -460,7 +439,7 @@ describe('Device provisioning API: List provisioned devices', function() { it('should return just the ones in the selected service', function(done) { request(options, function(error, response, body) { - var parsedBody = JSON.parse(body); + const parsedBody = JSON.parse(body); should.not.exist(error); response.statusCode.should.equal(200); parsedBody.devices.length.should.equal(3); diff --git a/test/unit/ngsiv2/provisioning/provisionDeviceMultientity-test.js b/test/unit/ngsiv2/provisioning/provisionDeviceMultientity-test.js index 37d916377..21d0d014f 100644 --- a/test/unit/ngsiv2/provisioning/provisionDeviceMultientity-test.js +++ b/test/unit/ngsiv2/provisioning/provisionDeviceMultientity-test.js @@ -22,31 +22,31 @@ * * Modified by: Daniel Calvo - ATOS Research & Innovation */ -'use strict'; -var iotAgentLib = require('../../../../lib/fiware-iotagent-lib'), - utils = require('../../../tools/utils'), +/* eslint-disable no-unused-vars */ - should = require('should'), - nock = require('nock'), - request = require('request'), - contextBrokerMock, - iotAgentConfig = { - logLevel: 'FATAL', - contextBroker: { - host: '192.168.1.1', - port: '1026', - ngsiVersion: 'v2' - }, - server: { - port: 4041, - baseRoot: '/' - }, - types: {}, - service: 'smartGondor', - subservice: 'gardens', - providerUrl: 'http://smartGondor.com' - }; +const iotAgentLib = require('../../../../lib/fiware-iotagent-lib'); +const utils = require('../../../tools/utils'); +const should = require('should'); +const nock = require('nock'); +const request = require('request'); +let contextBrokerMock; +const iotAgentConfig = { + logLevel: 'FATAL', + contextBroker: { + host: '192.168.1.1', + port: '1026', + ngsiVersion: 'v2' + }, + server: { + port: 4041, + baseRoot: '/' + }, + types: {}, + service: 'smartGondor', + subservice: 'gardens', + providerUrl: 'http://smartGondor.com' +}; describe('Device provisioning API: Provision devices', function() { beforeEach(function(done) { @@ -70,23 +70,32 @@ describe('Device provisioning API: Provision devices', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', '/gardens') - .post('/v2/registrations', utils.readExampleFile('./test/unit/ngsiv2/examples' + - '/contextAvailabilityRequests/registerProvisionedDevice.json')) - .reply(201, null, {'Location': '/v2/registrations/6319a7f5254b05844116584d'}); + .post( + '/v2/registrations', + utils.readExampleFile( + './test/unit/ngsiv2/examples/contextAvailabilityRequests/registerProvisionedDevice.json' + ) + ) + .reply(201, null, { Location: '/v2/registrations/6319a7f5254b05844116584d' }); contextBrokerMock .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', '/gardens') - .post('/v2/entities?options=upsert', utils.readExampleFile( - './test/unit/ngsiv2/examples/contextRequests/createProvisionedDeviceMultientity.json')) + .post( + '/v2/entities?options=upsert', + utils.readExampleFile( + './test/unit/ngsiv2/examples/contextRequests/createProvisionedDeviceMultientity.json' + ) + ) .reply(204); }); - var options = { + const options = { url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices', method: 'POST', - json: utils.readExampleFile('./test/unit/examples/' + - 'deviceProvisioningRequests/provisionNewDeviceMultientity.json'), + json: utils.readExampleFile( + './test/unit/examples/deviceProvisioningRequests/provisionNewDeviceMultientity.json' + ), headers: { 'fiware-service': 'smartGondor', 'fiware-servicepath': '/gardens' @@ -104,8 +113,5 @@ describe('Device provisioning API: Provision devices', function() { }); }); }); - }); }); - - diff --git a/test/unit/ngsiv2/provisioning/removeProvisionedDevice-test.js b/test/unit/ngsiv2/provisioning/removeProvisionedDevice-test.js index ef6048a1d..833807460 100644 --- a/test/unit/ngsiv2/provisioning/removeProvisionedDevice-test.js +++ b/test/unit/ngsiv2/provisioning/removeProvisionedDevice-test.js @@ -22,71 +22,72 @@ * * Modified by: Daniel Calvo - ATOS Research & Innovation */ -'use strict'; - -var iotAgentLib = require('../../../../lib/fiware-iotagent-lib'), - utils = require('../../../tools/utils'), - should = require('should'), - nock = require('nock'), - async = require('async'), - request = require('request'), - contextBrokerMock, - iotAgentConfig = { - logLevel: 'FATAL', - contextBroker: { - host: '192.168.1.1', - port: '1026', - ngsiVersion: 'v2' - }, - server: { - port: 4041, - baseRoot: '/' - }, - types: {}, - service: 'smartGondor', - subservice: 'gardens', - providerUrl: 'http://smartGondor.com' - }; + +/* eslint-disable no-unused-vars */ + +const iotAgentLib = require('../../../../lib/fiware-iotagent-lib'); +const utils = require('../../../tools/utils'); +const should = require('should'); +const nock = require('nock'); +const async = require('async'); +const request = require('request'); +let contextBrokerMock; +const iotAgentConfig = { + logLevel: 'FATAL', + contextBroker: { + host: '192.168.1.1', + port: '1026', + ngsiVersion: 'v2' + }, + server: { + port: 4041, + baseRoot: '/' + }, + types: {}, + service: 'smartGondor', + subservice: 'gardens', + providerUrl: 'http://smartGondor.com' +}; describe('Device provisioning API: Remove provisioned devices', function() { - var provisioning1Options = { - url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices', - method: 'POST', - headers: { - 'fiware-service': 'smartGondor', - 'fiware-servicepath': '/gardens' - }, - json: utils.readExampleFile('./test/unit/examples/deviceProvisioningRequests/provisionNewDevice.json') + const provisioning1Options = { + url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices', + method: 'POST', + headers: { + 'fiware-service': 'smartGondor', + 'fiware-servicepath': '/gardens' }, - provisioning2Options = { - url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices', - method: 'POST', - headers: { - 'fiware-service': 'smartGondor', - 'fiware-servicepath': '/gardens' - }, - json: utils.readExampleFile('./test/unit/examples/deviceProvisioningRequests/provisionAnotherDevice.json') + json: utils.readExampleFile('./test/unit/examples/deviceProvisioningRequests/provisionNewDevice.json') + }; + const provisioning2Options = { + url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices', + method: 'POST', + headers: { + 'fiware-service': 'smartGondor', + 'fiware-servicepath': '/gardens' }, - provisioning3Options = { - url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices', - method: 'POST', - headers: { - 'fiware-service': 'smartGondor', - 'fiware-servicepath': '/gardens' - }, - json: utils.readExampleFile('./test/unit/examples/deviceProvisioningRequests/' + - 'provisionDeviceActiveAtts.json') - }; + json: utils.readExampleFile('./test/unit/examples/deviceProvisioningRequests/provisionAnotherDevice.json') + }; + const provisioning3Options = { + url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices', + method: 'POST', + headers: { + 'fiware-service': 'smartGondor', + 'fiware-servicepath': '/gardens' + }, + json: utils.readExampleFile('./test/unit/examples/deviceProvisioningRequests/provisionDeviceActiveAtts.json') + }; beforeEach(function(done) { iotAgentLib.activate(iotAgentConfig, function() { - var nockBody = utils.readExampleFile( - './test/unit/ngsiv2/examples/contextAvailabilityRequests/registerProvisionedDevice.json'); + const nockBody = utils.readExampleFile( + './test/unit/ngsiv2/examples/contextAvailabilityRequests/registerProvisionedDevice.json' + ); contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', '/gardens') .post('/v2/registrations', nockBody) - .reply(201, null, {'Location': '/v2/registrations/6319a7f5254b05844116584d'}); + .reply(201, null, { Location: '/v2/registrations/6319a7f5254b05844116584d' }); // This mock does not check the payload since the aim of the test is not to verify // device provisioning functionality. Appropriate verification is done in tests under @@ -97,13 +98,14 @@ describe('Device provisioning API: Remove provisioned devices', function() { .post('/v2/entities?options=upsert') .reply(204); - var nockBody2 = utils.readExampleFile( - './test/unit/ngsiv2/examples/contextAvailabilityRequests/registerProvisionedDevice2.json'); + const nockBody2 = utils.readExampleFile( + './test/unit/ngsiv2/examples/contextAvailabilityRequests/registerProvisionedDevice2.json' + ); contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', '/gardens') .post('/v2/registrations', nockBody2) - .reply(201, null, {'Location': '/v2/registrations/6319a7f5254b05844116584d'}); + .reply(201, null, { Location: '/v2/registrations/6319a7f5254b05844116584d' }); // This mock does not check the payload since the aim of the test is not to verify // device provisioning functionality. Appropriate verification is done in tests under @@ -129,14 +131,17 @@ describe('Device provisioning API: Remove provisioned devices', function() { .post('/v2/entities?options=upsert') .reply(204); - async.series([ - iotAgentLib.clearAll, - async.apply(request, provisioning1Options), - async.apply(request, provisioning2Options), - async.apply(request, provisioning3Options) - ], function(error, results) { - done(); - }); + async.series( + [ + iotAgentLib.clearAll, + async.apply(request, provisioning1Options), + async.apply(request, provisioning2Options), + async.apply(request, provisioning3Options) + ], + function(error, results) { + done(); + } + ); }); }); @@ -145,7 +150,7 @@ describe('Device provisioning API: Remove provisioned devices', function() { }); describe('When a request to remove a provision device arrives', function() { - var options = { + const options = { url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices/Light1', headers: { 'fiware-service': 'smartGondor', @@ -164,7 +169,7 @@ describe('Device provisioning API: Remove provisioned devices', function() { it('should remove the device from the provisioned devices list', function(done) { request(options, function(error, response, body) { - var options = { + const options = { url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices', headers: { 'fiware-service': 'smartGondor', @@ -174,7 +179,7 @@ describe('Device provisioning API: Remove provisioned devices', function() { }; request(options, function(error, response, body) { - var parsedBody = JSON.parse(body); + const parsedBody = JSON.parse(body); parsedBody.devices.length.should.equal(2); done(); }); @@ -183,7 +188,7 @@ describe('Device provisioning API: Remove provisioned devices', function() { it('should return a 404 error when asking for the particular device', function(done) { request(options, function(error, response, body) { - var options = { + const options = { url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices/Light1', headers: { 'fiware-service': 'smartGondor', @@ -201,7 +206,7 @@ describe('Device provisioning API: Remove provisioned devices', function() { }); it('should call the device remove handler if present', function(done) { - var handlerCalled = false; + let handlerCalled = false; iotAgentLib.setRemoveDeviceHandler(function(device, callback) { handlerCalled = true; @@ -216,7 +221,7 @@ describe('Device provisioning API: Remove provisioned devices', function() { }); describe('When a request to remove a provision device arrives. Device without lazy atts or commands', function() { - var options = { + const options = { url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices/Light3', headers: { 'fiware-service': 'smartGondor', diff --git a/test/unit/ngsiv2/provisioning/singleConfigurationMode-test.js b/test/unit/ngsiv2/provisioning/singleConfigurationMode-test.js index c77cb2f0d..9d22ecea8 100644 --- a/test/unit/ngsiv2/provisioning/singleConfigurationMode-test.js +++ b/test/unit/ngsiv2/provisioning/singleConfigurationMode-test.js @@ -22,52 +22,50 @@ * * Modified by: Daniel Calvo - ATOS Research & Innovation */ -'use strict'; - -/* jshint camelcase: false */ - -var iotAgentLib = require('../../../../lib/fiware-iotagent-lib'), - utils = require('../../../tools/utils'), - - should = require('should'), - nock = require('nock'), - contextBrokerMock, - request = require('request'), - iotAgentConfig = { - logLevel: 'FATAL', - contextBroker: { - host: '192.168.1.1', - port: '1026', - ngsiVersion: 'v2' - }, - server: { - port: 4041, - baseRoot: '/' - }, - types: {}, - service: 'smartGondor', - singleConfigurationMode: true, - subservice: 'gardens', - providerUrl: 'http://smartGondor.com' + +/* eslint-disable no-unused-vars */ + +const iotAgentLib = require('../../../../lib/fiware-iotagent-lib'); +const utils = require('../../../tools/utils'); +const should = require('should'); +const nock = require('nock'); +let contextBrokerMock; +const request = require('request'); +const iotAgentConfig = { + logLevel: 'FATAL', + contextBroker: { + host: '192.168.1.1', + port: '1026', + ngsiVersion: 'v2' }, - groupCreation = { - url: 'http://localhost:4041/iot/services', - method: 'POST', - json: utils.readExampleFile('./test/unit/examples/groupProvisioningRequests/provisionFullGroup.json'), - headers: { - 'fiware-service': 'TestService', - 'fiware-servicepath': '/testingPath' - } + server: { + port: 4041, + baseRoot: '/' }, - deviceCreation = { - url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices', - method: 'POST', - json: utils.readExampleFile('./test/unit/examples/deviceProvisioningRequests/provisionNewDevice.json'), - headers: { - 'fiware-service': 'TestService', - 'fiware-servicepath': '/testingPath' - } - }; + types: {}, + service: 'smartGondor', + singleConfigurationMode: true, + subservice: 'gardens', + providerUrl: 'http://smartGondor.com' +}; +const groupCreation = { + url: 'http://localhost:4041/iot/services', + method: 'POST', + json: utils.readExampleFile('./test/unit/examples/groupProvisioningRequests/provisionFullGroup.json'), + headers: { + 'fiware-service': 'TestService', + 'fiware-servicepath': '/testingPath' + } +}; +const deviceCreation = { + url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices', + method: 'POST', + json: utils.readExampleFile('./test/unit/examples/deviceProvisioningRequests/provisionNewDevice.json'), + headers: { + 'fiware-service': 'TestService', + 'fiware-servicepath': '/testingPath' + } +}; describe('Provisioning API: Single service mode', function() { beforeEach(function(done) { @@ -85,7 +83,7 @@ describe('Provisioning API: Single service mode', function() { }); describe('When a new configuration arrives to an already configured subservice', function() { - var groupCreationDuplicated = { + const groupCreationDuplicated = { url: 'http://localhost:4041/iot/services', method: 'POST', json: utils.readExampleFile('./test/unit/examples/groupProvisioningRequests/provisionDuplicateGroup.json'), @@ -110,7 +108,7 @@ describe('Provisioning API: Single service mode', function() { }); }); describe('When a device is provisioned with an ID that already exists in the configuration', function() { - var deviceCreationDuplicated = { + const deviceCreationDuplicated = { url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices', method: 'POST', json: utils.readExampleFile('./test/unit/examples/deviceProvisioningRequests/provisionDuplicatedDev.json'), @@ -127,7 +125,7 @@ describe('Provisioning API: Single service mode', function() { .matchHeader('fiware-service', 'TestService') .matchHeader('fiware-servicepath', '/testingPath') .post('/v2/registrations') - .reply(201, null, {'Location': '/v2/registrations/6319a7f5254b05844116584d'}); + .reply(201, null, { Location: '/v2/registrations/6319a7f5254b05844116584d' }); // This mock does not check the payload since the aim of the test is not to verify // device provisioning functionality. Appropriate verification is done in tests under @@ -156,24 +154,24 @@ describe('Provisioning API: Single service mode', function() { }); }); describe('When a device is provisioned with an ID that exists globally but not in the configuration', function() { - var alternativeDeviceCreation = { - url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices', - method: 'POST', - json: utils.readExampleFile('./test/unit/examples/deviceProvisioningRequests/provisionNewDevice.json'), - headers: { - 'fiware-service': 'AlternateService', - 'fiware-servicepath': '/testingPath' - } - }, - alternativeGroupCreation = { - url: 'http://localhost:4041/iot/services', - method: 'POST', - json: utils.readExampleFile('./test/unit/examples/groupProvisioningRequests/provisionFullGroup.json'), - headers: { - 'fiware-service': 'AlternateService', - 'fiware-servicepath': '/testingPath' - } - }; + const alternativeDeviceCreation = { + url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices', + method: 'POST', + json: utils.readExampleFile('./test/unit/examples/deviceProvisioningRequests/provisionNewDevice.json'), + headers: { + 'fiware-service': 'AlternateService', + 'fiware-servicepath': '/testingPath' + } + }; + const alternativeGroupCreation = { + url: 'http://localhost:4041/iot/services', + method: 'POST', + json: utils.readExampleFile('./test/unit/examples/groupProvisioningRequests/provisionFullGroup.json'), + headers: { + 'fiware-service': 'AlternateService', + 'fiware-servicepath': '/testingPath' + } + }; beforeEach(function(done) { nock.cleanAll(); @@ -182,7 +180,7 @@ describe('Provisioning API: Single service mode', function() { .matchHeader('fiware-service', 'TestService') .matchHeader('fiware-servicepath', '/testingPath') .post('/v2/registrations') - .reply(201, null, {'Location': '/v2/registrations/6319a7f5254b05844116584d'}); + .reply(201, null, { Location: '/v2/registrations/6319a7f5254b05844116584d' }); // This mock does not check the payload since the aim of the test is not to verify // device provisioning functionality. Appropriate verification is done in tests under @@ -197,7 +195,7 @@ describe('Provisioning API: Single service mode', function() { .matchHeader('fiware-service', 'AlternateService') .matchHeader('fiware-servicepath', '/testingPath') .post('/v2/registrations') - .reply(201, null, {'Location': '/v2/registrations/6319a7f5254b05844116584d'}); + .reply(201, null, { Location: '/v2/registrations/6319a7f5254b05844116584d' }); // This mock does not check the payload since the aim of the test is not to verify // device provisioning functionality. Appropriate verification is done in tests under @@ -226,15 +224,15 @@ describe('Provisioning API: Single service mode', function() { }); }); describe('When a device is provisioned without a type and with a default configuration type', function() { - var getDevice = { - url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices/Light1', - method: 'GET', - headers: { - 'fiware-service': 'TestService', - 'fiware-servicepath': '/testingPath' - } - }, - oldType; + const getDevice = { + url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices/Light1', + method: 'GET', + headers: { + 'fiware-service': 'TestService', + 'fiware-servicepath': '/testingPath' + } + }; + let oldType; beforeEach(function(done) { nock.cleanAll(); @@ -243,7 +241,7 @@ describe('Provisioning API: Single service mode', function() { .matchHeader('fiware-service', 'TestService') .matchHeader('fiware-servicepath', '/testingPath') .post('/v2/registrations') - .reply(201, null, {'Location': '/v2/registrations/6319a7f5254b05844116584d'}); + .reply(201, null, { Location: '/v2/registrations/6319a7f5254b05844116584d' }); // This mock does not check the payload since the aim of the test is not to verify // device provisioning functionality. Appropriate verification is done in tests under @@ -266,9 +264,7 @@ describe('Provisioning API: Single service mode', function() { it('should be provisioned with the default type', function(done) { request(deviceCreation, function(error, response, body) { request(getDevice, function(error, response, body) { - var parsedBody; - - parsedBody = JSON.parse(body); + const parsedBody = JSON.parse(body); parsedBody.entity_type.should.equal('SensorMachine'); @@ -283,15 +279,24 @@ describe('Provisioning API: Single service mode', function() { contextBrokerMock = nock('http://unexistentHost:1026') .matchHeader('fiware-service', 'TestService') .matchHeader('fiware-servicepath', '/testingPath') - .post('/v2/registrations', utils.readExampleFile('./test/unit/ngsiv2/examples' + - '/contextAvailabilityRequests/registerProvisionedDeviceWithGroup.json')) - .reply(201, null, {'Location': '/v2/registrations/6319a7f5254b05844116584d'}); + .post( + '/v2/registrations', + utils.readExampleFile( + './test/unit/ngsiv2/examples' + + '/contextAvailabilityRequests/registerProvisionedDeviceWithGroup.json' + ) + ) + .reply(201, null, { Location: '/v2/registrations/6319a7f5254b05844116584d' }); contextBrokerMock .matchHeader('fiware-service', 'TestService') .matchHeader('fiware-servicepath', '/testingPath') - .post('/v2/entities?options=upsert', utils.readExampleFile( - './test/unit/ngsiv2/examples/contextRequests/createProvisionedDeviceWithGroupAndStatic.json')) + .post( + '/v2/entities?options=upsert', + utils.readExampleFile( + './test/unit/ngsiv2/examples/contextRequests/createProvisionedDeviceWithGroupAndStatic.json' + ) + ) .reply(204); request(groupCreation, done); @@ -311,6 +316,5 @@ describe('Provisioning API: Single service mode', function() { done(); }); }); - }); }); diff --git a/test/unit/ngsiv2/provisioning/updateProvisionedDevices-test.js b/test/unit/ngsiv2/provisioning/updateProvisionedDevices-test.js index 131d550e5..e4a00f6d6 100644 --- a/test/unit/ngsiv2/provisioning/updateProvisionedDevices-test.js +++ b/test/unit/ngsiv2/provisioning/updateProvisionedDevices-test.js @@ -22,71 +22,73 @@ * * Modified by: Daniel Calvo - ATOS Research & Innovation */ -'use strict'; - -var iotAgentLib = require('../../../../lib/fiware-iotagent-lib'), - utils = require('../../../tools/utils'), - should = require('should'), - nock = require('nock'), - async = require('async'), - request = require('request'), - contextBrokerMock, - iotAgentConfig = { - logLevel: 'FATAL', - contextBroker: { - host: '192.168.1.1', - port: '1026', - ngsiVersion: 'v2' - }, - server: { - port: 4041, - baseRoot: '/' - }, - types: {}, - service: 'smartGondor', - subservice: 'gardens', - providerUrl: 'http://smartGondor.com' - }; + +/* eslint-disable no-unused-vars */ + +const iotAgentLib = require('../../../../lib/fiware-iotagent-lib'); +const utils = require('../../../tools/utils'); +const should = require('should'); +const nock = require('nock'); +const async = require('async'); +const request = require('request'); +let contextBrokerMock; +const iotAgentConfig = { + logLevel: 'FATAL', + contextBroker: { + host: '192.168.1.1', + port: '1026', + ngsiVersion: 'v2' + }, + server: { + port: 4041, + baseRoot: '/' + }, + types: {}, + service: 'smartGondor', + subservice: 'gardens', + providerUrl: 'http://smartGondor.com' +}; describe('Device provisioning API: Update provisioned devices', function() { - var provisioning1Options = { - url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices', - method: 'POST', - headers: { - 'fiware-service': 'smartGondor', - 'fiware-servicepath': '/gardens' - }, - json: utils.readExampleFile('./test/unit/examples/deviceProvisioningRequests/provisionNewDevice.json') + const provisioning1Options = { + url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices', + method: 'POST', + headers: { + 'fiware-service': 'smartGondor', + 'fiware-servicepath': '/gardens' }, - provisioning2Options = { - url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices', - method: 'POST', - headers: { - 'fiware-service': 'smartGondor', - 'fiware-servicepath': '/gardens' - }, - json: utils.readExampleFile('./test/unit/examples/deviceProvisioningRequests/provisionAnotherDevice.json') + json: utils.readExampleFile('./test/unit/examples/deviceProvisioningRequests/provisionNewDevice.json') + }; + const provisioning2Options = { + url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices', + method: 'POST', + headers: { + 'fiware-service': 'smartGondor', + 'fiware-servicepath': '/gardens' }, - provisioning3Options = { - url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices', - method: 'POST', - headers: { - 'fiware-service': 'smartGondor', - 'fiware-servicepath': '/gardens' - }, - json: utils.readExampleFile('./test/unit/examples/deviceProvisioningRequests/provisionMinimumDevice2.json') - }; + json: utils.readExampleFile('./test/unit/examples/deviceProvisioningRequests/provisionAnotherDevice.json') + }; + const provisioning3Options = { + url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices', + method: 'POST', + headers: { + 'fiware-service': 'smartGondor', + 'fiware-servicepath': '/gardens' + }, + json: utils.readExampleFile('./test/unit/examples/deviceProvisioningRequests/provisionMinimumDevice2.json') + }; beforeEach(function(done) { nock.cleanAll(); iotAgentLib.activate(iotAgentConfig, function() { - var nockBody = utils.readExampleFile( - './test/unit/ngsiv2/examples/contextAvailabilityRequests/registerProvisionedDevice.json'); + const nockBody = utils.readExampleFile( + './test/unit/ngsiv2/examples/contextAvailabilityRequests/registerProvisionedDevice.json' + ); contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', '/gardens') .post('/v2/registrations', nockBody) - .reply(201, null, {'Location': '/v2/registrations/6319a7f5254b05844116584d'}); + .reply(201, null, { Location: '/v2/registrations/6319a7f5254b05844116584d' }); // This mock does not check the payload since the aim of the test is not to verify // device provisioning functionality. Appropriate verification is done in tests under @@ -97,14 +99,15 @@ describe('Device provisioning API: Update provisioned devices', function() { .post('/v2/entities?options=upsert') .reply(204); - var nockBody2 = utils.readExampleFile( - './test/unit/ngsiv2/examples/contextAvailabilityRequests/registerProvisionedDevice2.json'); + const nockBody2 = utils.readExampleFile( + './test/unit/ngsiv2/examples/contextAvailabilityRequests/registerProvisionedDevice2.json' + ); nockBody2.expires = /.+/i; contextBrokerMock .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', '/gardens') .post('/v2/registrations', nockBody2) - .reply(201, null, {'Location': '/v2/registrations/6719a7f5254b058441165849'}); + .reply(201, null, { Location: '/v2/registrations/6719a7f5254b058441165849' }); // This mock does not check the payload since the aim of the test is not to verify // device provisioning functionality. Appropriate verification is done in tests under @@ -112,7 +115,7 @@ describe('Device provisioning API: Update provisioned devices', function() { contextBrokerMock .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', '/gardens') - .post('/v2/entities?options=upsert') + .post('/v2/entities?options=upsert') .reply(204); // FIXME: When https://github.com/telefonicaid/fiware-orion/issues/3007 is merged into master branch, @@ -124,20 +127,24 @@ describe('Device provisioning API: Update provisioned devices', function() { .delete('/v2/registrations/6719a7f5254b058441165849') .reply(204); - var nockBody3 = utils.readExampleFile( - './test/unit/ngsiv2/examples/contextAvailabilityRequests/updateIoTAgent2.json'); + const nockBody3 = utils.readExampleFile( + './test/unit/ngsiv2/examples/contextAvailabilityRequests/updateIoTAgent2.json' + ); nockBody3.expires = /.+/i; contextBrokerMock .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', '/gardens') .post('/v2/registrations', nockBody3) - .reply(201, null, {'Location': '/v2/registrations/4419a7f5254b058441165849'}); - - async.series([ - iotAgentLib.clearAll, - async.apply(request, provisioning1Options), - async.apply(request, provisioning2Options) - ], done); + .reply(201, null, { Location: '/v2/registrations/4419a7f5254b058441165849' }); + + async.series( + [ + iotAgentLib.clearAll, + async.apply(request, provisioning1Options), + async.apply(request, provisioning2Options) + ], + done + ); }); }); @@ -148,7 +155,7 @@ describe('Device provisioning API: Update provisioned devices', function() { }); describe('When a request to update a provision device arrives', function() { - var optionsUpdate = { + const optionsUpdate = { url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices/Light1', method: 'PUT', headers: { @@ -178,18 +185,24 @@ describe('Device provisioning API: Update provisioned devices', function() { contextBrokerMock .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', '/gardens') - .post('/v2/registrations', - utils.readExampleFile( - './test/unit/ngsiv2/examples/contextAvailabilityRequests/updateIoTAgent2.json')) - .reply(201, null, {'Location': '/v2/registrations/4419a7f5254b058441165849'}); + .post( + '/v2/registrations', + utils.readExampleFile( + './test/unit/ngsiv2/examples/contextAvailabilityRequests/updateIoTAgent2.json' + ) + ) + .reply(201, null, { Location: '/v2/registrations/4419a7f5254b058441165849' }); contextBrokerMock .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', '/gardens') - .post('/v2/registrations', - utils.readExampleFile( - './test/unit/ngsiv2/examples/contextAvailabilityRequests/updateIoTAgent3.json')) - .reply(201, null, {'Location': '/v2/registrations/4419a7f52546658441165849'}); + .post( + '/v2/registrations', + utils.readExampleFile( + './test/unit/ngsiv2/examples/contextAvailabilityRequests/updateIoTAgent3.json' + ) + ) + .reply(201, null, { Location: '/v2/registrations/4419a7f52546658441165849' }); }); it('should return a 200 OK and no errors', function(done) { @@ -202,7 +215,7 @@ describe('Device provisioning API: Update provisioned devices', function() { it('should have updated the data when asking for the particular device', function(done) { request(optionsUpdate, function(error, response, body) { - var options = { + const options = { url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices/Light1', headers: { 'fiware-service': 'smartGondor', @@ -212,9 +225,7 @@ describe('Device provisioning API: Update provisioned devices', function() { }; request(options, function(error, response, body) { - /* jshint camelcase:false */ - - var parsedBody = JSON.parse(body); + const parsedBody = JSON.parse(body); parsedBody.entity_name.should.equal('ANewLightName'); parsedBody.timezone.should.equal('Europe/Madrid'); done(); @@ -224,7 +235,7 @@ describe('Device provisioning API: Update provisioned devices', function() { it('should not modify the attributes not present in the update request', function(done) { request(optionsUpdate, function(error, response, body) { - var options = { + const options = { url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices/Light1', headers: { 'fiware-service': 'smartGondor', @@ -234,9 +245,7 @@ describe('Device provisioning API: Update provisioned devices', function() { }; request(options, function(error, response, body) { - /* jshint camelcase:false */ - - var parsedBody = JSON.parse(body); + const parsedBody = JSON.parse(body); parsedBody.entity_type.should.equal('TheLightType'); parsedBody.service.should.equal('smartGondor'); done(); @@ -245,7 +254,7 @@ describe('Device provisioning API: Update provisioned devices', function() { }); }); describe('When an update request arrives with a new Device ID', function() { - var optionsUpdate = { + const optionsUpdate = { url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices/Light1', method: 'PUT', headers: { @@ -253,7 +262,8 @@ describe('Device provisioning API: Update provisioned devices', function() { 'fiware-servicepath': '/gardens' }, json: utils.readExampleFile( - './test/unit/examples/deviceProvisioningRequests/updateProvisionDeviceWithId.json') + './test/unit/examples/deviceProvisioningRequests/updateProvisionDeviceWithId.json' + ) }; it('should raise a 400 error', function(done) { @@ -265,7 +275,7 @@ describe('Device provisioning API: Update provisioned devices', function() { }); }); describe('When a wrong update request payload arrives', function() { - var optionsUpdate = { + const optionsUpdate = { url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices/Light1', method: 'PUT', headers: { @@ -273,7 +283,8 @@ describe('Device provisioning API: Update provisioned devices', function() { 'fiware-servicepath': '/gardens' }, json: utils.readExampleFile( - './test/unit/examples/deviceProvisioningRequests/updateProvisionDeviceWrong.json') + './test/unit/examples/deviceProvisioningRequests/updateProvisionDeviceWrong.json' + ) }; it('should raise a 400 error', function(done) { @@ -286,23 +297,23 @@ describe('Device provisioning API: Update provisioned devices', function() { }); describe('When a device is provisioned without attributes and new ones are added through an update', function() { - var optionsUpdate = { - url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices/MicroLight2', - method: 'PUT', - headers: { - 'fiware-service': 'smartGondor', - 'fiware-servicepath': '/gardens' - }, - json: utils.readExampleFile('./test/unit/examples/deviceProvisioningRequests/updateMinimumDevice.json') + const optionsUpdate = { + url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices/MicroLight2', + method: 'PUT', + headers: { + 'fiware-service': 'smartGondor', + 'fiware-servicepath': '/gardens' }, - optionsGetDevice = { - url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices/MicroLight2', - method: 'GET', - headers: { - 'fiware-service': 'smartGondor', - 'fiware-servicepath': '/gardens' - } - }; + json: utils.readExampleFile('./test/unit/examples/deviceProvisioningRequests/updateMinimumDevice.json') + }; + const optionsGetDevice = { + url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices/MicroLight2', + method: 'GET', + headers: { + 'fiware-service': 'smartGondor', + 'fiware-servicepath': '/gardens' + } + }; beforeEach(function(done) { nock.cleanAll(); @@ -319,14 +330,15 @@ describe('Device provisioning API: Update provisioned devices', function() { contextBrokerMock .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', '/gardens') - .post('/v2/entities/SecondMicroLight/attrs?type=MicroLights', utils.readExampleFile( - './test/unit/ngsiv2/examples/contextRequests/updateProvisionMinimumDevice.json')) + .post( + '/v2/entities/SecondMicroLight/attrs?type=MicroLights', + utils.readExampleFile( + './test/unit/ngsiv2/examples/contextRequests/updateProvisionMinimumDevice.json' + ) + ) .reply(204); - async.series([ - iotAgentLib.clearAll, - async.apply(request, provisioning3Options) - ], done); + async.series([iotAgentLib.clearAll, async.apply(request, provisioning3Options)], done); }); it('should not raise any error', function(done) { @@ -339,11 +351,10 @@ describe('Device provisioning API: Update provisioned devices', function() { it('should provision the attributes appropriately', function(done) { request(optionsUpdate, function(error, response, body) { request(optionsGetDevice, function(error, response, body) { - var parsedBody; should.not.exist(error); response.statusCode.should.equal(200); - parsedBody = JSON.parse(body); + const parsedBody = JSON.parse(body); parsedBody.attributes.length.should.equal(1); parsedBody.attributes[0].name.should.equal('newAttribute'); @@ -361,25 +372,23 @@ describe('Device provisioning API: Update provisioned devices', function() { }); describe('When a device is updated to add static attributes', function() { - /* jshint camelcase: false */ - - var optionsUpdate = { - url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices/MicroLight2', - method: 'PUT', - headers: { - 'fiware-service': 'smartGondor', - 'fiware-servicepath': '/gardens' - }, - json: utils.readExampleFile('./test/unit/examples/deviceProvisioningRequests/updateDeviceStatic.json') + const optionsUpdate = { + url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices/MicroLight2', + method: 'PUT', + headers: { + 'fiware-service': 'smartGondor', + 'fiware-servicepath': '/gardens' }, - optionsGetDevice = { - url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices/MicroLight2', - method: 'GET', - headers: { - 'fiware-service': 'smartGondor', - 'fiware-servicepath': '/gardens' - } - }; + json: utils.readExampleFile('./test/unit/examples/deviceProvisioningRequests/updateDeviceStatic.json') + }; + const optionsGetDevice = { + url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices/MicroLight2', + method: 'GET', + headers: { + 'fiware-service': 'smartGondor', + 'fiware-servicepath': '/gardens' + } + }; beforeEach(function(done) { nock.cleanAll(); @@ -396,24 +405,24 @@ describe('Device provisioning API: Update provisioned devices', function() { contextBrokerMock .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', '/gardens') - .post('/v2/entities/SecondMicroLight/attrs?type=MicroLights', utils.readExampleFile( - './test/unit/ngsiv2/examples/contextRequests/updateProvisionDeviceStatic.json')) + .post( + '/v2/entities/SecondMicroLight/attrs?type=MicroLights', + utils.readExampleFile( + './test/unit/ngsiv2/examples/contextRequests/updateProvisionDeviceStatic.json' + ) + ) .reply(204); - async.series([ - iotAgentLib.clearAll, - async.apply(request, provisioning3Options) - ], done); + async.series([iotAgentLib.clearAll, async.apply(request, provisioning3Options)], done); }); it('should provision the attributes appropriately', function(done) { request(optionsUpdate, function(error, response, body) { request(optionsGetDevice, function(error, response, body) { - var parsedBody; should.not.exist(error); response.statusCode.should.equal(200); - parsedBody = JSON.parse(body); + const parsedBody = JSON.parse(body); parsedBody.static_attributes.length.should.equal(3); parsedBody.static_attributes[0].name.should.equal('cellID'); diff --git a/test/unit/plugins/alias-plugin_test.js b/test/unit/plugins/alias-plugin_test.js index 035bc1f35..35804e4e7 100644 --- a/test/unit/plugins/alias-plugin_test.js +++ b/test/unit/plugins/alias-plugin_test.js @@ -20,54 +20,51 @@ * For those usages not covered by the GNU Affero General Public License * please contact with::[contacto@tid.es] */ -'use strict'; -/* jshint camelcase: false */ - -var iotAgentLib = require('../../../lib/fiware-iotagent-lib'), - utils = require('../../tools/utils'), - should = require('should'), - logger = require('logops'), - nock = require('nock'), - contextBrokerMock, - iotAgentConfig = { - contextBroker: { - host: '192.168.1.1', - port: '1026' - }, - server: { - port: 4041 - }, - types: { - 'Light': { - commands: [], - type: 'Light', - lazy: [ - { - object_id: 't', - name: 'temperature', - type: 'centigrades' - } - ], - active: [ - { - object_id: 'p', - name: 'pressure', - type: 'Hgmm' - }, - { - object_id: 'l', - name: 'luminance', - type: 'lumens' - } - ] - } - }, - service: 'smartGondor', - subservice: 'gardens', - providerUrl: 'http://smartGondor.com', - deviceRegistrationDuration: 'P1M' - }; +const iotAgentLib = require('../../../lib/fiware-iotagent-lib'); +const utils = require('../../tools/utils'); +const should = require('should'); +const logger = require('logops'); +const nock = require('nock'); +let contextBrokerMock; +const iotAgentConfig = { + contextBroker: { + host: '192.168.1.1', + port: '1026' + }, + server: { + port: 4041 + }, + types: { + Light: { + commands: [], + type: 'Light', + lazy: [ + { + object_id: 't', + name: 'temperature', + type: 'centigrades' + } + ], + active: [ + { + object_id: 'p', + name: 'pressure', + type: 'Hgmm' + }, + { + object_id: 'l', + name: 'luminance', + type: 'lumens' + } + ] + } + }, + service: 'smartGondor', + subservice: 'gardens', + providerUrl: 'http://smartGondor.com', + deviceRegistrationDuration: 'P1M' +}; describe('Attribute alias plugin', function() { beforeEach(function(done) { @@ -88,7 +85,7 @@ describe('Attribute alias plugin', function() { }); }); describe('When an update comes for attributes with aliases', function() { - var values = [ + const values = [ { name: 't', type: 'centigrades', @@ -107,10 +104,14 @@ describe('Attribute alias plugin', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v1/updateContext', utils.readExampleFile( - './test/unit/examples/contextRequests/updateContextAliasPlugin.json')) - .reply(200, utils.readExampleFile( - './test/unit/examples/contextResponses/updateContextAliasPluginSuccess.json')); + .post( + '/v1/updateContext', + utils.readExampleFile('./test/unit/examples/contextRequests/updateContextAliasPlugin.json') + ) + .reply( + 200, + utils.readExampleFile('./test/unit/examples/contextResponses/updateContextAliasPluginSuccess.json') + ); }); it('should rename the attributes as expected by the mappings', function(done) { @@ -122,7 +123,7 @@ describe('Attribute alias plugin', function() { }); }); describe('When an update comes for attributes with aliases and a different type', function() { - var values = [ + const values = [ { name: 'l', type: 'lums', @@ -136,10 +137,14 @@ describe('Attribute alias plugin', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v1/updateContext', utils.readExampleFile( - './test/unit/examples/contextRequests/updateContextAliasPlugin2.json')) - .reply(200, utils.readExampleFile( - './test/unit/examples/contextResponses/updateContextAliasPlugin2Success.json')); + .post( + '/v1/updateContext', + utils.readExampleFile('./test/unit/examples/contextRequests/updateContextAliasPlugin2.json') + ) + .reply( + 200, + utils.readExampleFile('./test/unit/examples/contextResponses/updateContextAliasPlugin2Success.json') + ); }); it('should rename the attributes as expected by the mappings', function(done) { diff --git a/test/unit/plugins/bidirectional-plugin_test.js b/test/unit/plugins/bidirectional-plugin_test.js index 1b6234cdd..d137378ad 100644 --- a/test/unit/plugins/bidirectional-plugin_test.js +++ b/test/unit/plugins/bidirectional-plugin_test.js @@ -21,53 +21,54 @@ * please contact with::daniel.moranjimenez@telefonica.com */ -'use strict'; - -var iotAgentLib = require('../../../lib/fiware-iotagent-lib'), - utils = require('../../tools/utils'), - should = require('should'), - logger = require('logops'), - nock = require('nock'), - request = require('request'), - contextBrokerMock, - iotAgentConfig = { - contextBroker: { - host: '192.168.1.1', - port: '1026' - }, - server: { - port: 4041 - }, - types: { - 'Light': { - commands: [], - type: 'Light', - lazy: [ - { - name: 'temperature', - type: 'centigrades' - } - ], - active: [ - { - name: 'pressure', - type: 'Hgmm' - } - ] - } - }, - service: 'smartGondor', - subservice: 'gardens', - providerUrl: 'http://smartGondor.com', - deviceRegistrationDuration: 'P1M' - }; +/* eslint-disable no-unused-vars */ + +const iotAgentLib = require('../../../lib/fiware-iotagent-lib'); +const utils = require('../../tools/utils'); +const should = require('should'); +const logger = require('logops'); +const nock = require('nock'); +const request = require('request'); +let contextBrokerMock; +const iotAgentConfig = { + contextBroker: { + host: '192.168.1.1', + port: '1026' + }, + server: { + port: 4041 + }, + types: { + Light: { + commands: [], + type: 'Light', + lazy: [ + { + name: 'temperature', + type: 'centigrades' + } + ], + active: [ + { + name: 'pressure', + type: 'Hgmm' + } + ] + } + }, + service: 'smartGondor', + subservice: 'gardens', + providerUrl: 'http://smartGondor.com', + deviceRegistrationDuration: 'P1M' +}; describe('Bidirectional data plugin', function() { - var options = { + const options = { url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices', method: 'POST', - json: - utils.readExampleFile('./test/unit/examples/deviceProvisioningRequests/provisionBidirectionalDevice.json'), + json: utils.readExampleFile( + './test/unit/examples/deviceProvisioningRequests/provisionBidirectionalDevice.json' + ), headers: { 'fiware-service': 'smartGondor', 'fiware-servicepath': '/gardens' @@ -79,12 +80,11 @@ describe('Bidirectional data plugin', function() { iotAgentLib.activate(iotAgentConfig, function() { iotAgentLib.clearAll(function() { - iotAgentLib.addDeviceProvisionMiddleware( - iotAgentLib.dataPlugins.bidirectionalData.deviceProvision); + iotAgentLib.addDeviceProvisionMiddleware(iotAgentLib.dataPlugins.bidirectionalData.deviceProvision); iotAgentLib.addConfigurationProvisionMiddleware( - iotAgentLib.dataPlugins.bidirectionalData.groupProvision); - iotAgentLib.addNotificationMiddleware( - iotAgentLib.dataPlugins.bidirectionalData.notification); + iotAgentLib.dataPlugins.bidirectionalData.groupProvision + ); + iotAgentLib.addNotificationMiddleware(iotAgentLib.dataPlugins.bidirectionalData.notification); done(); }); }); @@ -101,19 +101,30 @@ describe('Bidirectional data plugin', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', '/gardens') - .post('/v1/subscribeContext', utils.readExampleFile( - './test/unit/examples/subscriptionRequests/bidirectionalSubscriptionRequest.json')) - .reply(200, utils.readExampleFile( - './test/unit/examples/subscriptionResponses/bidirectionalSubscriptionSuccess.json')); + .post( + '/v1/subscribeContext', + utils.readExampleFile( + './test/unit/examples/subscriptionRequests/bidirectionalSubscriptionRequest.json' + ) + ) + .reply( + 200, + utils.readExampleFile( + './test/unit/examples/subscriptionResponses/bidirectionalSubscriptionSuccess.json' + ) + ); contextBrokerMock .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', '/gardens') - .post('/v1/updateContext', utils.readExampleFile( - './test/unit/examples/contextRequests/createBidirectionalDevice.json')) - .reply(200, utils.readExampleFile( - './test/unit/examples/contextResponses/createBidirectionalDeviceSuccess.json')); - + .post( + '/v1/updateContext', + utils.readExampleFile('./test/unit/examples/contextRequests/createBidirectionalDevice.json') + ) + .reply( + 200, + utils.readExampleFile('./test/unit/examples/contextResponses/createBidirectionalDeviceSuccess.json') + ); }); it('should subscribe to the modification of the combined attribute with all the variables', function(done) { @@ -126,7 +137,7 @@ describe('Bidirectional data plugin', function() { }); describe('When a device with bidirectionality subscriptions is removed', function() { - var deleteRequest = { + const deleteRequest = { url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices/Light1', method: 'DELETE', headers: { @@ -139,26 +150,44 @@ describe('Bidirectional data plugin', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', '/gardens') - .post('/v1/subscribeContext', utils.readExampleFile( - './test/unit/examples/subscriptionRequests/bidirectionalSubscriptionRequest.json')) - .reply(200, utils.readExampleFile( - './test/unit/examples/subscriptionResponses/bidirectionalSubscriptionSuccess.json')); + .post( + '/v1/subscribeContext', + utils.readExampleFile( + './test/unit/examples/subscriptionRequests/bidirectionalSubscriptionRequest.json' + ) + ) + .reply( + 200, + utils.readExampleFile( + './test/unit/examples/subscriptionResponses/bidirectionalSubscriptionSuccess.json' + ) + ); contextBrokerMock .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', '/gardens') - .post('/v1/updateContext', utils.readExampleFile( - './test/unit/examples/contextRequests/createBidirectionalDevice.json')) - .reply(200, utils.readExampleFile( - './test/unit/examples/contextResponses/createBidirectionalDeviceSuccess.json')); + .post( + '/v1/updateContext', + utils.readExampleFile('./test/unit/examples/contextRequests/createBidirectionalDevice.json') + ) + .reply( + 200, + utils.readExampleFile('./test/unit/examples/contextResponses/createBidirectionalDeviceSuccess.json') + ); contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', '/gardens') - .post('/v1/unsubscribeContext', utils.readExampleFile( - './test/unit/examples/subscriptionRequests/simpleSubscriptionRemove.json')) - .reply(200, utils.readExampleFile( - './test/unit/examples/subscriptionResponses/bidirectionalSubscriptionSuccess.json')); + .post( + '/v1/unsubscribeContext', + utils.readExampleFile('./test/unit/examples/subscriptionRequests/simpleSubscriptionRemove.json') + ) + .reply( + 200, + utils.readExampleFile( + './test/unit/examples/subscriptionResponses/bidirectionalSubscriptionSuccess.json' + ) + ); }); it('should remove its subscriptions from the Context Broker', function(done) { @@ -173,41 +202,59 @@ describe('Bidirectional data plugin', function() { }); describe('When a notification arrives for a bidirectional attribute', function() { - var notificationOptions = { - url: 'http://localhost:' + iotAgentConfig.server.port + '/notify', - method: 'POST', - json: utils.readExampleFile('./test/unit/examples/subscriptionRequests/bidirectionalNotification.json'), - headers: { - 'fiware-service': 'smartGondor', - 'fiware-servicepath': '/gardens' - } - }, - executedHandler = false; + const notificationOptions = { + url: 'http://localhost:' + iotAgentConfig.server.port + '/notify', + method: 'POST', + json: utils.readExampleFile('./test/unit/examples/subscriptionRequests/bidirectionalNotification.json'), + headers: { + 'fiware-service': 'smartGondor', + 'fiware-servicepath': '/gardens' + } + }; + let executedHandler = false; beforeEach(function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', '/gardens') - .post('/v1/subscribeContext', utils.readExampleFile( - './test/unit/examples/subscriptionRequests/bidirectionalSubscriptionRequest.json')) - .reply(200, utils.readExampleFile( - './test/unit/examples/subscriptionResponses/bidirectionalSubscriptionSuccess.json')); + .post( + '/v1/subscribeContext', + utils.readExampleFile( + './test/unit/examples/subscriptionRequests/bidirectionalSubscriptionRequest.json' + ) + ) + .reply( + 200, + utils.readExampleFile( + './test/unit/examples/subscriptionResponses/bidirectionalSubscriptionSuccess.json' + ) + ); contextBrokerMock .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', '/gardens') - .post('/v1/updateContext', utils.readExampleFile( - './test/unit/examples/contextRequests/createBidirectionalDevice.json')) - .reply(200, utils.readExampleFile( - './test/unit/examples/contextResponses/createBidirectionalDeviceSuccess.json')); + .post( + '/v1/updateContext', + utils.readExampleFile('./test/unit/examples/contextRequests/createBidirectionalDevice.json') + ) + .reply( + 200, + utils.readExampleFile('./test/unit/examples/contextResponses/createBidirectionalDeviceSuccess.json') + ); contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', '/gardens') - .post('/v1/unsubscribeContext', utils.readExampleFile( - './test/unit/examples/subscriptionRequests/simpleSubscriptionRemove.json')) - .reply(200, utils.readExampleFile( - './test/unit/examples/subscriptionResponses/bidirectionalSubscriptionSuccess.json')); + .post( + '/v1/unsubscribeContext', + utils.readExampleFile('./test/unit/examples/subscriptionRequests/simpleSubscriptionRemove.json') + ) + .reply( + 200, + utils.readExampleFile( + './test/unit/examples/subscriptionResponses/bidirectionalSubscriptionSuccess.json' + ) + ); }); afterEach(function() { @@ -247,13 +294,13 @@ describe('Bidirectional data plugin', function() { }); it('should return the transformed values', function(done) { - var transformedHandler = false; + let transformedHandler = false; function mockedHandler(device, values, callback) { - var latitudeFound = false, - longitudeFound = false; + let latitudeFound = false; + let longitudeFound = false; - for (var i = 0; i < values.length; i++) { + for (let i = 0; i < values.length; i++) { if (values[i].name === 'latitude' && values[i].type === 'string' && values[i].value === '-9.6') { latitudeFound = true; } @@ -263,7 +310,7 @@ describe('Bidirectional data plugin', function() { } } - transformedHandler = (values.length >= 2 && longitudeFound && latitudeFound); + transformedHandler = values.length >= 2 && longitudeFound && latitudeFound; callback(); } @@ -279,44 +326,55 @@ describe('Bidirectional data plugin', function() { }); describe('When a new Group provisioning request arrives with bidirectional attributes', function() { - var provisionGroup = { - url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/services', - method: 'POST', - json: - utils.readExampleFile('./test/unit/examples/groupProvisioningRequests/bidirectionalGroup.json'), - headers: { - 'fiware-service': 'smartGondor', - 'fiware-servicepath': '/gardens' - } - }, - provisionDevice = { - url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices', - method: 'POST', - json: utils.readExampleFile( - './test/unit/examples/deviceProvisioningRequests/provisionDeviceBidirectionalGroup.json'), - headers: { - 'fiware-service': 'smartGondor', - 'fiware-servicepath': '/gardens' - } - }; + const provisionGroup = { + url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/services', + method: 'POST', + json: utils.readExampleFile('./test/unit/examples/groupProvisioningRequests/bidirectionalGroup.json'), + headers: { + 'fiware-service': 'smartGondor', + 'fiware-servicepath': '/gardens' + } + }; + const provisionDevice = { + url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices', + method: 'POST', + json: utils.readExampleFile( + './test/unit/examples/deviceProvisioningRequests/provisionDeviceBidirectionalGroup.json' + ), + headers: { + 'fiware-service': 'smartGondor', + 'fiware-servicepath': '/gardens' + } + }; beforeEach(function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', '/gardens') - .post('/v1/subscribeContext', utils.readExampleFile( - './test/unit/examples/subscriptionRequests/bidirectionalSubscriptionRequest.json')) - .reply(200, utils.readExampleFile( - './test/unit/examples/subscriptionResponses/bidirectionalSubscriptionSuccess.json')); + .post( + '/v1/subscribeContext', + utils.readExampleFile( + './test/unit/examples/subscriptionRequests/bidirectionalSubscriptionRequest.json' + ) + ) + .reply( + 200, + utils.readExampleFile( + './test/unit/examples/subscriptionResponses/bidirectionalSubscriptionSuccess.json' + ) + ); contextBrokerMock .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', '/gardens') - .post('/v1/updateContext', utils.readExampleFile( - './test/unit/examples/contextRequests/createBidirectionalDevice.json')) - .reply(200, utils.readExampleFile( - './test/unit/examples/contextResponses/createBidirectionalDeviceSuccess.json')); - + .post( + '/v1/updateContext', + utils.readExampleFile('./test/unit/examples/contextRequests/createBidirectionalDevice.json') + ) + .reply( + 200, + utils.readExampleFile('./test/unit/examples/contextResponses/createBidirectionalDeviceSuccess.json') + ); }); it('should subscribe to the modification of the combined attribute with all the variables', function(done) { request(provisionGroup, function(error, response, body) { @@ -330,53 +388,64 @@ describe('Bidirectional data plugin', function() { }); describe('When a notification arrives for a bidirectional attribute in a Configuration Group', function() { - var provisionGroup = { - url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/services', - method: 'POST', - json: - utils.readExampleFile('./test/unit/examples/groupProvisioningRequests/bidirectionalGroup.json'), - headers: { - 'fiware-service': 'smartGondor', - 'fiware-servicepath': '/gardens' - } - }, - notificationOptions = { - url: 'http://localhost:' + iotAgentConfig.server.port + '/notify', - method: 'POST', - json: utils.readExampleFile('./test/unit/examples/subscriptionRequests/bidirectionalNotification.json'), - headers: { - 'fiware-service': 'smartGondor', - 'fiware-servicepath': '/gardens' - } - }, - provisionDevice = { - url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices', - method: 'POST', - json: utils.readExampleFile( - './test/unit/examples/deviceProvisioningRequests/provisionDeviceBidirectionalGroup.json'), - headers: { - 'fiware-service': 'smartGondor', - 'fiware-servicepath': '/gardens' - } - }; + const provisionGroup = { + url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/services', + method: 'POST', + json: utils.readExampleFile('./test/unit/examples/groupProvisioningRequests/bidirectionalGroup.json'), + headers: { + 'fiware-service': 'smartGondor', + 'fiware-servicepath': '/gardens' + } + }; + const notificationOptions = { + url: 'http://localhost:' + iotAgentConfig.server.port + '/notify', + method: 'POST', + json: utils.readExampleFile('./test/unit/examples/subscriptionRequests/bidirectionalNotification.json'), + headers: { + 'fiware-service': 'smartGondor', + 'fiware-servicepath': '/gardens' + } + }; + const provisionDevice = { + url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices', + method: 'POST', + json: utils.readExampleFile( + './test/unit/examples/deviceProvisioningRequests/provisionDeviceBidirectionalGroup.json' + ), + headers: { + 'fiware-service': 'smartGondor', + 'fiware-servicepath': '/gardens' + } + }; beforeEach(function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', '/gardens') - .post('/v1/subscribeContext', utils.readExampleFile( - './test/unit/examples/subscriptionRequests/bidirectionalSubscriptionRequest.json')) - .reply(200, utils.readExampleFile( - './test/unit/examples/subscriptionResponses/bidirectionalSubscriptionSuccess.json')); + .post( + '/v1/subscribeContext', + utils.readExampleFile( + './test/unit/examples/subscriptionRequests/bidirectionalSubscriptionRequest.json' + ) + ) + .reply( + 200, + utils.readExampleFile( + './test/unit/examples/subscriptionResponses/bidirectionalSubscriptionSuccess.json' + ) + ); contextBrokerMock .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', '/gardens') - .post('/v1/updateContext', utils.readExampleFile( - './test/unit/examples/contextRequests/createBidirectionalDevice.json')) - .reply(200, utils.readExampleFile( - './test/unit/examples/contextResponses/createBidirectionalDeviceSuccess.json')); - + .post( + '/v1/updateContext', + utils.readExampleFile('./test/unit/examples/contextRequests/createBidirectionalDevice.json') + ) + .reply( + 200, + utils.readExampleFile('./test/unit/examples/contextResponses/createBidirectionalDeviceSuccess.json') + ); }); afterEach(function() { @@ -384,13 +453,13 @@ describe('Bidirectional data plugin', function() { }); it('should return the transformed values', function(done) { - var transformedHandler = false; + let transformedHandler = false; function mockedHandler(device, values, callback) { - var latitudeFound = false, - longitudeFound = false; + let latitudeFound = false; + let longitudeFound = false; - for (var i = 0; i < values.length; i++) { + for (let i = 0; i < values.length; i++) { if (values[i].name === 'latitude' && values[i].type === 'string' && values[i].value === '-9.6') { latitudeFound = true; } @@ -400,7 +469,7 @@ describe('Bidirectional data plugin', function() { } } - transformedHandler = (values.length >= 2 && longitudeFound && latitudeFound); + transformedHandler = values.length >= 2 && longitudeFound && latitudeFound; callback(); } @@ -419,11 +488,12 @@ describe('Bidirectional data plugin', function() { }); describe('Bidirectional data plugin and CB is defined using environment variables', function() { - var options = { + const options = { url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices', method: 'POST', - json: - utils.readExampleFile('./test/unit/examples/deviceProvisioningRequests/provisionBidirectionalDevice.json'), + json: utils.readExampleFile( + './test/unit/examples/deviceProvisioningRequests/provisionBidirectionalDevice.json' + ), headers: { 'fiware-service': 'smartGondor', 'fiware-servicepath': '/gardens' @@ -435,12 +505,11 @@ describe('Bidirectional data plugin and CB is defined using environment variable process.env.IOTA_CB_HOST = 'cbhost'; iotAgentLib.activate(iotAgentConfig, function() { iotAgentLib.clearAll(function() { - iotAgentLib.addDeviceProvisionMiddleware( - iotAgentLib.dataPlugins.bidirectionalData.deviceProvision); + iotAgentLib.addDeviceProvisionMiddleware(iotAgentLib.dataPlugins.bidirectionalData.deviceProvision); iotAgentLib.addConfigurationProvisionMiddleware( - iotAgentLib.dataPlugins.bidirectionalData.groupProvision); - iotAgentLib.addNotificationMiddleware( - iotAgentLib.dataPlugins.bidirectionalData.notification); + iotAgentLib.dataPlugins.bidirectionalData.groupProvision + ); + iotAgentLib.addNotificationMiddleware(iotAgentLib.dataPlugins.bidirectionalData.notification); done(); }); }); @@ -458,19 +527,30 @@ describe('Bidirectional data plugin and CB is defined using environment variable contextBrokerMock = nock('http://cbhost:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', '/gardens') - .post('/v1/subscribeContext', utils.readExampleFile( - './test/unit/examples/subscriptionRequests/bidirectionalSubscriptionRequest.json')) - .reply(200, utils.readExampleFile( - './test/unit/examples/subscriptionResponses/bidirectionalSubscriptionSuccess.json')); + .post( + '/v1/subscribeContext', + utils.readExampleFile( + './test/unit/examples/subscriptionRequests/bidirectionalSubscriptionRequest.json' + ) + ) + .reply( + 200, + utils.readExampleFile( + './test/unit/examples/subscriptionResponses/bidirectionalSubscriptionSuccess.json' + ) + ); contextBrokerMock .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', '/gardens') - .post('/v1/updateContext', utils.readExampleFile( - './test/unit/examples/contextRequests/createBidirectionalDevice.json')) - .reply(200, utils.readExampleFile( - './test/unit/examples/contextResponses/createBidirectionalDeviceSuccess.json')); - + .post( + '/v1/updateContext', + utils.readExampleFile('./test/unit/examples/contextRequests/createBidirectionalDevice.json') + ) + .reply( + 200, + utils.readExampleFile('./test/unit/examples/contextResponses/createBidirectionalDeviceSuccess.json') + ); }); it('should subscribe to the modification of the combined attribute with all the variables', function(done) { diff --git a/test/unit/plugins/capture-configuration-inPlugins_test.js b/test/unit/plugins/capture-configuration-inPlugins_test.js index d244162cc..2455b4f51 100644 --- a/test/unit/plugins/capture-configuration-inPlugins_test.js +++ b/test/unit/plugins/capture-configuration-inPlugins_test.js @@ -21,89 +21,87 @@ * please contact with::daniel.moranjimenez@telefonica.com */ -'use strict'; - -/* jshint camelcase: false */ - -var iotAgentLib = require('../../../lib/fiware-iotagent-lib'), - should = require('should'), - logger = require('logops'), - request = require('request'), - iotAgentConfig = { - contextBroker: { - host: '192.168.1.1', - port: '1026' - }, - server: { - port: 4041 - }, - types: { - 'Light': { - commands: [], - type: 'Light', +/* eslint-disable no-unused-vars */ + +const iotAgentLib = require('../../../lib/fiware-iotagent-lib'); +const should = require('should'); +const logger = require('logops'); +const request = require('request'); +const iotAgentConfig = { + contextBroker: { + host: '192.168.1.1', + port: '1026' + }, + server: { + port: 4041 + }, + types: { + Light: { + commands: [], + type: 'Light', + lazy: [ + { + name: 'temperature', + type: 'centigrades' + } + ], + active: [ + { + name: 'pressure', + type: 'Hgmm' + } + ] + } + }, + service: 'smartGondor', + subservice: 'gardens', + providerUrl: 'http://smartGondor.com', + deviceRegistrationDuration: 'P1M' +}; +const optionsCreation = { + url: 'http://localhost:4041/iot/services', + method: 'POST', + json: { + services: [ + { + resource: '/deviceTest', + apikey: '801230BJKL23Y9090DSFL123HJK09H324HV8732', + entity_type: 'SensorMachine', + trust: '8970A9078A803H3BL98PINEQRW8342HBAMS', + cbHost: 'http://unexistentHost:1026', + commands: [ + { + name: 'wheel1', + type: 'Wheel' + } + ], lazy: [ { - name: 'temperature', - type: 'centigrades' + name: 'luminescence', + type: 'Lumens' + } + ], + attributes: [ + { + name: 'status', + type: 'Boolean' } ], - active: [ + static_attributes: [ { - name: 'pressure', - type: 'Hgmm' + name: 'bootstrapServer', + type: 'Address', + value: '127.0.0.1' } ] } - }, - service: 'smartGondor', - subservice: 'gardens', - providerUrl: 'http://smartGondor.com', - deviceRegistrationDuration: 'P1M' + ] }, - optionsCreation = { - url: 'http://localhost:4041/iot/services', - method: 'POST', - json: { - services: [ - { - resource: '/deviceTest', - apikey: '801230BJKL23Y9090DSFL123HJK09H324HV8732', - entity_type: 'SensorMachine', - trust: '8970A9078A803H3BL98PINEQRW8342HBAMS', - cbHost: 'http://unexistentHost:1026', - commands: [ - { - name: 'wheel1', - type: 'Wheel' - } - ], - lazy: [ - { - name: 'luminescence', - type: 'Lumens' - } - ], - attributes: [ - { - name: 'status', - type: 'Boolean' - } - ], - static_attributes: [ - { - name: 'bootstrapServer', - type: 'Address', - value: '127.0.0.1' - } - ] - } - ] - }, - headers: { - 'fiware-service': 'TestService', - 'fiware-servicepath': '/testingPath' - } - }; + headers: { + 'fiware-service': 'TestService', + 'fiware-servicepath': '/testingPath' + } +}; describe('Data Mapping Plugins: configuration provision', function() { beforeEach(function(done) { @@ -114,7 +112,6 @@ describe('Data Mapping Plugins: configuration provision', function() { }); }); - afterEach(function(done) { iotAgentLib.clearAll(function() { iotAgentLib.deactivate(done); @@ -123,7 +120,7 @@ describe('Data Mapping Plugins: configuration provision', function() { describe('When a configuration provision request arrives to a IoTA with configuration middleware', function() { it('should execute the configuration provisioning middlewares', function(done) { - var handlerCalled = false; + let handlerCalled = false; iotAgentLib.addConfigurationProvisionMiddleware(function(newConfiguration, callback) { handlerCalled = true; @@ -138,7 +135,7 @@ describe('Data Mapping Plugins: configuration provision', function() { }); it('should still execute the configuration handlers', function(done) { - var handlerCalled = false; + let handlerCalled = false; iotAgentLib.addConfigurationProvisionMiddleware(function(newConfiguration, callback) { callback(null, newConfiguration); @@ -158,7 +155,7 @@ describe('Data Mapping Plugins: configuration provision', function() { describe('When a configuration middleware returns an error', function() { it('should not execute the configuration handlers', function(done) { - var handlerCalled = false; + let handlerCalled = false; iotAgentLib.addConfigurationProvisionMiddleware(function(newConfiguration, callback) { callback(new Error('This will prevent the handler from being executed')); diff --git a/test/unit/plugins/capture-provision-inPlugins_test.js b/test/unit/plugins/capture-provision-inPlugins_test.js index ad192f2ab..b9bd567dc 100644 --- a/test/unit/plugins/capture-provision-inPlugins_test.js +++ b/test/unit/plugins/capture-provision-inPlugins_test.js @@ -21,49 +21,49 @@ * please contact with::daniel.moranjimenez@telefonica.com */ -'use strict'; - -var iotAgentLib = require('../../../lib/fiware-iotagent-lib'), - utils = require('../../tools/utils'), - should = require('should'), - logger = require('logops'), - nock = require('nock'), - request = require('request'), - contextBrokerMock, - iotAgentConfig = { - contextBroker: { - host: '192.168.1.1', - port: '1026' - }, - server: { - port: 4041 - }, - types: { - 'Light': { - commands: [], - type: 'Light', - lazy: [ - { - name: 'temperature', - type: 'centigrades' - } - ], - active: [ - { - name: 'pressure', - type: 'Hgmm' - } - ] - } - }, - service: 'smartGondor', - subservice: 'gardens', - providerUrl: 'http://smartGondor.com', - deviceRegistrationDuration: 'P1M' - }; +/* eslint-disable no-unused-vars */ + +const iotAgentLib = require('../../../lib/fiware-iotagent-lib'); +const utils = require('../../tools/utils'); +const should = require('should'); +const logger = require('logops'); +const nock = require('nock'); +const request = require('request'); +let contextBrokerMock; +const iotAgentConfig = { + contextBroker: { + host: '192.168.1.1', + port: '1026' + }, + server: { + port: 4041 + }, + types: { + Light: { + commands: [], + type: 'Light', + lazy: [ + { + name: 'temperature', + type: 'centigrades' + } + ], + active: [ + { + name: 'pressure', + type: 'Hgmm' + } + ] + } + }, + service: 'smartGondor', + subservice: 'gardens', + providerUrl: 'http://smartGondor.com', + deviceRegistrationDuration: 'P1M' +}; describe('Data Mapping Plugins: device provision', function() { - var options = { + const options = { url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices', method: 'POST', json: utils.readExampleFile('./test/unit/examples/deviceProvisioningRequests/provisionNewDevice.json'), @@ -81,25 +81,34 @@ describe('Data Mapping Plugins: device provision', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', '/gardens') - .post('/NGSI9/registerContext', utils.readExampleFile( - './test/unit/examples/contextAvailabilityRequests/registerProvisionedDevice.json')) - .reply(200, utils.readExampleFile( - './test/unit/examples/contextAvailabilityResponses/registerProvisionedDeviceSuccess.json')); + .post( + '/NGSI9/registerContext', + utils.readExampleFile('./test/unit/examples/contextAvailabilityRequests/registerProvisionedDevice.json') + ) + .reply( + 200, + utils.readExampleFile( + './test/unit/examples/contextAvailabilityResponses/registerProvisionedDeviceSuccess.json' + ) + ); contextBrokerMock .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', '/gardens') - .post('/v1/updateContext', utils.readExampleFile( - './test/unit/examples/contextRequests/createProvisionedDevice.json')) - .reply(200, utils.readExampleFile( - './test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json')); + .post( + '/v1/updateContext', + utils.readExampleFile('./test/unit/examples/contextRequests/createProvisionedDevice.json') + ) + .reply( + 200, + utils.readExampleFile('./test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json') + ); iotAgentLib.activate(iotAgentConfig, function(error) { iotAgentLib.clearAll(done); }); }); - afterEach(function(done) { iotAgentLib.clearAll(function() { iotAgentLib.deactivate(done); @@ -108,7 +117,7 @@ describe('Data Mapping Plugins: device provision', function() { describe('When a provision request arrives to a IoTA with provisioning middleware', function() { it('should execute the translation middlewares', function(done) { - var executed = false; + let executed = false; function testMiddleware(device, callback) { executed = true; @@ -138,7 +147,7 @@ describe('Data Mapping Plugins: device provision', function() { }); it('should execute the device provisioning handlers', function(done) { - var executed = false; + let executed = false; function testMiddleware(device, callback) { callback(null, device); @@ -156,7 +165,6 @@ describe('Data Mapping Plugins: device provision', function() { executed.should.equal(true); done(); }); - }); }); @@ -175,7 +183,7 @@ describe('Data Mapping Plugins: device provision', function() { }); it('should not execute the device provisioning handlers', function(done) { - var executed = false; + let executed = false; function testMiddleware(device, callback) { callback(new Error('This provisioning should not progress')); @@ -193,7 +201,6 @@ describe('Data Mapping Plugins: device provision', function() { executed.should.equal(false); done(); }); - }); }); }); diff --git a/test/unit/plugins/compress-timestamp-plugin_test.js b/test/unit/plugins/compress-timestamp-plugin_test.js index 0a43ca5bf..0005fe5b1 100644 --- a/test/unit/plugins/compress-timestamp-plugin_test.js +++ b/test/unit/plugins/compress-timestamp-plugin_test.js @@ -21,102 +21,99 @@ * please contact with::daniel.moranjimenez@telefonica.com */ -'use strict'; - -var iotAgentLib = require('../../../lib/fiware-iotagent-lib'), - utils = require('../../tools/utils'), - should = require('should'), - logger = require('logops'), - nock = require('nock'), - contextBrokerMock, - iotAgentConfig = { - contextBroker: { - host: '192.168.1.1', - port: '1026' +const iotAgentLib = require('../../../lib/fiware-iotagent-lib'); +const utils = require('../../tools/utils'); +const should = require('should'); +const logger = require('logops'); +const nock = require('nock'); +let contextBrokerMock; +const iotAgentConfig = { + contextBroker: { + host: '192.168.1.1', + port: '1026' + }, + server: { + port: 4041 + }, + types: { + Light: { + commands: [], + type: 'Light', + lazy: [ + { + name: 'temperature', + type: 'centigrades' + } + ], + active: [ + { + name: 'pressure', + type: 'Hgmm' + } + ] }, - server: { - port: 4041 + BrokenLight: { + commands: [], + lazy: [ + { + name: 'temperature', + type: 'centigrades' + } + ], + active: [ + { + name: 'pressure', + type: 'Hgmm' + } + ] }, - types: { - 'Light': { - commands: [], - type: 'Light', - lazy: [ - { - name: 'temperature', - type: 'centigrades' - } - ], - active: [ - { - name: 'pressure', - type: 'Hgmm' - } - ] - }, - 'BrokenLight': { - commands: [], - lazy: [ - { - name: 'temperature', - type: 'centigrades' - } - ], - active: [ - { - name: 'pressure', - type: 'Hgmm' - } - ] - }, - 'Termometer': { - type: 'Termometer', - commands: [], - lazy: [ - { - name: 'temp', - type: 'kelvin' - } - ], - active: [ - ] - }, - 'Humidity': { - type: 'Humidity', - cbHost: 'http://192.168.1.1:3024', - commands: [], - lazy: [], - active: [ - { - name: 'humidity', - type: 'percentage' - } - ] - }, - 'Motion': { - type: 'Motion', - commands: [], - lazy: [], - staticAttributes: [ - { - 'name': 'location', - 'type': 'Vector', - 'value': '(123,523)' - } - ], - active: [ - { - name: 'humidity', - type: 'percentage' - } - ] - } + Termometer: { + type: 'Termometer', + commands: [], + lazy: [ + { + name: 'temp', + type: 'kelvin' + } + ], + active: [] + }, + Humidity: { + type: 'Humidity', + cbHost: 'http://192.168.1.1:3024', + commands: [], + lazy: [], + active: [ + { + name: 'humidity', + type: 'percentage' + } + ] }, - service: 'smartGondor', - subservice: 'gardens', - providerUrl: 'http://smartGondor.com', - deviceRegistrationDuration: 'P1M' - }; + Motion: { + type: 'Motion', + commands: [], + lazy: [], + staticAttributes: [ + { + name: 'location', + type: 'Vector', + value: '(123,523)' + } + ], + active: [ + { + name: 'humidity', + type: 'percentage' + } + ] + } + }, + service: 'smartGondor', + subservice: 'gardens', + providerUrl: 'http://smartGondor.com', + deviceRegistrationDuration: 'P1M' +}; describe('Timestamp compression plugin', function() { beforeEach(function(done) { @@ -137,7 +134,7 @@ describe('Timestamp compression plugin', function() { }); }); describe('When an update comes with a timestamp through the plugin', function() { - var values = [ + const values = [ { name: 'state', type: 'Boolean', @@ -156,10 +153,16 @@ describe('Timestamp compression plugin', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v1/updateContext', utils.readExampleFile( - './test/unit/examples/contextRequests/updateContextCompressTimestamp1.json')) - .reply(200, utils.readExampleFile( - './test/unit/examples/contextResponses/updateContextCompressTimestamp1Success.json')); + .post( + '/v1/updateContext', + utils.readExampleFile('./test/unit/examples/contextRequests/updateContextCompressTimestamp1.json') + ) + .reply( + 200, + utils.readExampleFile( + './test/unit/examples/contextResponses/updateContextCompressTimestamp1Success.json' + ) + ); }); it('should return an entity with all its timestamps expanded to have separators', function(done) { @@ -172,7 +175,7 @@ describe('Timestamp compression plugin', function() { }); describe('When an update comes with a timestamp through the plugin with metadatas', function() { - var values = [ + const values = [ { name: 'state', type: 'Boolean', @@ -198,10 +201,16 @@ describe('Timestamp compression plugin', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v1/updateContext', utils.readExampleFile( - './test/unit/examples/contextRequests/updateContextCompressTimestamp2.json')) - .reply(200, utils.readExampleFile( - './test/unit/examples/contextResponses/updateContextCompressTimestamp2Success.json')); + .post( + '/v1/updateContext', + utils.readExampleFile('./test/unit/examples/contextRequests/updateContextCompressTimestamp2.json') + ) + .reply( + 200, + utils.readExampleFile( + './test/unit/examples/contextResponses/updateContextCompressTimestamp2Success.json' + ) + ); }); it('should return an entity with all its timestamps expanded to have separators', function(done) { @@ -214,10 +223,7 @@ describe('Timestamp compression plugin', function() { }); describe('When a query comes for a timestamp through the plugin', function() { - var values = [ - 'state', - 'The Target Value' - ]; + const values = ['state', 'The Target Value']; beforeEach(function() { nock.cleanAll(); @@ -225,10 +231,16 @@ describe('Timestamp compression plugin', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v1/queryContext', utils.readExampleFile( - './test/unit/examples/contextRequests/queryContextCompressTimestamp1.json')) - .reply(200, utils.readExampleFile( - './test/unit/examples/contextResponses/queryContextCompressTimestamp1Success.json')); + .post( + '/v1/queryContext', + utils.readExampleFile('./test/unit/examples/contextRequests/queryContextCompressTimestamp1.json') + ) + .reply( + 200, + utils.readExampleFile( + './test/unit/examples/contextResponses/queryContextCompressTimestamp1Success.json' + ) + ); }); it('should return an entity with all its timestamps without separators (basic format)', function(done) { diff --git a/test/unit/plugins/event-plugin_test.js b/test/unit/plugins/event-plugin_test.js index ed26855ff..1537e85ce 100644 --- a/test/unit/plugins/event-plugin_test.js +++ b/test/unit/plugins/event-plugin_test.js @@ -21,45 +21,43 @@ * please contact with::daniel.moranjimenez@telefonica.com */ -'use strict'; - -var iotAgentLib = require('../../../lib/fiware-iotagent-lib'), - utils = require('../../tools/utils'), - should = require('should'), - logger = require('logops'), - nock = require('nock'), - contextBrokerMock, - iotAgentConfig = { - contextBroker: { - host: '192.168.1.1', - port: '1026' - }, - server: { - port: 4041 - }, - types: { - 'Light': { - commands: [], - type: 'Light', - lazy: [ - { - name: 'temperature', - type: 'centigrades' - } - ], - active: [ - { - name: 'pressure', - type: 'Hgmm' - } - ] - } - }, - service: 'smartGondor', - subservice: 'gardens', - providerUrl: 'http://smartGondor.com', - deviceRegistrationDuration: 'P1M' - }; +const iotAgentLib = require('../../../lib/fiware-iotagent-lib'); +const utils = require('../../tools/utils'); +const should = require('should'); +const logger = require('logops'); +const nock = require('nock'); +let contextBrokerMock; +const iotAgentConfig = { + contextBroker: { + host: '192.168.1.1', + port: '1026' + }, + server: { + port: 4041 + }, + types: { + Light: { + commands: [], + type: 'Light', + lazy: [ + { + name: 'temperature', + type: 'centigrades' + } + ], + active: [ + { + name: 'pressure', + type: 'Hgmm' + } + ] + } + }, + service: 'smartGondor', + subservice: 'gardens', + providerUrl: 'http://smartGondor.com', + deviceRegistrationDuration: 'P1M' +}; describe('Event plugin', function() { beforeEach(function(done) { @@ -80,7 +78,7 @@ describe('Event plugin', function() { }); }); describe('When an update comes with an event to the plugin', function() { - var values = [ + const values = [ { name: 'state', type: 'Boolean', @@ -100,12 +98,14 @@ describe('Event plugin', function() { .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') .post('/v1/updateContext', function(body) { - var dateRegex = /\d{4}-\d\d-\d\dT\d\d:\d\d:\d\d.\d{3}Z/; + const dateRegex = /\d{4}-\d\d-\d\dT\d\d:\d\d:\d\d.\d{3}Z/; return body.contextElements['0'].attributes['1'].value.match(dateRegex); }) - .reply(200, utils.readExampleFile( - './test/unit/examples/contextResponses/updateContextEvents1Success.json')); + .reply( + 200, + utils.readExampleFile('./test/unit/examples/contextResponses/updateContextEvents1Success.json') + ); }); it('should return an entity with all its timestamps expanded to have separators', function(done) { diff --git a/test/unit/plugins/multientity-plugin_test.js b/test/unit/plugins/multientity-plugin_test.js index 37baf52ee..9a67fc751 100644 --- a/test/unit/plugins/multientity-plugin_test.js +++ b/test/unit/plugins/multientity-plugin_test.js @@ -20,86 +20,83 @@ * For those usages not covered by the GNU Affero General Public License * please contact with::[contacto@tid.es] */ -'use strict'; - -/* jshint camelcase: false */ - -var iotAgentLib = require('../../../lib/fiware-iotagent-lib'), - utils = require('../../tools/utils'), - should = require('should'), - logger = require('logops'), - nock = require('nock'), - contextBrokerMock, - iotAgentConfig = { - contextBroker: { - host: '192.168.1.1', - port: '1026' - }, - server: { - port: 4041 + +const iotAgentLib = require('../../../lib/fiware-iotagent-lib'); +const utils = require('../../tools/utils'); +const should = require('should'); +const logger = require('logops'); +const nock = require('nock'); +let contextBrokerMock; +const iotAgentConfig = { + contextBroker: { + host: '192.168.1.1', + port: '1026' + }, + server: { + port: 4041 + }, + types: { + WeatherStation: { + commands: [], + type: 'WeatherStation', + lazy: [], + active: [ + { + object_id: 'p', + name: 'pressure', + type: 'Hgmm' + }, + { + object_id: 'h', + name: 'humidity', + type: 'Percentage', + entity_name: 'Higro2000', + entity_type: 'Higrometer' + } + ] }, - types: { - 'WeatherStation': { - commands: [], - type: 'WeatherStation', - lazy: [], - active: [ - { - object_id: 'p', - name: 'pressure', - type: 'Hgmm' - }, - { - object_id: 'h', - name: 'humidity', - type: 'Percentage', - entity_name: 'Higro2000', - entity_type: 'Higrometer' - } - ] - }, - 'WeatherStation2': { - commands: [], - type: 'WeatherStation', - lazy: [], - active: [ - { - object_id: 'p', - name: 'pressure', - type: 'Hgmm' - }, - { - object_id: 'h', - name: 'humidity', - type: 'Percentage', - entity_name: 'Higro2000', - } - ] - }, - 'WeatherStation3': { - commands: [], - type: 'WeatherStation', - lazy: [], - active: [ - { - object_id: 'p', - name: 'pressure', - type: 'Hgmm' - }, - { - object_id: 'h', - name: 'humidity', - type: 'Percentage', - entity_name: 'Station Number ${@sn * 10}', - } - ] - } + WeatherStation2: { + commands: [], + type: 'WeatherStation', + lazy: [], + active: [ + { + object_id: 'p', + name: 'pressure', + type: 'Hgmm' + }, + { + object_id: 'h', + name: 'humidity', + type: 'Percentage', + entity_name: 'Higro2000' + } + ] }, - service: 'smartGondor', - subservice: 'gardens', - providerUrl: 'http://smartGondor.com', - deviceRegistrationDuration: 'P1M' - }; + WeatherStation3: { + commands: [], + type: 'WeatherStation', + lazy: [], + active: [ + { + object_id: 'p', + name: 'pressure', + type: 'Hgmm' + }, + { + object_id: 'h', + name: 'humidity', + type: 'Percentage', + entity_name: 'Station Number ${@sn * 10}' + } + ] + } + }, + service: 'smartGondor', + subservice: 'gardens', + providerUrl: 'http://smartGondor.com', + deviceRegistrationDuration: 'P1M' +}; describe('Multi-entity plugin', function() { beforeEach(function(done) { @@ -122,7 +119,7 @@ describe('Multi-entity plugin', function() { }); describe('When an update comes for a multientity measurement', function() { - var values = [ + const values = [ { name: 'p', type: 'centigrades', @@ -141,10 +138,16 @@ describe('Multi-entity plugin', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v1/updateContext', utils.readExampleFile( - './test/unit/examples/contextRequests/updateContextMultientityPlugin1.json')) - .reply(200, utils.readExampleFile( - './test/unit/examples/contextResponses/updateContextMultientityPlugin1Success.json')); + .post( + '/v1/updateContext', + utils.readExampleFile('./test/unit/examples/contextRequests/updateContextMultientityPlugin1.json') + ) + .reply( + 200, + utils.readExampleFile( + './test/unit/examples/contextResponses/updateContextMultientityPlugin1Success.json' + ) + ); }); it('should send two context elements, one for each entity', function(done) { @@ -156,11 +159,8 @@ describe('Multi-entity plugin', function() { }); }); - - - describe('When an update comes for a multientity defined with an expression', function() { - var values = [ + const values = [ { name: 'p', type: 'centigrades', @@ -184,10 +184,16 @@ describe('Multi-entity plugin', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v1/updateContext', utils.readExampleFile( - './test/unit/examples/contextRequests/updateContextMultiEntityPlugin3.json')) - .reply(200, utils.readExampleFile( - './test/unit/examples/contextResponses/updateContextMultientityPlugin3Success.json')); + .post( + '/v1/updateContext', + utils.readExampleFile('./test/unit/examples/contextRequests/updateContextMultiEntityPlugin3.json') + ) + .reply( + 200, + utils.readExampleFile( + './test/unit/examples/contextResponses/updateContextMultientityPlugin3Success.json' + ) + ); }); it('should send the update value to the resulting value of the expression', function(done) { @@ -199,9 +205,8 @@ describe('Multi-entity plugin', function() { }); }); - describe('When an update comes for a multientity measurement without type for one entity', function() { - var values = [ + const values = [ { name: 'p', type: 'centigrades', @@ -220,10 +225,16 @@ describe('Multi-entity plugin', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v1/updateContext', utils.readExampleFile( - './test/unit/examples/contextRequests/updateContextMultientityPlugin2.json')) - .reply(200, utils.readExampleFile( - './test/unit/examples/contextResponses/updateContextMultientityPlugin2Success.json')); + .post( + '/v1/updateContext', + utils.readExampleFile('./test/unit/examples/contextRequests/updateContextMultientityPlugin2.json') + ) + .reply( + 200, + utils.readExampleFile( + './test/unit/examples/contextResponses/updateContextMultientityPlugin2Success.json' + ) + ); }); it('should use the device type as a default value', function(done) { diff --git a/test/unit/plugins/timestamp-processing-plugin_test.js b/test/unit/plugins/timestamp-processing-plugin_test.js index fac323eec..fb49b360a 100644 --- a/test/unit/plugins/timestamp-processing-plugin_test.js +++ b/test/unit/plugins/timestamp-processing-plugin_test.js @@ -21,45 +21,43 @@ * please contact with::daniel.moranjimenez@telefonica.com */ -'use strict'; - -var iotAgentLib = require('../../../lib/fiware-iotagent-lib'), - utils = require('../../tools/utils'), - should = require('should'), - logger = require('logops'), - nock = require('nock'), - contextBrokerMock, - iotAgentConfig = { - contextBroker: { - host: '192.168.1.1', - port: '1026' - }, - server: { - port: 4041 - }, - types: { - 'Light': { - commands: [], - type: 'Light', - lazy: [ - { - name: 'temperature', - type: 'centigrades' - } - ], - active: [ - { - name: 'pressure', - type: 'Hgmm' - } - ] - } - }, - service: 'smartGondor', - subservice: 'gardens', - providerUrl: 'http://smartGondor.com', - deviceRegistrationDuration: 'P1M' - }; +const iotAgentLib = require('../../../lib/fiware-iotagent-lib'); +const utils = require('../../tools/utils'); +const should = require('should'); +const logger = require('logops'); +const nock = require('nock'); +let contextBrokerMock; +const iotAgentConfig = { + contextBroker: { + host: '192.168.1.1', + port: '1026' + }, + server: { + port: 4041 + }, + types: { + Light: { + commands: [], + type: 'Light', + lazy: [ + { + name: 'temperature', + type: 'centigrades' + } + ], + active: [ + { + name: 'pressure', + type: 'Hgmm' + } + ] + } + }, + service: 'smartGondor', + subservice: 'gardens', + providerUrl: 'http://smartGondor.com', + deviceRegistrationDuration: 'P1M' +}; describe('Timestamp processing plugin', function() { beforeEach(function(done) { @@ -79,7 +77,7 @@ describe('Timestamp processing plugin', function() { }); }); describe('When an update comes with a timestamp through the plugin', function() { - var values = [ + const values = [ { name: 'state', type: 'Boolean', @@ -98,10 +96,16 @@ describe('Timestamp processing plugin', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v1/updateContext', utils.readExampleFile( - './test/unit/examples/contextRequests/updateContextProcessTimestamp1.json')) - .reply(200, utils.readExampleFile( - './test/unit/examples/contextResponses/updateContextProcessTimestamp1Success.json')); + .post( + '/v1/updateContext', + utils.readExampleFile('./test/unit/examples/contextRequests/updateContextProcessTimestamp1.json') + ) + .reply( + 200, + utils.readExampleFile( + './test/unit/examples/contextResponses/updateContextProcessTimestamp1Success.json' + ) + ); }); it('should return an entity with all its timestamps expanded to have separators', function(done) { diff --git a/test/unit/plugins/translation-inPlugins_test.js b/test/unit/plugins/translation-inPlugins_test.js index 620bf79cc..9d39ca11f 100644 --- a/test/unit/plugins/translation-inPlugins_test.js +++ b/test/unit/plugins/translation-inPlugins_test.js @@ -20,102 +20,102 @@ * For those usages not covered by the GNU Affero General Public License * please contact with::[contacto@tid.es] */ -'use strict'; -var iotAgentLib = require('../../../lib/fiware-iotagent-lib'), - utils = require('../../tools/utils'), - should = require('should'), - logger = require('logops'), - nock = require('nock'), - contextBrokerMock, - iotAgentConfig = { - contextBroker: { - host: '192.168.1.1', - port: '1026' +/* eslint-disable no-unused-vars */ + +const iotAgentLib = require('../../../lib/fiware-iotagent-lib'); +const utils = require('../../tools/utils'); +const should = require('should'); +const logger = require('logops'); +const nock = require('nock'); +let contextBrokerMock; +const iotAgentConfig = { + contextBroker: { + host: '192.168.1.1', + port: '1026' + }, + server: { + port: 4041 + }, + types: { + Light: { + commands: [], + type: 'Light', + lazy: [ + { + name: 'temperature', + type: 'centigrades' + } + ], + active: [ + { + name: 'pressure', + type: 'Hgmm' + } + ] }, - server: { - port: 4041 + BrokenLight: { + commands: [], + lazy: [ + { + name: 'temperature', + type: 'centigrades' + } + ], + active: [ + { + name: 'pressure', + type: 'Hgmm' + } + ] }, - types: { - 'Light': { - commands: [], - type: 'Light', - lazy: [ - { - name: 'temperature', - type: 'centigrades' - } - ], - active: [ - { - name: 'pressure', - type: 'Hgmm' - } - ] - }, - 'BrokenLight': { - commands: [], - lazy: [ - { - name: 'temperature', - type: 'centigrades' - } - ], - active: [ - { - name: 'pressure', - type: 'Hgmm' - } - ] - }, - 'Termometer': { - type: 'Termometer', - commands: [], - lazy: [ - { - name: 'temp', - type: 'kelvin' - } - ], - active: [ - ] - }, - 'Humidity': { - type: 'Humidity', - cbHost: 'http://192.168.1.1:3024', - commands: [], - lazy: [], - active: [ - { - name: 'humidity', - type: 'percentage' - } - ] - }, - 'Motion': { - type: 'Motion', - commands: [], - lazy: [], - staticAttributes: [ - { - 'name': 'location', - 'type': 'Vector', - 'value': '(123,523)' - } - ], - active: [ - { - name: 'humidity', - type: 'percentage' - } - ] - } + Termometer: { + type: 'Termometer', + commands: [], + lazy: [ + { + name: 'temp', + type: 'kelvin' + } + ], + active: [] }, - service: 'smartGondor', - subservice: 'gardens', - providerUrl: 'http://smartGondor.com', - deviceRegistrationDuration: 'P1M' - }; + Humidity: { + type: 'Humidity', + cbHost: 'http://192.168.1.1:3024', + commands: [], + lazy: [], + active: [ + { + name: 'humidity', + type: 'percentage' + } + ] + }, + Motion: { + type: 'Motion', + commands: [], + lazy: [], + staticAttributes: [ + { + name: 'location', + type: 'Vector', + value: '(123,523)' + } + ], + active: [ + { + name: 'humidity', + type: 'percentage' + } + ] + } + }, + service: 'smartGondor', + subservice: 'gardens', + providerUrl: 'http://smartGondor.com', + deviceRegistrationDuration: 'P1M' +}; describe('Data Mapping Plugins: translation', function() { beforeEach(function(done) { @@ -139,14 +139,15 @@ describe('Data Mapping Plugins: translation', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v1/updateContext', - utils.readExampleFile('./test/unit/examples/contextRequests/updateContextMiddleware1.json')) - .reply(200, - utils.readExampleFile('./test/unit/examples/contextResponses/updateContext1Success.json')); + .post( + '/v1/updateContext', + utils.readExampleFile('./test/unit/examples/contextRequests/updateContextMiddleware1.json') + ) + .reply(200, utils.readExampleFile('./test/unit/examples/contextResponses/updateContext1Success.json')); }); it('should execute the translation middlewares', function(done) { - var values = [ + const values = [ { name: 'state', type: 'Boolean', @@ -159,7 +160,7 @@ describe('Data Mapping Plugins: translation', function() { } ]; - var executed = false; + let executed = false; function testMiddleware(entity, typeInformation, callback) { entity.contextElements[0].attributes[1].value = entity.contextElements[0].attributes[1].value + '%'; @@ -177,7 +178,7 @@ describe('Data Mapping Plugins: translation', function() { }); it('should translate the appropriate attributes', function(done) { - var values = [ + const values = [ { name: 'state', type: 'Boolean', @@ -205,12 +206,8 @@ describe('Data Mapping Plugins: translation', function() { }); }); - describe('When a new query translation middleware is added to the IoT Agent', function() { - var attributes = [ - 'state', - 'dimming' - ]; + const attributes = ['state', 'dimming']; beforeEach(function() { nock.cleanAll(); @@ -218,14 +215,15 @@ describe('Data Mapping Plugins: translation', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v1/queryContext', - utils.readExampleFile('./test/unit/examples/contextRequests/queryContext1.json')) - .reply(200, - utils.readExampleFile('./test/unit/examples/contextResponses/queryContext1Success.json')); + .post( + '/v1/queryContext', + utils.readExampleFile('./test/unit/examples/contextRequests/queryContext1.json') + ) + .reply(200, utils.readExampleFile('./test/unit/examples/contextResponses/queryContext1Success.json')); }); it('should call the middleware', function(done) { - var called = false; + let called = false; function testMiddleware(entity, typeInformation, callback) { entity.contextResponses[0].contextElement.attributes[1].value = @@ -245,8 +243,7 @@ describe('Data Mapping Plugins: translation', function() { }); }); it('should call the middleware', function(done) { - function testMiddleware(entity, typeInformation, - callback) { + function testMiddleware(entity, typeInformation, callback) { entity.contextResponses[0].contextElement.attributes[1].value = entity.contextResponses[0].contextElement.attributes[1].value + '%'; diff --git a/test/unit/provisioning/device-group-api-test.js b/test/unit/provisioning/device-group-api-test.js index 45f9b70dc..b3d0c2e52 100644 --- a/test/unit/provisioning/device-group-api-test.js +++ b/test/unit/provisioning/device-group-api-test.js @@ -20,177 +20,175 @@ * For those usages not covered by the GNU Affero General Public License * please contact with::[contacto@tid.es] */ -'use strict'; - -/* jshint camelcase: false */ - -var iotAgentLib = require('../../../lib/fiware-iotagent-lib'), - _ = require('underscore'), - async = require('async'), - nock = require('nock'), - utils = require('../../tools/utils'), - groupRegistryMemory = require('../../../lib/services/groups/groupRegistryMemory'), - request = require('request'), - should = require('should'), - iotAgentConfig = { - logLevel: 'FATAL', - contextBroker: { - host: '192.168.1.1', - port: '1026' - }, - server: { - name: 'testAgent', - port: 4041, - baseRoot: '/' - }, - types: {}, - service: 'smartGondor', - subservice: 'gardens', - providerUrl: 'http://smartGondor.com', - deviceRegistrationDuration: 'P1M' + +/* eslint-disable no-unused-vars */ + +const iotAgentLib = require('../../../lib/fiware-iotagent-lib'); +const _ = require('underscore'); +const async = require('async'); +const nock = require('nock'); +const utils = require('../../tools/utils'); +const groupRegistryMemory = require('../../../lib/services/groups/groupRegistryMemory'); +const request = require('request'); +const should = require('should'); +const iotAgentConfig = { + logLevel: 'FATAL', + contextBroker: { + host: '192.168.1.1', + port: '1026' }, - optionsCreation = { - url: 'http://localhost:4041/iot/services', - method: 'POST', - json: { - services: [ - { - resource: '/deviceTest', - apikey: '801230BJKL23Y9090DSFL123HJK09H324HV8732', - entity_type: 'SensorMachine', - trust: '8970A9078A803H3BL98PINEQRW8342HBAMS', - cbHost: 'http://unexistentHost:1026', - commands: [ - { - name: 'wheel1', - type: 'Wheel' - } - ], - lazy: [ - { - name: 'luminescence', - type: 'Lumens' - } - ], - attributes: [ - { - name: 'status', - type: 'Boolean' - } - ], - static_attributes: [ - { - name: 'bootstrapServer', - type: 'Address', - value: '127.0.0.1' - } - ] - } - ] - }, - headers: { - 'fiware-service': 'TestService', - 'fiware-servicepath': '/testingPath' - } + server: { + name: 'testAgent', + port: 4041, + baseRoot: '/' }, - optionsDeviceCreation = { - url: 'http://localhost:4041/iot/devices', - method: 'POST', - json: utils.readExampleFile('./test/unit/examples/deviceProvisioningRequests/provisionNewDevice.json'), - headers: { - 'fiware-service': 'TestService', - 'fiware-servicepath': '/testingPath' - } + types: {}, + service: 'smartGondor', + subservice: 'gardens', + providerUrl: 'http://smartGondor.com', + deviceRegistrationDuration: 'P1M' +}; +const optionsCreation = { + url: 'http://localhost:4041/iot/services', + method: 'POST', + json: { + services: [ + { + resource: '/deviceTest', + apikey: '801230BJKL23Y9090DSFL123HJK09H324HV8732', + entity_type: 'SensorMachine', + trust: '8970A9078A803H3BL98PINEQRW8342HBAMS', + cbHost: 'http://unexistentHost:1026', + commands: [ + { + name: 'wheel1', + type: 'Wheel' + } + ], + lazy: [ + { + name: 'luminescence', + type: 'Lumens' + } + ], + attributes: [ + { + name: 'status', + type: 'Boolean' + } + ], + static_attributes: [ + { + name: 'bootstrapServer', + type: 'Address', + value: '127.0.0.1' + } + ] + } + ] }, - optionsDelete = { - url: 'http://localhost:4041/iot/services', - method: 'DELETE', - json: {}, - headers: { - 'fiware-service': 'TestService', - 'fiware-servicepath': '/testingPath' - }, - qs: { - resource: '/deviceTest', - apikey: '801230BJKL23Y9090DSFL123HJK09H324HV8732' - } + headers: { + 'fiware-service': 'TestService', + 'fiware-servicepath': '/testingPath' + } +}; +const optionsDeviceCreation = { + url: 'http://localhost:4041/iot/devices', + method: 'POST', + json: utils.readExampleFile('./test/unit/examples/deviceProvisioningRequests/provisionNewDevice.json'), + headers: { + 'fiware-service': 'TestService', + 'fiware-servicepath': '/testingPath' + } +}; +const optionsDelete = { + url: 'http://localhost:4041/iot/services', + method: 'DELETE', + json: {}, + headers: { + 'fiware-service': 'TestService', + 'fiware-servicepath': '/testingPath' }, - optionsDeleteDevice = { - url: 'http://localhost:4041/iot/services', - method: 'DELETE', - json: {}, - headers: { - 'fiware-service': 'TestService', - 'fiware-servicepath': '/testingPath' - }, - qs: { - resource: '/deviceTest', - apikey: '801230BJKL23Y9090DSFL123HJK09H324HV8732', - device: 'true' - } + qs: { + resource: '/deviceTest', + apikey: '801230BJKL23Y9090DSFL123HJK09H324HV8732' + } +}; +const optionsDeleteDevice = { + url: 'http://localhost:4041/iot/services', + method: 'DELETE', + json: {}, + headers: { + 'fiware-service': 'TestService', + 'fiware-servicepath': '/testingPath' }, - optionsUpdate = { - url: 'http://localhost:4041/iot/services', - method: 'PUT', - json: { - trust: '8970A9078A803H3BL98PINEQRW8342HBAMS', - cbHost: 'http://anotherUnexistentHost:1026', - commands: [ - { - name: 'wheel1', - type: 'Wheel' - } - ], - lazy: [ - { - name: 'luminescence', - type: 'Lumens' - } - ], - attributes: [ - { - name: 'status', - type: 'Boolean' - } - ], - static_attributes: [ - { - name: 'identifier', - type: 'UUID', - value: 'WERTYUIOP234567890' - } - ] - }, - headers: { - 'fiware-service': 'TestService', - 'fiware-servicepath': '/testingPath' - }, - qs: { - resource: '/deviceTest', - apikey: '801230BJKL23Y9090DSFL123HJK09H324HV8732' - } + qs: { + resource: '/deviceTest', + apikey: '801230BJKL23Y9090DSFL123HJK09H324HV8732', + device: 'true' + } +}; +const optionsUpdate = { + url: 'http://localhost:4041/iot/services', + method: 'PUT', + json: { + trust: '8970A9078A803H3BL98PINEQRW8342HBAMS', + cbHost: 'http://anotherUnexistentHost:1026', + commands: [ + { + name: 'wheel1', + type: 'Wheel' + } + ], + lazy: [ + { + name: 'luminescence', + type: 'Lumens' + } + ], + attributes: [ + { + name: 'status', + type: 'Boolean' + } + ], + static_attributes: [ + { + name: 'identifier', + type: 'UUID', + value: 'WERTYUIOP234567890' + } + ] }, - optionsList = { - url: 'http://localhost:4041/iot/services', - method: 'GET', - json: {}, - headers: { - 'fiware-service': 'TestService', - 'fiware-servicepath': '/*' - } + headers: { + 'fiware-service': 'TestService', + 'fiware-servicepath': '/testingPath' }, - optionsGet = { - url: 'http://localhost:4041/iot/services', - method: 'GET', - json: {}, - headers: { - 'fiware-service': 'TestService', - 'fiware-servicepath': '/testingPath' - } - }; + qs: { + resource: '/deviceTest', + apikey: '801230BJKL23Y9090DSFL123HJK09H324HV8732' + } +}; +const optionsList = { + url: 'http://localhost:4041/iot/services', + method: 'GET', + json: {}, + headers: { + 'fiware-service': 'TestService', + 'fiware-servicepath': '/*' + } +}; +const optionsGet = { + url: 'http://localhost:4041/iot/services', + method: 'GET', + json: {}, + headers: { + 'fiware-service': 'TestService', + 'fiware-servicepath': '/testingPath' + } +}; describe('Device Group Configuration API', function() { - beforeEach(function(done) { iotAgentLib.activate(iotAgentConfig, function() { groupRegistryMemory.clear(done); @@ -256,7 +254,7 @@ describe('Device Group Configuration API', function() { }); }); it('should call the configuration creation handler', function(done) { - var handlerCalled = false; + let handlerCalled = false; iotAgentLib.setConfigurationHandler(function(newConfiguration, callback) { should.exist(newConfiguration); @@ -361,15 +359,13 @@ describe('Device Group Configuration API', function() { }); it('should remove it from the configuration', function(done) { request(optionsDelete, function(error, response, body) { - /* jshint sub:true */ - - should.not.exist(iotAgentConfig.types['SensorMachine']); + should.not.exist(iotAgentConfig.types.SensorMachine); done(); }); }); }); describe('When a device group removal request arrives with device=true option', function() { - var contextBrokerMock; + let contextBrokerMock; beforeEach(function(done) { nock.cleanAll(); @@ -377,67 +373,96 @@ describe('Device Group Configuration API', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'TestService') .matchHeader('fiware-servicepath', '/testingPath') - .post('/v1/updateContext', utils.readExampleFile( - './test/unit/examples/contextRequests/createProvisionedDevice.json')) - .reply(200, utils.readExampleFile( - './test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json')); + .post( + '/v1/updateContext', + utils.readExampleFile('./test/unit/examples/contextRequests/createProvisionedDevice.json') + ) + .reply( + 200, + utils.readExampleFile('./test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json') + ); contextBrokerMock .matchHeader('fiware-service', 'TestService') .matchHeader('fiware-servicepath', '/testingPath') - .post('/NGSI9/registerContext', utils.readExampleFile( - './test/unit/examples/contextAvailabilityRequests/registerProvisionedDevice.json')) - .reply(200, utils.readExampleFile( - './test/unit/examples/contextAvailabilityResponses/registerProvisionedDeviceSuccess.json')); + .post( + '/NGSI9/registerContext', + utils.readExampleFile( + './test/unit/examples/contextAvailabilityRequests/registerProvisionedDevice.json' + ) + ) + .reply( + 200, + utils.readExampleFile( + './test/unit/examples/contextAvailabilityResponses/registerProvisionedDeviceSuccess.json' + ) + ); contextBrokerMock .matchHeader('fiware-service', 'TestService') .matchHeader('fiware-servicepath', '/testingPath') - .post('/NGSI9/registerContext', utils.readExampleFile( - './test/unit/examples/contextAvailabilityRequests/unregisterProvisionedDevice.json')) - .reply(200, - utils.readExampleFile( - './test/unit/examples/contextAvailabilityResponses/unregisterDevice1Success.json')); + .post( + '/NGSI9/registerContext', + utils.readExampleFile( + './test/unit/examples/contextAvailabilityRequests/unregisterProvisionedDevice.json' + ) + ) + .reply( + 200, + utils.readExampleFile( + './test/unit/examples/contextAvailabilityResponses/unregisterDevice1Success.json' + ) + ); contextBrokerMock .matchHeader('fiware-service', 'TestService') .matchHeader('fiware-servicepath', '/testingPath') - .post('/v1/updateContext', utils.readExampleFile( - './test/unit/examples/contextRequests/createProvisionedDevice.json')) - .reply(200, utils.readExampleFile( - './test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json')); - - async.series([ - iotAgentLib.clearAll, - async.apply(request, optionsCreation), - async.apply(request, optionsDeviceCreation) - ], done); + .post( + '/v1/updateContext', + utils.readExampleFile('./test/unit/examples/contextRequests/createProvisionedDevice.json') + ) + .reply( + 200, + utils.readExampleFile('./test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json') + ); + + async.series( + [ + iotAgentLib.clearAll, + async.apply(request, optionsCreation), + async.apply(request, optionsDeviceCreation) + ], + done + ); }); it('should remove all associated devices', function(done) { - var options = { - url: 'http://localhost:4041/iot/devices/Light1', - headers: { - 'fiware-service': 'TestService', - 'fiware-servicepath': '/testingPath' - }, - method: 'GET' - }; - - function test (error, response, body) { - response.statusCode.should.equal(404); - done(); - } - - async.series([ - async.apply(request, optionsDeleteDevice), - async.apply(request, options), - async.apply(request, options, test), - ], done); + const options = { + url: 'http://localhost:4041/iot/devices/Light1', + headers: { + 'fiware-service': 'TestService', + 'fiware-servicepath': '/testingPath' + }, + method: 'GET' + }; + + function test(error, response, body) { + response.statusCode.should.equal(404); + done(); + } + + async.series( + [ + async.apply(request, optionsDeleteDevice), + async.apply(request, options), + async.apply(request, options, test) + ], + done + ); }); it('should call the remove configuration handler', function(done) { - var handlerCalled = false; + let handlerCalled = false; iotAgentLib.setRemoveConfigurationHandler(function(newConfiguration, callback) { should.exist(newConfiguration); @@ -458,7 +483,7 @@ describe('Device Group Configuration API', function() { }); }); describe('When a device group removal arrives declaring a different service', function() { - var optionsDeleteDifferentService = _.clone(optionsDelete); + const optionsDeleteDifferentService = _.clone(optionsDelete); beforeEach(function(done) { optionsDeleteDifferentService.headers['fiware-service'] = 'unexistentService'; @@ -481,7 +506,7 @@ describe('Device Group Configuration API', function() { }); describe('When a device group removal arrives declaring a different subservice', function() { - var optionsDeleteDifferentService = _.clone(optionsDelete); + const optionsDeleteDifferentService = _.clone(optionsDelete); beforeEach(function(done) { optionsDeleteDifferentService.headers['fiware-servicepath'] = '/unexistentSubservice'; @@ -502,12 +527,12 @@ describe('Device Group Configuration API', function() { }); }); }); - + describe('When a device group removal arrives to a DB with three groups', function() { beforeEach(function(done) { - var optionsCreation1 = _.clone(optionsCreation), - optionsCreation2 = _.clone(optionsCreation), - optionsCreation3 = _.clone(optionsCreation); + const optionsCreation1 = _.clone(optionsCreation); + const optionsCreation2 = _.clone(optionsCreation); + const optionsCreation3 = _.clone(optionsCreation); optionsCreation1.json = { services: [] }; optionsCreation3.json = { services: [] }; @@ -518,11 +543,14 @@ describe('Device Group Configuration API', function() { optionsCreation1.json.services[0].apikey = 'qwertyuiop'; optionsCreation3.json.services[0].apikey = 'lkjhgfds'; - async.series([ - async.apply(request, optionsCreation1), - async.apply(request, optionsCreation2), - async.apply(request, optionsCreation3) - ], done); + async.series( + [ + async.apply(request, optionsCreation1), + async.apply(request, optionsCreation2), + async.apply(request, optionsCreation3) + ], + done + ); }); it('should remove just the selected group', function(done) { @@ -530,7 +558,7 @@ describe('Device Group Configuration API', function() { request(optionsList, function(error, response, body) { body.count.should.equal(2); - for (var i = 0; i < body.services.length; i++) { + for (let i = 0; i < body.services.length; i++) { body.services[i].apikey.should.not.equal('801230BJKL23Y9090DSFL123HJK09H324HV8732'); } @@ -583,10 +611,9 @@ describe('Device Group Configuration API', function() { describe('When a device group update request arrives', function() { beforeEach(function(done) { - var optionsCreation1 = _.clone(optionsCreation), - optionsCreation2 = _.clone(optionsCreation), - optionsCreation3 = _.clone(optionsCreation); - + const optionsCreation1 = _.clone(optionsCreation); + const optionsCreation2 = _.clone(optionsCreation); + const optionsCreation3 = _.clone(optionsCreation); optionsCreation1.json = { services: [] }; optionsCreation3.json = { services: [] }; @@ -597,11 +624,14 @@ describe('Device Group Configuration API', function() { optionsCreation1.json.services[0].apikey = 'qwertyuiop'; optionsCreation3.json.services[0].apikey = 'lkjhgfds'; - async.series([ - async.apply(request, optionsCreation1), - async.apply(request, optionsCreation2), - async.apply(request, optionsCreation3) - ], done); + async.series( + [ + async.apply(request, optionsCreation1), + async.apply(request, optionsCreation2), + async.apply(request, optionsCreation3) + ], + done + ); }); it('should return a 204 OK', function(done) { @@ -615,12 +645,14 @@ describe('Device Group Configuration API', function() { it('should update the appropriate values in the database', function(done) { request(optionsUpdate, function(error, response, body) { request(optionsList, function(error, response, body) { - var found = false; + let found = false; body.count.should.equal(3); - for (var i = 0; i < body.services.length; i++) { - if (body.services[i].apikey === '801230BJKL23Y9090DSFL123HJK09H324HV8732' && - body.services[i].resource === '/deviceTest') { + for (let i = 0; i < body.services.length; i++) { + if ( + body.services[i].apikey === '801230BJKL23Y9090DSFL123HJK09H324HV8732' && + body.services[i].resource === '/deviceTest' + ) { body.services[i].cbHost.should.equal('http://anotherUnexistentHost:1026'); body.services[i].static_attributes.length.should.equal(1); found = true; @@ -633,7 +665,7 @@ describe('Device Group Configuration API', function() { }); }); it('should call the configuration creation handler', function(done) { - var handlerCalled = false; + let handlerCalled = false; iotAgentLib.setConfigurationHandler(function(newConfiguration, callback) { should.exist(newConfiguration); @@ -665,7 +697,6 @@ describe('Device Group Configuration API', function() { optionsUpdate.headers['fiware-service'] = 'TestService'; }); - it('should return a 200 OK', function(done) { request(optionsUpdate, function(error, response, body) { should.not.exist(error); @@ -686,7 +717,6 @@ describe('Device Group Configuration API', function() { optionsUpdate.headers['fiware-servicepath'] = '/testingPath'; }); - it('should return a 200 OK', function(done) { request(optionsUpdate, function(error, response, body) { should.not.exist(error); @@ -737,10 +767,9 @@ describe('Device Group Configuration API', function() { describe('When a device group listing request arrives', function() { beforeEach(function(done) { - var optionsCreation1 = _.clone(optionsCreation), - optionsCreation2 = _.clone(optionsCreation), - optionsCreation3 = _.clone(optionsCreation); - + const optionsCreation1 = _.clone(optionsCreation); + const optionsCreation2 = _.clone(optionsCreation); + const optionsCreation3 = _.clone(optionsCreation); optionsCreation2.json = { services: [] }; optionsCreation3.json = { services: [] }; @@ -751,11 +780,14 @@ describe('Device Group Configuration API', function() { optionsCreation2.json.services[0].apikey = 'qwertyuiop'; optionsCreation3.json.services[0].apikey = 'lkjhgfds'; - async.series([ - async.apply(request, optionsCreation1), - async.apply(request, optionsCreation2), - async.apply(request, optionsCreation3) - ], done); + async.series( + [ + async.apply(request, optionsCreation1), + async.apply(request, optionsCreation2), + async.apply(request, optionsCreation3) + ], + done + ); }); it('should return a 200 OK', function(done) { @@ -778,9 +810,7 @@ describe('Device Group Configuration API', function() { describe('When a device info request arrives', function() { beforeEach(function(done) { - async.series([ - async.apply(request, optionsCreation) - ], done); + async.series([async.apply(request, optionsCreation)], done); }); it('should return a 200 OK', function(done) { @@ -799,14 +829,14 @@ describe('Device Group Configuration API', function() { }); describe('When a new device from a created group arrives to the IoT Agent and sends a measure', function() { - var contextBrokerMock, - values = [ - { - name: 'status', - type: 'String', - value: 'STARTING' - } - ]; + let contextBrokerMock; + const values = [ + { + name: 'status', + type: 'String', + value: 'STARTING' + } + ]; beforeEach(function(done) { nock.cleanAll(); @@ -814,14 +844,13 @@ describe('Device Group Configuration API', function() { contextBrokerMock = nock('http://unexistentHost:1026') .matchHeader('fiware-service', 'TestService') .matchHeader('fiware-servicepath', '/testingPath') - .post('/v1/updateContext', - utils.readExampleFile('./test/unit/examples/contextRequests/updateContext3WithStatic.json')) - .reply(200, - utils.readExampleFile('./test/unit/examples/contextResponses/updateContext1Success.json')); + .post( + '/v1/updateContext', + utils.readExampleFile('./test/unit/examples/contextRequests/updateContext3WithStatic.json') + ) + .reply(200, utils.readExampleFile('./test/unit/examples/contextResponses/updateContext1Success.json')); - async.series([ - async.apply(request, optionsCreation) - ], done); + async.series([async.apply(request, optionsCreation)], done); }); afterEach(function(done) { @@ -830,35 +859,36 @@ describe('Device Group Configuration API', function() { }); it('should use the configured data', function(done) { - iotAgentLib.update('machine1', 'SensorMachine', '801230BJKL23Y9090DSFL123HJK09H324HV8732', values, - function(error) { - should.not.exist(error); - contextBrokerMock.done(); - done(); - }); + iotAgentLib.update('machine1', 'SensorMachine', '801230BJKL23Y9090DSFL123HJK09H324HV8732', values, function( + error + ) { + should.not.exist(error); + contextBrokerMock.done(); + done(); + }); }); }); describe('When a group listing request arrives with offset and limit parameters', function() { - var optConstrainedList = { - url: 'http://localhost:4041/iot/services', - method: 'GET', - qs: { - limit: 3, - offset: 2 - }, - json: {}, - headers: { - 'fiware-service': 'TestService', - 'fiware-servicepath': '/*' - } - }; + const optConstrainedList = { + url: 'http://localhost:4041/iot/services', + method: 'GET', + qs: { + limit: 3, + offset: 2 + }, + json: {}, + headers: { + 'fiware-service': 'TestService', + 'fiware-servicepath': '/*' + } + }; beforeEach(function(done) { - var optionsCreationList = [], - creationFns = []; + const optionsCreationList = []; + const creationFns = []; - for (var i = 0; i < 10; i++) { + for (let i = 0; i < 10; i++) { optionsCreationList[i] = _.clone(optionsCreation); optionsCreationList[i].json = { services: [] }; optionsCreationList[i].json.services[0] = _.clone(optionsCreation.json.services[0]); diff --git a/test/unit/provisioning/device-group-utils_test.js b/test/unit/provisioning/device-group-utils_test.js index fa2f5a2b9..233124501 100644 --- a/test/unit/provisioning/device-group-utils_test.js +++ b/test/unit/provisioning/device-group-utils_test.js @@ -20,66 +20,64 @@ * For those usages not covered by the GNU Affero General Public License * please contact with::[contacto@tid.es] */ -'use strict'; -/* jshint camelcase: false */ +/* eslint-disable no-unused-vars */ -var iotAgentLib = require('../../../lib/fiware-iotagent-lib'), - utils = require('../../tools/utils'), - should = require('should'), - async = require('async'), - groupRegistryMemory = require('../../../lib/services/groups/groupRegistryMemory'), - request = require('request'), - groupCreation = { - url: 'http://localhost:4041/iot/services', - method: 'POST', - json: utils.readExampleFile('./test/unit/examples/groupProvisioningRequests/provisionFullGroup.json'), - headers: { - 'fiware-service': 'TestService', - 'fiware-servicepath': '/testingPath' - } +const iotAgentLib = require('../../../lib/fiware-iotagent-lib'); +const utils = require('../../tools/utils'); +const should = require('should'); +const async = require('async'); +const groupRegistryMemory = require('../../../lib/services/groups/groupRegistryMemory'); +const request = require('request'); +const groupCreation = { + url: 'http://localhost:4041/iot/services', + method: 'POST', + json: utils.readExampleFile('./test/unit/examples/groupProvisioningRequests/provisionFullGroup.json'), + headers: { + 'fiware-service': 'TestService', + 'fiware-servicepath': '/testingPath' + } +}; +const alternateGroupCreation = { + url: 'http://localhost:4041/iot/services', + method: 'POST', + json: utils.readExampleFile('./test/unit/examples/groupProvisioningRequests/provisionFullGroupAlternate.json'), + headers: { + 'fiware-service': 'TestService', + 'fiware-servicepath': '/testingPath' + } +}; +const iotAgentConfig = { + logLevel: 'FATAL', + contextBroker: { + host: '192.168.1.1', + port: '1026' + }, + server: { + port: 4041, + baseRoot: '/' }, - alternateGroupCreation = { - url: 'http://localhost:4041/iot/services', - method: 'POST', - json: utils.readExampleFile('./test/unit/examples/groupProvisioningRequests/provisionFullGroupAlternate.json'), - headers: { - 'fiware-service': 'TestService', - 'fiware-servicepath': '/testingPath' + types: { + Termometer: { + commands: [], + lazy: [ + { + name: 'temp', + type: 'kelvin' + } + ], + active: [], + apikey: '1234567890asdfghjkl', + service: 'TestService', + subservice: '/testingPath' } }, - iotAgentConfig = { - logLevel: 'FATAL', - contextBroker: { - host: '192.168.1.1', - port: '1026' - }, - server: { - port: 4041, - baseRoot: '/' - }, - types: { - 'Termometer': { - commands: [], - lazy: [ - { - name: 'temp', - type: 'kelvin' - } - ], - active: [ - ], - apikey: '1234567890asdfghjkl', - service: 'TestService', - subservice: '/testingPath' - } - }, - service: 'smartGondor', - subservice: 'gardens', - providerUrl: 'http://smartGondor.com', - deviceRegistrationDuration: 'P1M', - defaultKey: 'default1234' - }; + service: 'smartGondor', + subservice: 'gardens', + providerUrl: 'http://smartGondor.com', + deviceRegistrationDuration: 'P1M', + defaultKey: 'default1234' +}; describe('Device Group utils', function() { afterEach(function(done) { @@ -90,11 +88,14 @@ describe('Device Group utils', function() { describe('When an API Key is requested for a device in a group without the SingleConfiguration mode', function() { beforeEach(function(done) { - async.series([ - async.apply(iotAgentLib.activate, iotAgentConfig), - async.apply(request, alternateGroupCreation), - async.apply(request, groupCreation) - ], done); + async.series( + [ + async.apply(iotAgentLib.activate, iotAgentConfig), + async.apply(request, alternateGroupCreation), + async.apply(request, groupCreation) + ], + done + ); }); it('should return the API Key of the group', function(done) { iotAgentLib.getEffectiveApiKey('TestService', '/testingPath', 'AnotherMachine', function(error, apiKey) { diff --git a/test/unit/provisioning/device-provisioning-api_test.js b/test/unit/provisioning/device-provisioning-api_test.js index 2731a2662..c8272a58b 100644 --- a/test/unit/provisioning/device-provisioning-api_test.js +++ b/test/unit/provisioning/device-provisioning-api_test.js @@ -20,31 +20,31 @@ * For those usages not covered by the GNU Affero General Public License * please contact with::[contacto@tid.es] */ -'use strict'; - -var iotAgentLib = require('../../../lib/fiware-iotagent-lib'), - utils = require('../../tools/utils'), - - should = require('should'), - nock = require('nock'), - request = require('request'), - contextBrokerMock, - iotAgentConfig = { - logLevel: 'FATAL', - contextBroker: { - host: '192.168.1.1', - port: '1026' - }, - server: { - port: 4041, - baseRoot: '/' - }, - types: {}, - service: 'smartGondor', - subservice: 'gardens', - providerUrl: 'http://smartGondor.com', - deviceRegistrationDuration: 'P1M' - }; + +/* eslint-disable no-unused-vars */ + +const iotAgentLib = require('../../../lib/fiware-iotagent-lib'); +const utils = require('../../tools/utils'); +const should = require('should'); +const nock = require('nock'); +const request = require('request'); +let contextBrokerMock; +const iotAgentConfig = { + logLevel: 'FATAL', + contextBroker: { + host: '192.168.1.1', + port: '1026' + }, + server: { + port: 4041, + baseRoot: '/' + }, + types: {}, + service: 'smartGondor', + subservice: 'gardens', + providerUrl: 'http://smartGondor.com', + deviceRegistrationDuration: 'P1M' +}; describe('Device provisioning API: Provision devices', function() { beforeEach(function(done) { @@ -54,17 +54,27 @@ describe('Device provisioning API: Provision devices', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', '/gardens') - .post('/NGSI9/registerContext', utils.readExampleFile( - './test/unit/examples/contextAvailabilityRequests/registerProvisionedDevice.json')) - .reply(200, utils.readExampleFile( - './test/unit/examples/contextAvailabilityResponses/registerProvisionedDeviceSuccess.json')); + .post( + '/NGSI9/registerContext', + utils.readExampleFile( + './test/unit/examples/contextAvailabilityRequests/registerProvisionedDevice.json' + ) + ) + .reply( + 200, + utils.readExampleFile( + './test/unit/examples/contextAvailabilityResponses/registerProvisionedDeviceSuccess.json' + ) + ); contextBrokerMock .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', '/gardens') .post('/v1/updateContext') - .reply(200, utils.readExampleFile( - './test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json')); + .reply( + 200, + utils.readExampleFile('./test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json') + ); iotAgentLib.clearAll(done); }); @@ -83,21 +93,33 @@ describe('Device provisioning API: Provision devices', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', '/gardens') - .post('/NGSI9/registerContext', utils.readExampleFile( - './test/unit/examples/contextAvailabilityRequests/registerProvisionedDevice.json')) - .reply(200, utils.readExampleFile( - './test/unit/examples/contextAvailabilityResponses/registerProvisionedDeviceSuccess.json')); + .post( + '/NGSI9/registerContext', + utils.readExampleFile( + './test/unit/examples/contextAvailabilityRequests/registerProvisionedDevice.json' + ) + ) + .reply( + 200, + utils.readExampleFile( + './test/unit/examples/contextAvailabilityResponses/registerProvisionedDeviceSuccess.json' + ) + ); contextBrokerMock .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', '/gardens') - .post('/v1/updateContext', utils.readExampleFile( - './test/unit/examples/contextRequests/createProvisionedDevice.json')) - .reply(200, utils.readExampleFile( - './test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json')); + .post( + '/v1/updateContext', + utils.readExampleFile('./test/unit/examples/contextRequests/createProvisionedDevice.json') + ) + .reply( + 200, + utils.readExampleFile('./test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json') + ); }); - var options = { + const options = { url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices', method: 'POST', json: utils.readExampleFile('./test/unit/examples/deviceProvisioningRequests/provisionNewDevice.json'), @@ -120,7 +142,7 @@ describe('Device provisioning API: Provision devices', function() { }); it('should call the device provisioning handler if present', function(done) { - var handlerCalled = false; + let handlerCalled = false; iotAgentLib.setProvisioningHandler(function(device, callback) { handlerCalled = true; @@ -175,7 +197,6 @@ describe('Device provisioning API: Provision devices', function() { }); it('should store fill the device ID in case only the name is provided', function(done) { - /* jshint camelcase:false */ request(options, function(error, response, body) { response.statusCode.should.equal(201); iotAgentLib.listDevices('smartGondor', '/gardens', function(error, results) { @@ -211,7 +232,7 @@ describe('Device provisioning API: Provision devices', function() { }); }); describe('When a device provisioning request with a TimeInstant attribute arrives to the IoTA', function() { - var options = { + const options = { url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices', method: 'POST', json: utils.readExampleFile('./test/unit/examples/deviceProvisioningRequests/provisionTimeInstant.json'), @@ -237,10 +258,14 @@ describe('Device provisioning API: Provision devices', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', '/gardens') - .post('/v1/updateContext', - utils.readExampleFile('./test/unit/examples/contextRequests/createTimeinstantDevice.json')) - .reply(200, - utils.readExampleFile('./test/unit/examples/contextResponses/createTimeinstantSuccess.json')); + .post( + '/v1/updateContext', + utils.readExampleFile('./test/unit/examples/contextRequests/createTimeinstantDevice.json') + ) + .reply( + 200, + utils.readExampleFile('./test/unit/examples/contextResponses/createTimeinstantSuccess.json') + ); done(); }); @@ -254,7 +279,7 @@ describe('Device provisioning API: Provision devices', function() { }); describe('When a device provisioning request with the minimum required data arrives to the IoT Agent', function() { - var options = { + const options = { url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices', method: 'POST', json: utils.readExampleFile('./test/unit/examples/deviceProvisioningRequests/provisionMinimumDevice.json'), @@ -269,10 +294,14 @@ describe('Device provisioning API: Provision devices', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', '/gardens') - .post('/v1/updateContext', - utils.readExampleFile('./test/unit/examples/contextRequests/createMinimumProvisionedDevice.json')) - .reply(200, - utils.readExampleFile('./test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json')); + .post( + '/v1/updateContext', + utils.readExampleFile('./test/unit/examples/contextRequests/createMinimumProvisionedDevice.json') + ) + .reply( + 200, + utils.readExampleFile('./test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json') + ); done(); }); @@ -310,7 +339,7 @@ describe('Device provisioning API: Provision devices', function() { }); describe('When a device provisioning request with geo:point attributes arrives', function() { - var options = { + const options = { url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices', method: 'POST', json: utils.readExampleFile('./test/unit/examples/deviceProvisioningRequests/provisionGeopointDevice.json'), @@ -325,12 +354,16 @@ describe('Device provisioning API: Provision devices', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', '/gardens') - .post('/v1/updateContext', + .post( + '/v1/updateContext', + utils.readExampleFile('./test/unit/examples/contextRequests/createGeopointProvisionedDevice.json') + ) + .reply( + 200, utils.readExampleFile( - './test/unit/examples/contextRequests/createGeopointProvisionedDevice.json')) - .reply(200, - utils.readExampleFile( - './test/unit/examples/contextResponses/createGeopointProvisionedDeviceSuccess.json')); + './test/unit/examples/contextResponses/createGeopointProvisionedDeviceSuccess.json' + ) + ); done(); }); @@ -344,7 +377,7 @@ describe('Device provisioning API: Provision devices', function() { }); describe('When a device provisioning request with DateTime attributes arrives', function() { - var options = { + const options = { url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices', method: 'POST', json: utils.readExampleFile('./test/unit/examples/deviceProvisioningRequests/provisionDatetimeDevice.json'), @@ -359,12 +392,16 @@ describe('Device provisioning API: Provision devices', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', '/gardens') - .post('/v1/updateContext', - utils.readExampleFile( - './test/unit/examples/contextRequests/createDatetimeProvisionedDevice.json')) - .reply(200, + .post( + '/v1/updateContext', + utils.readExampleFile('./test/unit/examples/contextRequests/createDatetimeProvisionedDevice.json') + ) + .reply( + 200, utils.readExampleFile( - './test/unit/examples/contextResponses/createDatetimeProvisionedDeviceSuccess.json')); + './test/unit/examples/contextResponses/createDatetimeProvisionedDeviceSuccess.json' + ) + ); done(); }); @@ -377,43 +414,47 @@ describe('Device provisioning API: Provision devices', function() { }); }); - describe('When two devices with the same ID but different services arrive to the agent', function() { - var options1 = { - url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices', - method: 'POST', - json: utils.readExampleFile( - './test/unit/examples/deviceProvisioningRequests/provisionMinimumDevice.json'), - headers: { - 'fiware-service': 'smartGondor', - 'fiware-servicepath': '/gardens' - } - }, - options2 = { - url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices', - method: 'POST', - json: utils.readExampleFile( - './test/unit/examples/deviceProvisioningRequests/provisionMinimumDevice.json'), - headers: { - 'fiware-service': 'smartMordor', - 'fiware-servicepath': '/electricity' - } - }; + const options1 = { + url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices', + method: 'POST', + json: utils.readExampleFile('./test/unit/examples/deviceProvisioningRequests/provisionMinimumDevice.json'), + headers: { + 'fiware-service': 'smartGondor', + 'fiware-servicepath': '/gardens' + } + }; + const options2 = { + url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices', + method: 'POST', + json: utils.readExampleFile('./test/unit/examples/deviceProvisioningRequests/provisionMinimumDevice.json'), + headers: { + 'fiware-service': 'smartMordor', + 'fiware-servicepath': '/electricity' + } + }; beforeEach(function(done) { nock.cleanAll(); contextBrokerMock = nock('http://192.168.1.1:1026') - .post('/v1/updateContext', - utils.readExampleFile('./test/unit/examples/contextRequests/createMinimumProvisionedDevice.json')) - .reply(200, - utils.readExampleFile('./test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json')); - + .post( + '/v1/updateContext', + utils.readExampleFile('./test/unit/examples/contextRequests/createMinimumProvisionedDevice.json') + ) + .reply( + 200, + utils.readExampleFile('./test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json') + ); contextBrokerMock - .post('/v1/updateContext', - utils.readExampleFile('./test/unit/examples/contextRequests/createMinimumProvisionedDevice.json')) - .reply(200, - utils.readExampleFile('./test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json')); + .post( + '/v1/updateContext', + utils.readExampleFile('./test/unit/examples/contextRequests/createMinimumProvisionedDevice.json') + ) + .reply( + 200, + utils.readExampleFile('./test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json') + ); done(); }); @@ -448,7 +489,7 @@ describe('Device provisioning API: Provision devices', function() { }); describe('When there is a connection error with a String code connecting the CB', function() { - var options = { + const options = { url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices', method: 'POST', json: utils.readExampleFile('./test/unit/examples/deviceProvisioningRequests/provisionMinimumDevice.json'), @@ -465,15 +506,18 @@ describe('Device provisioning API: Provision devices', function() { .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', '/gardens') .post('/NGSI9/registerContext') - .reply(200, + .reply( + 200, utils.readExampleFile( - './test/unit/examples/contextAvailabilityResponses/registerProvisionedDeviceSuccess.json')); + './test/unit/examples/contextAvailabilityResponses/registerProvisionedDeviceSuccess.json' + ) + ); contextBrokerMock .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', '/gardens') .post('/v1/updateContext') - .replyWithError({'message': 'Description of the error', 'code': 'STRING_CODE'}); + .replyWithError({ message: 'Description of the error', code: 'STRING_CODE' }); done(); }); @@ -489,7 +533,7 @@ describe('Device provisioning API: Provision devices', function() { }); describe('When there is a connection error with a Number code connecting the CB', function() { - var options = { + const options = { url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices', method: 'POST', json: utils.readExampleFile('./test/unit/examples/deviceProvisioningRequests/provisionMinimumDevice.json'), @@ -506,15 +550,18 @@ describe('Device provisioning API: Provision devices', function() { .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', '/gardens') .post('/NGSI9/registerContext') - .reply(200, + .reply( + 200, utils.readExampleFile( - './test/unit/examples/contextAvailabilityResponses/registerProvisionedDeviceSuccess.json')); + './test/unit/examples/contextAvailabilityResponses/registerProvisionedDeviceSuccess.json' + ) + ); contextBrokerMock .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', '/gardens') .post('/v1/updateContext') - .replyWithError({'message': 'Description of the error', 'code': 123456789}); + .replyWithError({ message: 'Description of the error', code: 123456789 }); done(); }); @@ -530,7 +577,7 @@ describe('Device provisioning API: Provision devices', function() { }); describe('When a device provisioning request with missing data arrives to the IoT Agent', function() { - var options = { + const options = { url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices', method: 'POST', headers: { @@ -538,7 +585,8 @@ describe('Device provisioning API: Provision devices', function() { 'fiware-servicepath': '/gardens' }, json: utils.readExampleFile( - './test/unit/examples/deviceProvisioningRequests/provisionDeviceMissingParameters.json') + './test/unit/examples/deviceProvisioningRequests/provisionDeviceMissingParameters.json' + ) }; it('should raise a MISSING_ATTRIBUTES error, indicating the missing attributes', function(done) { @@ -552,7 +600,7 @@ describe('Device provisioning API: Provision devices', function() { }); }); describe('When two device provisioning requests with the same service and Device ID arrive', function() { - var options = { + const options = { url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices', method: 'POST', json: utils.readExampleFile('./test/unit/examples/deviceProvisioningRequests/provisionNewDevice.json'), @@ -566,18 +614,27 @@ describe('Device provisioning API: Provision devices', function() { contextBrokerMock .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', '/gardens') - .post('/NGSI9/registerContext', utils.readExampleFile( - './test/unit/examples/contextAvailabilityRequests/registerProvisionedDevice.json')) - .reply(200, utils.readExampleFile( - './test/unit/examples/contextAvailabilityResponses/registerProvisionedDeviceSuccess.json')); + .post( + '/NGSI9/registerContext', + utils.readExampleFile( + './test/unit/examples/contextAvailabilityRequests/registerProvisionedDevice.json' + ) + ) + .reply( + 200, + utils.readExampleFile( + './test/unit/examples/contextAvailabilityResponses/registerProvisionedDeviceSuccess.json' + ) + ); contextBrokerMock .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', '/gardens') .post('/v1/updateContext') - .reply(200, - utils.readExampleFile( - './test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json')); + .reply( + 200, + utils.readExampleFile('./test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json') + ); done(); }); @@ -594,11 +651,12 @@ describe('Device provisioning API: Provision devices', function() { }); }); describe('When a device provisioning request is malformed', function() { - var options = { + const options = { url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices', method: 'POST', json: utils.readExampleFile( - './test/unit/examples/deviceProvisioningRequests/provisionNewDeviceMalformed1.json'), + './test/unit/examples/deviceProvisioningRequests/provisionNewDeviceMalformed1.json' + ), headers: { 'fiware-service': 'smartGondor', 'fiware-servicepath': '/gardens' @@ -617,7 +675,7 @@ describe('Device provisioning API: Provision devices', function() { }); }); describe('When an agent is activated with a different base root', function() { - var options = { + const options = { url: 'http://localhost:' + iotAgentConfig.server.port + '/newBaseRoot/iot/devices', method: 'POST', headers: { @@ -651,12 +709,13 @@ describe('Device provisioning API: Provision devices', function() { }); }); describe('When a device provisioning request without the mandatory headers arrives to the Agent', function() { - var options = { + const options = { url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices', method: 'POST', headers: {}, json: utils.readExampleFile( - './test/unit/examples/deviceProvisioningRequests/provisionDeviceMissingParameters.json') + './test/unit/examples/deviceProvisioningRequests/provisionDeviceMissingParameters.json' + ) }; it('should raise a MISSING_HEADERS error, indicating the missing attributes', function(done) { @@ -669,21 +728,21 @@ describe('Device provisioning API: Provision devices', function() { }); }); describe('When a device delete request arrives to the Agent for a not existing device', function() { - var options = { - url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices/Light84', - headers: { - 'fiware-service': 'smartGondor', - 'fiware-servicepath': '/gardens' - }, - method: 'DELETE' - }; - - it('should return a 404 error', function(done) { - request(options, function(error, response, body) { - should.not.exist(error); - response.statusCode.should.equal(404); - done(); - }); - }); + const options = { + url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices/Light84', + headers: { + 'fiware-service': 'smartGondor', + 'fiware-servicepath': '/gardens' + }, + method: 'DELETE' + }; + + it('should return a 404 error', function(done) { + request(options, function(error, response, body) { + should.not.exist(error); + response.statusCode.should.equal(404); + done(); + }); + }); }); }); diff --git a/test/unit/provisioning/device-registration_test.js b/test/unit/provisioning/device-registration_test.js index 837aa4869..110226483 100644 --- a/test/unit/provisioning/device-registration_test.js +++ b/test/unit/provisioning/device-registration_test.js @@ -20,72 +20,72 @@ * For those usages not covered by the GNU Affero General Public License * please contact with::[contacto@tid.es] */ -'use strict'; - -var iotAgentLib = require('../../../lib/fiware-iotagent-lib'), - utils = require('../../tools/utils'), - should = require('should'), - logger = require('logops'), - nock = require('nock'), - async = require('async'), - contextBrokerMock, - iotAgentConfig = { - contextBroker: { - host: '192.168.1.1', - port: '1026' - }, - server: { - port: 4041 - }, - types: { - 'Light': { - commands: [], - lazy: [ - { - name: 'temperature', - type: 'centigrades' - } - ], - active: [ - { - name: 'pressure', - type: 'Hgmm' - } - ], - service: 'smartGondor', - subservice: 'gardens' - }, - 'Termometer': { - commands: [], - lazy: [ - { - name: 'temp', - type: 'kelvin' - } - ], - active: [ - ], - service: 'smartGondor', - subservice: 'gardens' - } - }, - service: 'smartGondor', - subservice: 'gardens', - providerUrl: 'http://smartGondor.com', - deviceRegistrationDuration: 'P1M' + +/* eslint-disable no-unused-vars */ + +const iotAgentLib = require('../../../lib/fiware-iotagent-lib'); +const utils = require('../../tools/utils'); +const should = require('should'); +const logger = require('logops'); +const nock = require('nock'); +const async = require('async'); +let contextBrokerMock; +const iotAgentConfig = { + contextBroker: { + host: '192.168.1.1', + port: '1026' + }, + server: { + port: 4041 }, - device1 = { - id: 'light1', - type: 'Light', - service: 'smartGondor', - subservice: 'gardens' + types: { + Light: { + commands: [], + lazy: [ + { + name: 'temperature', + type: 'centigrades' + } + ], + active: [ + { + name: 'pressure', + type: 'Hgmm' + } + ], + service: 'smartGondor', + subservice: 'gardens' + }, + Termometer: { + commands: [], + lazy: [ + { + name: 'temp', + type: 'kelvin' + } + ], + active: [], + service: 'smartGondor', + subservice: 'gardens' + } }, - device2 = { - id: 'term2', - type: 'Termometer', - service: 'smartGondor', - subservice: 'gardens' - }; + service: 'smartGondor', + subservice: 'gardens', + providerUrl: 'http://smartGondor.com', + deviceRegistrationDuration: 'P1M' +}; +const device1 = { + id: 'light1', + type: 'Light', + service: 'smartGondor', + subservice: 'gardens' +}; +const device2 = { + id: 'term2', + type: 'Termometer', + service: 'smartGondor', + subservice: 'gardens' +}; describe('IoT Agent Device Registration', function() { beforeEach(function() { @@ -93,7 +93,7 @@ describe('IoT Agent Device Registration', function() { }); afterEach(function(done) { - delete(device1.registrationId); + delete device1.registrationId; iotAgentLib.clearAll(function() { iotAgentLib.deactivate(done); }); @@ -106,17 +106,25 @@ describe('IoT Agent Device Registration', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/NGSI9/registerContext', utils.readExampleFile( - './test/unit/examples/contextAvailabilityRequests/registerIoTAgent1.json')) - .reply(200, utils.readExampleFile( - './test/unit/examples/contextAvailabilityResponses/registerIoTAgent1Success.json')); + .post( + '/NGSI9/registerContext', + utils.readExampleFile('./test/unit/examples/contextAvailabilityRequests/registerIoTAgent1.json') + ) + .reply( + 200, + utils.readExampleFile( + './test/unit/examples/contextAvailabilityResponses/registerIoTAgent1Success.json' + ) + ); contextBrokerMock .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') .post('/v1/updateContext') - .reply(200, utils.readExampleFile( - './test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json')); + .reply( + 200, + utils.readExampleFile('./test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json') + ); iotAgentLib.activate(iotAgentConfig, function(error) { iotAgentLib.clearAll(done); @@ -125,9 +133,9 @@ describe('IoT Agent Device Registration', function() { it('should register as ContextProvider of its lazy attributes', function(done) { iotAgentLib.register(device1, function(error) { - should.not.exist(error); - contextBrokerMock.done(); - done(); + should.not.exist(error); + contextBrokerMock.done(); + done(); }); }); }); @@ -139,10 +147,16 @@ describe('IoT Agent Device Registration', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/NGSI9/registerContext', utils.readExampleFile( - './test/unit/examples/contextAvailabilityRequests/registerIoTAgent1.json')) - .reply(200, utils.readExampleFile( - './test/unit/examples/contextAvailabilityResponses/registerIoTAgent1Failed.json')); + .post( + '/NGSI9/registerContext', + utils.readExampleFile('./test/unit/examples/contextAvailabilityRequests/registerIoTAgent1.json') + ) + .reply( + 200, + utils.readExampleFile( + './test/unit/examples/contextAvailabilityResponses/registerIoTAgent1Failed.json' + ) + ); iotAgentLib.activate(iotAgentConfig, function(error) { iotAgentLib.clearAll(done); @@ -166,10 +180,16 @@ describe('IoT Agent Device Registration', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/NGSI9/registerContext', utils.readExampleFile( - './test/unit/examples/contextAvailabilityRequests/registerIoTAgent1.json')) - .reply(500, utils.readExampleFile( - './test/unit/examples/contextAvailabilityResponses/registerIoTAgent1Failed.json')); + .post( + '/NGSI9/registerContext', + utils.readExampleFile('./test/unit/examples/contextAvailabilityRequests/registerIoTAgent1.json') + ) + .reply( + 500, + utils.readExampleFile( + './test/unit/examples/contextAvailabilityResponses/registerIoTAgent1Failed.json' + ) + ); iotAgentLib.activate(iotAgentConfig, function(error) { iotAgentLib.clearAll(done); @@ -195,24 +215,32 @@ describe('IoT Agent Device Registration', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/NGSI9/registerContext', utils.readExampleFile( - './test/unit/examples/contextAvailabilityRequests/registerIoTAgent1.json')) - .reply(200, utils.readExampleFile( - './test/unit/examples/contextAvailabilityResponses/registerIoTAgent1Success.json')); + .post( + '/NGSI9/registerContext', + utils.readExampleFile('./test/unit/examples/contextAvailabilityRequests/registerIoTAgent1.json') + ) + .reply( + 200, + utils.readExampleFile( + './test/unit/examples/contextAvailabilityResponses/registerIoTAgent1Success.json' + ) + ); contextBrokerMock .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') .post('/v1/updateContext') - .reply(200, utils.readExampleFile( - './test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json')); + .reply( + 200, + utils.readExampleFile('./test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json') + ); iotAgentLib.activate(iotAgentConfig, function(error) { iotAgentLib.clearAll(done); }); }); - it('should return all the device\'s information', function(done) { + it("should return all the device's information", function(done) { iotAgentLib.register(device1, function(error) { iotAgentLib.getDevice('light1', 'smartGondor', 'gardens', function(error, data) { should.not.exist(error); @@ -232,10 +260,16 @@ describe('IoT Agent Device Registration', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/NGSI9/registerContext', utils.readExampleFile( - './test/unit/examples/contextAvailabilityRequests/registerIoTAgent1.json')) - .reply(200, utils.readExampleFile( - './test/unit/examples/contextAvailabilityResponses/registerIoTAgent1Success.json')); + .post( + '/NGSI9/registerContext', + utils.readExampleFile('./test/unit/examples/contextAvailabilityRequests/registerIoTAgent1.json') + ) + .reply( + 200, + utils.readExampleFile( + './test/unit/examples/contextAvailabilityResponses/registerIoTAgent1Success.json' + ) + ); iotAgentLib.activate(iotAgentConfig, function(error) { iotAgentLib.clearAll(done); @@ -257,44 +291,61 @@ describe('IoT Agent Device Registration', function() { describe('When a device is removed from the IoT Agent', function() { beforeEach(function(done) { - var expectedPayload3 = utils - .readExampleFile('./test/unit/examples/contextAvailabilityRequests/unregisterDevice1.json'); + const expectedPayload3 = utils.readExampleFile( + './test/unit/examples/contextAvailabilityRequests/unregisterDevice1.json' + ); nock.cleanAll(); contextBrokerMock = nock('http://192.168.1.1:1026') .post('/NGSI9/registerContext') - .reply(200, utils.readExampleFile( - './test/unit/examples/contextAvailabilityResponses/registerNewDevice1Success.json')); + .reply( + 200, + utils.readExampleFile( + './test/unit/examples/contextAvailabilityResponses/registerNewDevice1Success.json' + ) + ); contextBrokerMock .post('/v1/updateContext') - .reply(200, - utils.readExampleFile( - './test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json')); + .reply( + 200, + utils.readExampleFile('./test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json') + ); contextBrokerMock .post('/NGSI9/registerContext') - .reply(200, utils.readExampleFile( - './test/unit/examples/contextAvailabilityResponses/registerNewDevice2Success.json')); + .reply( + 200, + utils.readExampleFile( + './test/unit/examples/contextAvailabilityResponses/registerNewDevice2Success.json' + ) + ); contextBrokerMock .post('/v1/updateContext') - .reply(200, - utils.readExampleFile( - './test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json')); + .reply( + 200, + utils.readExampleFile('./test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json') + ); contextBrokerMock .post('/NGSI9/registerContext', expectedPayload3) - .reply(200, utils.readExampleFile( - './test/unit/examples/contextAvailabilityResponses/unregisterDevice1Success.json')); - + .reply( + 200, + utils.readExampleFile( + './test/unit/examples/contextAvailabilityResponses/unregisterDevice1Success.json' + ) + ); iotAgentLib.activate(iotAgentConfig, function(error) { - async.series([ - async.apply(iotAgentLib.clearAll), - async.apply(iotAgentLib.register, device1), - async.apply(iotAgentLib.register, device2) - ], done); + async.series( + [ + async.apply(iotAgentLib.clearAll), + async.apply(iotAgentLib.register, device1), + async.apply(iotAgentLib.register, device2) + ], + done + ); }); }); @@ -309,43 +360,61 @@ describe('IoT Agent Device Registration', function() { describe('When the Context Broker returns an error while unregistering a device', function() { beforeEach(function(done) { - var expectedPayload3 = utils - .readExampleFile('./test/unit/examples/contextAvailabilityRequests/unregisterDevice1.json'); + const expectedPayload3 = utils.readExampleFile( + './test/unit/examples/contextAvailabilityRequests/unregisterDevice1.json' + ); nock.cleanAll(); contextBrokerMock = nock('http://192.168.1.1:1026') .post('/NGSI9/registerContext') - .reply(200, utils.readExampleFile( - './test/unit/examples/contextAvailabilityResponses/registerNewDevice1Success.json')); + .reply( + 200, + utils.readExampleFile( + './test/unit/examples/contextAvailabilityResponses/registerNewDevice1Success.json' + ) + ); contextBrokerMock .post('/v1/updateContext') - .reply(200, - utils.readExampleFile( - './test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json')); + .reply( + 200, + utils.readExampleFile('./test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json') + ); contextBrokerMock .post('/NGSI9/registerContext') - .reply(200, utils.readExampleFile( - './test/unit/examples/contextAvailabilityResponses/registerNewDevice2Success.json')); + .reply( + 200, + utils.readExampleFile( + './test/unit/examples/contextAvailabilityResponses/registerNewDevice2Success.json' + ) + ); contextBrokerMock .post('/v1/updateContext') - .reply(200, - utils.readExampleFile( - './test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json')); + .reply( + 200, + utils.readExampleFile('./test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json') + ); contextBrokerMock .post('/NGSI9/registerContext', expectedPayload3) - .reply(500, utils.readExampleFile( - './test/unit/examples/contextAvailabilityResponses/unregisterDevice1Failed.json')); + .reply( + 500, + utils.readExampleFile( + './test/unit/examples/contextAvailabilityResponses/unregisterDevice1Failed.json' + ) + ); iotAgentLib.activate(iotAgentConfig, function(error) { - async.series([ - async.apply(iotAgentLib.clearAll), - async.apply(iotAgentLib.register, device1), - async.apply(iotAgentLib.register, device2) - ], done); + async.series( + [ + async.apply(iotAgentLib.clearAll), + async.apply(iotAgentLib.register, device1), + async.apply(iotAgentLib.register, device2) + ], + done + ); }); }); diff --git a/test/unit/provisioning/device-update-registration_test.js b/test/unit/provisioning/device-update-registration_test.js index cf552b243..d9ed9e692 100644 --- a/test/unit/provisioning/device-update-registration_test.js +++ b/test/unit/provisioning/device-update-registration_test.js @@ -20,116 +20,116 @@ * For those usages not covered by the GNU Affero General Public License * please contact with::[contacto@tid.es] */ -'use strict'; -var iotAgentLib = require('../../../lib/fiware-iotagent-lib'), - utils = require('../../tools/utils'), - should = require('should'), - logger = require('logops'), - nock = require('nock'), - contextBrokerMock, - iotAgentConfig = { - contextBroker: { - host: '192.168.1.1', - port: '1026' - }, - server: { - port: 4041 - }, - types: { - 'Light': { - commands: [], - lazy: [ - { - name: 'temperature', - type: 'centigrades' - } - ], - active: [ - { - name: 'pressure', - type: 'Hgmm' - } - ], - service: 'smartGondor', - subservice: 'gardens' - }, - 'Termometer': { - commands: [], - lazy: [ - { - name: 'temp', - type: 'kelvin' - } - ], - active: [ - ], - service: 'smartGondor', - subservice: 'gardens' - } - }, - service: 'smartGondor', - subservice: 'gardens', - providerUrl: 'http://smartGondor.com', - deviceRegistrationDuration: 'P1M' - }, - device1 = { - id: 'light1', - type: 'Light', - service: 'smartGondor', - subservice: 'gardens', +/* eslint-disable no-unused-vars */ + +const iotAgentLib = require('../../../lib/fiware-iotagent-lib'); +const utils = require('../../tools/utils'); +const should = require('should'); +const logger = require('logops'); +const nock = require('nock'); +let contextBrokerMock; +const iotAgentConfig = { + contextBroker: { + host: '192.168.1.1', + port: '1026' }, - deviceUpdated = { - id: 'light1', - type: 'Light', - name: 'light1', - service: 'smartGondor', - subservice: 'gardens', - internalId: 'newInternalId', - lazy: [ - { - name: 'pressure', - type: 'Hgmm' - } - ], - active: [ - { - name: 'temperature', - type: 'centigrades' - } - ] + server: { + port: 4041 }, - deviceCommandUpdated = { - id: 'light1', - type: 'Light', - name: 'light1', - service: 'smartGondor', - subservice: 'gardens', - internalId: 'newInternalId', - commands: [ - { - name: 'move', - type: 'command' - } - ], - active: [ - { - name: 'temperature', - type: 'centigrades' - } - ] + types: { + Light: { + commands: [], + lazy: [ + { + name: 'temperature', + type: 'centigrades' + } + ], + active: [ + { + name: 'pressure', + type: 'Hgmm' + } + ], + service: 'smartGondor', + subservice: 'gardens' + }, + Termometer: { + commands: [], + lazy: [ + { + name: 'temp', + type: 'kelvin' + } + ], + active: [], + service: 'smartGondor', + subservice: 'gardens' + } }, - unknownDevice = { - id: 'rotationSensor4', - type: 'Rotation', - name: 'Rotation4', - service: 'dumbMordor', - subservice: 'gardens', - internalId: 'unknownInternalId', + service: 'smartGondor', + subservice: 'gardens', + providerUrl: 'http://smartGondor.com', + deviceRegistrationDuration: 'P1M' +}; +const device1 = { + id: 'light1', + type: 'Light', + service: 'smartGondor', + subservice: 'gardens' +}; +const deviceUpdated = { + id: 'light1', + type: 'Light', + name: 'light1', + service: 'smartGondor', + subservice: 'gardens', + internalId: 'newInternalId', + lazy: [ + { + name: 'pressure', + type: 'Hgmm' + } + ], + active: [ + { + name: 'temperature', + type: 'centigrades' + } + ] +}; +const deviceCommandUpdated = { + id: 'light1', + type: 'Light', + name: 'light1', + service: 'smartGondor', + subservice: 'gardens', + internalId: 'newInternalId', + commands: [ + { + name: 'move', + type: 'command' + } + ], + active: [ + { + name: 'temperature', + type: 'centigrades' + } + ] +}; +const unknownDevice = { + id: 'rotationSensor4', + type: 'Rotation', + name: 'Rotation4', + service: 'dumbMordor', + subservice: 'gardens', + internalId: 'unknownInternalId', - lazy: [], - active: [] - }; + lazy: [], + active: [] +}; describe('IoT Agent Device Update Registration', function() { beforeEach(function(done) { @@ -141,15 +141,19 @@ describe('IoT Agent Device Update Registration', function() { .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') .post('/NGSI9/registerContext') - .reply(200, utils.readExampleFile( - './test/unit/examples/contextAvailabilityResponses/registerIoTAgent1Success.json')); + .reply( + 200, + utils.readExampleFile('./test/unit/examples/contextAvailabilityResponses/registerIoTAgent1Success.json') + ); contextBrokerMock .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') .post('/v1/updateContext') - .reply(200, utils.readExampleFile( - './test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json')); + .reply( + 200, + utils.readExampleFile('./test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json') + ); iotAgentLib.activate(iotAgentConfig, function(error) { iotAgentLib.register(device1, function(error) { @@ -168,19 +172,30 @@ describe('IoT Agent Device Update Registration', function() { describe('When a device is preregistered and its registration information updated', function() { beforeEach(function() { contextBrokerMock - .post('/NGSI9/registerContext', utils.readExampleFile( - './test/unit/examples/contextAvailabilityRequests/updateIoTAgent1.json')) - .reply(200, utils.readExampleFile( - './test/unit/examples/contextAvailabilityResponses/updateIoTAgent1Success.json')); + .post( + '/NGSI9/registerContext', + utils.readExampleFile('./test/unit/examples/contextAvailabilityRequests/updateIoTAgent1.json') + ) + .reply( + 200, + utils.readExampleFile( + './test/unit/examples/contextAvailabilityResponses/updateIoTAgent1Success.json' + ) + ); contextBrokerMock .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v1/updateContext', utils.readExampleFile( - './test/unit/examples/contextRequests/updateProvisionActiveAttributes1.json')) - .reply(200, + .post( + '/v1/updateContext', + utils.readExampleFile('./test/unit/examples/contextRequests/updateProvisionActiveAttributes1.json') + ) + .reply( + 200, utils.readExampleFile( - './test/unit/examples/contextResponses/updateProvisionActiveAttributes1Success.json')); + './test/unit/examples/contextResponses/updateProvisionActiveAttributes1Success.json' + ) + ); }); it('should register as ContextProvider of its lazy attributes', function(done) { @@ -209,17 +224,26 @@ describe('IoT Agent Device Update Registration', function() { contextBrokerMock .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') - .post('/v1/updateContext', utils.readExampleFile( - './test/unit/examples/contextRequests/updateProvisionCommands1.json')) - .reply(200, - utils.readExampleFile( - './test/unit/examples/contextResponses/updateProvisionCommands1Success.json')); + .post( + '/v1/updateContext', + utils.readExampleFile('./test/unit/examples/contextRequests/updateProvisionCommands1.json') + ) + .reply( + 200, + utils.readExampleFile('./test/unit/examples/contextResponses/updateProvisionCommands1Success.json') + ); contextBrokerMock - .post('/NGSI9/registerContext', utils.readExampleFile( - './test/unit/examples/contextAvailabilityRequests/updateCommands1.json')) - .reply(200, utils.readExampleFile( - './test/unit/examples/contextAvailabilityResponses/updateCommands1Success.json')); + .post( + '/NGSI9/registerContext', + utils.readExampleFile('./test/unit/examples/contextAvailabilityRequests/updateCommands1.json') + ) + .reply( + 200, + utils.readExampleFile( + './test/unit/examples/contextAvailabilityResponses/updateCommands1Success.json' + ) + ); }); it('should register as ContextProvider of its commands and create the additional attributes', function(done) { @@ -246,10 +270,16 @@ describe('IoT Agent Device Update Registration', function() { describe('When a update action is executed in a non registered device', function() { beforeEach(function() { contextBrokerMock - .post('/NGSI9/registerContext', utils.readExampleFile( - './test/unit/examples/contextAvailabilityRequests/updateIoTAgent1.json')) - .reply(200, utils.readExampleFile( - './test/unit/examples/contextAvailabilityResponses/updateIoTAgent1Success.json')); + .post( + '/NGSI9/registerContext', + utils.readExampleFile('./test/unit/examples/contextAvailabilityRequests/updateIoTAgent1.json') + ) + .reply( + 200, + utils.readExampleFile( + './test/unit/examples/contextAvailabilityResponses/updateIoTAgent1Success.json' + ) + ); }); it('should return a DEVICE_NOT_FOUND error', function(done) { @@ -263,16 +293,20 @@ describe('IoT Agent Device Update Registration', function() { describe('When a device register is updated in the Context Broker and the request fail to connect', function() { beforeEach(function() { contextBrokerMock - .post('/NGSI9/registerContext', - utils.readExampleFile('./test/unit/examples/contextAvailabilityRequests/updateIoTAgent1.json')) + .post( + '/NGSI9/registerContext', + utils.readExampleFile('./test/unit/examples/contextAvailabilityRequests/updateIoTAgent1.json') + ) .reply(500, {}); contextBrokerMock .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') .post('/v1/updateContext') - .reply(200, - utils.readExampleFile('./test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json')); + .reply( + 200, + utils.readExampleFile('./test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json') + ); }); it('should return a REGISTRATION_ERROR error in the update action', function(done) { diff --git a/test/unit/provisioning/listProvisionedDevices-test.js b/test/unit/provisioning/listProvisionedDevices-test.js index 373dc2af4..a22c5fb30 100644 --- a/test/unit/provisioning/listProvisionedDevices-test.js +++ b/test/unit/provisioning/listProvisionedDevices-test.js @@ -20,39 +20,38 @@ * For those usages not covered by the GNU Affero General Public License * please contact with::[contacto@tid.es] */ -'use strict'; - -/* jshint camelcase: false */ - -var iotAgentLib = require('../../../lib/fiware-iotagent-lib'), - utils = require('../../tools/utils'), - should = require('should'), - nock = require('nock'), - async = require('async'), - request = require('request'), - contextBrokerMock, - iotAgentConfig = { - logLevel: 'FATAL', - contextBroker: { - host: '192.168.1.1', - port: '1026' - }, - server: { - port: 4041, - baseRoot: '/' - }, - types: {}, - service: 'smartGondor', - subservice: 'gardens', - providerUrl: 'http://smartGondor.com', - deviceRegistrationDuration: 'P1M' - }; + +/* eslint-disable no-unused-vars */ + +const iotAgentLib = require('../../../lib/fiware-iotagent-lib'); +const utils = require('../../tools/utils'); +const should = require('should'); +const nock = require('nock'); +const async = require('async'); +const request = require('request'); +let contextBrokerMock; +const iotAgentConfig = { + logLevel: 'FATAL', + contextBroker: { + host: '192.168.1.1', + port: '1026' + }, + server: { + port: 4041, + baseRoot: '/' + }, + types: {}, + service: 'smartGondor', + subservice: 'gardens', + providerUrl: 'http://smartGondor.com', + deviceRegistrationDuration: 'P1M' +}; describe('Device provisioning API: List provisioned devices', function() { - var provisioning1Options, - provisioning2Options, - provisioning3Options, - provisioning4Options; + let provisioning1Options; + let provisioning2Options; + let provisioning3Options; + let provisioning4Options; beforeEach(function(done) { provisioning1Options = { @@ -88,48 +87,63 @@ describe('Device provisioning API: List provisioned devices', function() { iotAgentLib.activate(iotAgentConfig, function() { contextBrokerMock = nock('http://192.168.1.1:1026') .post('/NGSI9/registerContext') - .reply(200, - utils.readExampleFile( - './test/unit/examples/contextAvailabilityResponses/registerProvisionedDeviceSuccess.json')); + .reply( + 200, + utils.readExampleFile( + './test/unit/examples/contextAvailabilityResponses/registerProvisionedDeviceSuccess.json' + ) + ); contextBrokerMock .post('/v1/updateContext') - .reply(200, - utils.readExampleFile( - './test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json')); + .reply( + 200, + utils.readExampleFile('./test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json') + ); contextBrokerMock .post('/NGSI9/registerContext') - .reply(200, - utils.readExampleFile( - './test/unit/examples/contextAvailabilityResponses/registerProvisionedDeviceSuccess.json')); + .reply( + 200, + utils.readExampleFile( + './test/unit/examples/contextAvailabilityResponses/registerProvisionedDeviceSuccess.json' + ) + ); contextBrokerMock .post('/v1/updateContext') - .reply(200, - utils.readExampleFile( - './test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json')); + .reply( + 200, + utils.readExampleFile('./test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json') + ); contextBrokerMock .post('/NGSI9/registerContext') - .reply(200, + .reply( + 200, utils.readExampleFile( - './test/unit/examples/contextAvailabilityResponses/registerProvisionedDeviceSuccess.json')); + './test/unit/examples/contextAvailabilityResponses/registerProvisionedDeviceSuccess.json' + ) + ); contextBrokerMock .post('/v1/updateContext') - .reply(200, - utils.readExampleFile( - './test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json')); - - async.series([ - iotAgentLib.clearAll, - async.apply(request, provisioning1Options), - async.apply(request, provisioning2Options), - async.apply(request, provisioning4Options) - ], function(error, results) { - done(); - }); + .reply( + 200, + utils.readExampleFile('./test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json') + ); + + async.series( + [ + iotAgentLib.clearAll, + async.apply(request, provisioning1Options), + async.apply(request, provisioning2Options), + async.apply(request, provisioning4Options) + ], + function(error, results) { + done(); + } + ); }); }); @@ -138,7 +152,7 @@ describe('Device provisioning API: List provisioned devices', function() { }); describe('When a request for the list of provisioned devices arrive', function() { - var options = { + const options = { url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices', headers: { 'fiware-service': 'smartGondor', @@ -149,7 +163,7 @@ describe('Device provisioning API: List provisioned devices', function() { it('should return all the provisioned devices', function(done) { request(options, function(error, response, body) { - var parsedBody = JSON.parse(body); + const parsedBody = JSON.parse(body); should.not.exist(error); should.exist(parsedBody.devices); response.statusCode.should.equal(200); @@ -160,10 +174,8 @@ describe('Device provisioning API: List provisioned devices', function() { }); it('should return all the appropriate field names', function(done) { - /* jshint camelcase:false */ - request(options, function(error, response, body) { - var parsedBody = JSON.parse(body); + const parsedBody = JSON.parse(body); should.exist(parsedBody.devices[0].attributes); parsedBody.devices[0].attributes.length.should.equal(1); @@ -186,8 +198,7 @@ describe('Device provisioning API: List provisioned devices', function() { it('should return all the plugin attributes', function(done) { request(options, function(error, response, body) { - var parsedBody = JSON.parse(body); - + const parsedBody = JSON.parse(body); should.exist(parsedBody.devices[2].attributes[0].entity_name); should.exist(parsedBody.devices[2].attributes[0].entity_type); @@ -202,7 +213,7 @@ describe('Device provisioning API: List provisioned devices', function() { }); }); describe('When a request for the information about a specific device arrives', function() { - var options = { + const options = { url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices/Light1', headers: { 'fiware-service': 'smartGondor', @@ -213,14 +224,10 @@ describe('Device provisioning API: List provisioned devices', function() { it('should return all the information on that particular device', function(done) { request(options, function(error, response, body) { - /* jshint camelcase:false */ - - var parsedBody; - should.not.exist(error); response.statusCode.should.equal(200); - parsedBody = JSON.parse(body); + const parsedBody = JSON.parse(body); parsedBody.entity_name.should.equal('TheFirstLight'); parsedBody.device_id.should.equal('Light1'); done(); @@ -229,13 +236,9 @@ describe('Device provisioning API: List provisioned devices', function() { it('should return the appropriate attribute fields', function(done) { request(options, function(error, response, body) { - /* jshint camelcase:false */ - - var parsedBody; - should.not.exist(error); - parsedBody = JSON.parse(body); + const parsedBody = JSON.parse(body); should.exist(parsedBody.attributes[0].object_id); parsedBody.attributes[0].object_id.should.equal('attr_name'); parsedBody.attributes[0].name.should.equal('attr_name'); @@ -245,7 +248,7 @@ describe('Device provisioning API: List provisioned devices', function() { }); }); describe('When a request for a device with plugin attributes arrives', function() { - var options = { + const options = { url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices/LightFull', headers: { 'fiware-service': 'smartGondor', @@ -256,13 +259,9 @@ describe('Device provisioning API: List provisioned devices', function() { it('should return the appropriate attribute fields', function(done) { request(options, function(error, response, body) { - /* jshint camelcase:false */ - - var parsedBody; - should.not.exist(error); - parsedBody = JSON.parse(body); + const parsedBody = JSON.parse(body); should.exist(parsedBody.attributes[0].entity_name); should.exist(parsedBody.attributes[0].entity_type); should.exist(parsedBody.attributes[1].expression); @@ -276,7 +275,7 @@ describe('Device provisioning API: List provisioned devices', function() { }); }); describe('When a request for an unexistent device arrives', function() { - var options = { + const options = { url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices/Light84', headers: { 'fiware-service': 'smartGondor', @@ -295,7 +294,7 @@ describe('Device provisioning API: List provisioned devices', function() { }); describe('When a request for listing all the devices with a limit of 3 arrives', function() { - var options = { + const options = { url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices?limit=3', headers: { 'fiware-service': 'smartGondor', @@ -305,9 +304,7 @@ describe('Device provisioning API: List provisioned devices', function() { }; function createDeviceRequest(i, callback) { - /* jshint camelcase: false */ - - var provisioningDeviceOptions = { + const provisioningDeviceOptions = { url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices', method: 'POST', headers: { @@ -331,16 +328,20 @@ describe('Device provisioning API: List provisioned devices', function() { .matchHeader('fiware-servicepath', '/gardens') .post('/NGSI9/registerContext') .times(10) - .reply(200, + .reply( + 200, utils.readExampleFile( - './test/unit/examples/contextAvailabilityResponses/registerProvisionedDeviceSuccess.json')); + './test/unit/examples/contextAvailabilityResponses/registerProvisionedDeviceSuccess.json' + ) + ); contextBrokerMock .post('/v1/updateContext') .times(10) - .reply(200, - utils.readExampleFile( - './test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json')); + .reply( + 200, + utils.readExampleFile('./test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json') + ); iotAgentLib.clearAll(function() { async.times(10, createDeviceRequest, function(error, results) { @@ -351,7 +352,7 @@ describe('Device provisioning API: List provisioned devices', function() { it('should return just 3 devices', function(done) { request(options, function(error, response, body) { - var parsedBody = JSON.parse(body); + const parsedBody = JSON.parse(body); should.not.exist(error); parsedBody.devices.length.should.equal(3); done(); @@ -360,7 +361,7 @@ describe('Device provisioning API: List provisioned devices', function() { it('should return a count with the complete number of devices', function(done) { request(options, function(error, response, body) { - var parsedBody = JSON.parse(body); + const parsedBody = JSON.parse(body); should.not.exist(error); parsedBody.count.should.equal(10); done(); @@ -369,7 +370,7 @@ describe('Device provisioning API: List provisioned devices', function() { }); describe('When a request for listing all the devices with a offset of 3 arrives', function() { - var options = { + const options = { url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices?offset=3', headers: { 'fiware-service': 'smartGondor', @@ -379,7 +380,7 @@ describe('Device provisioning API: List provisioned devices', function() { }; function createDeviceRequest(i, callback) { - var provisioningDeviceOptions = { + const provisioningDeviceOptions = { url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices', method: 'POST', headers: { @@ -405,9 +406,12 @@ describe('Device provisioning API: List provisioned devices', function() { .matchHeader('fiware-servicepath', '/gardens') .post('/NGSI9/registerContext') .times(10) - .reply(200, - utils.readExampleFile( - './test/unit/examples/contextAvailabilityResponses/registerProvisionedDeviceSuccess.json')); + .reply( + 200, + utils.readExampleFile( + './test/unit/examples/contextAvailabilityResponses/registerProvisionedDeviceSuccess.json' + ) + ); iotAgentLib.clearAll(function() { async.timesSeries(10, createDeviceRequest, function(error, results) { @@ -418,10 +422,10 @@ describe('Device provisioning API: List provisioned devices', function() { it('should skip the first 3 devices', function(done) { request(options, function(error, response, body) { - var parsedBody = JSON.parse(body); + const parsedBody = JSON.parse(body); should.not.exist(error); - for (var i = 0; i < parsedBody.devices.length; i++) { + for (let i = 0; i < parsedBody.devices.length; i++) { ['Light1_0', 'Light1_1', 'Light1_2'].indexOf(parsedBody.devices[i].id).should.equal(-1); } @@ -431,7 +435,7 @@ describe('Device provisioning API: List provisioned devices', function() { }); describe('When a listing request arrives and there are devices in other service and servicepath', function() { - var options = { + const options = { url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices', headers: { 'fiware-service': 'smartGondor', @@ -449,14 +453,18 @@ describe('Device provisioning API: List provisioned devices', function() { 'fiware-servicepath': '/gardens' }, json: utils.readExampleFile( - './test/unit/examples/deviceProvisioningRequests/provisionYetAnotherDevice.json') + './test/unit/examples/deviceProvisioningRequests/provisionYetAnotherDevice.json' + ) }; contextBrokerMock .post('/NGSI9/registerContext') - .reply(200, - utils.readExampleFile( - './test/unit/examples/contextAvailabilityResponses/registerProvisionedDeviceSuccess.json')); + .reply( + 200, + utils.readExampleFile( + './test/unit/examples/contextAvailabilityResponses/registerProvisionedDeviceSuccess.json' + ) + ); request(provisioning3Options, function(error) { done(); @@ -465,7 +473,7 @@ describe('Device provisioning API: List provisioned devices', function() { it('should return just the ones in the selected service', function(done) { request(options, function(error, response, body) { - var parsedBody = JSON.parse(body); + const parsedBody = JSON.parse(body); should.not.exist(error); response.statusCode.should.equal(200); parsedBody.devices.length.should.equal(3); diff --git a/test/unit/provisioning/provisionDeviceMultientity-test.js b/test/unit/provisioning/provisionDeviceMultientity-test.js index e2f723bfa..7064524f3 100644 --- a/test/unit/provisioning/provisionDeviceMultientity-test.js +++ b/test/unit/provisioning/provisionDeviceMultientity-test.js @@ -20,31 +20,31 @@ * For those usages not covered by the GNU Affero General Public License * please contact with::[contacto@tid.es] */ -'use strict'; -var iotAgentLib = require('../../../lib/fiware-iotagent-lib'), - utils = require('../../tools/utils'), +/* eslint-disable no-unused-vars */ - should = require('should'), - nock = require('nock'), - request = require('request'), - contextBrokerMock, - iotAgentConfig = { - logLevel: 'FATAL', - contextBroker: { - host: '192.168.1.1', - port: '1026' - }, - server: { - port: 4041, - baseRoot: '/' - }, - types: {}, - service: 'smartGondor', - subservice: 'gardens', - providerUrl: 'http://smartGondor.com', - deviceRegistrationDuration: 'P1M' - }; +const iotAgentLib = require('../../../lib/fiware-iotagent-lib'); +const utils = require('../../tools/utils'); +const should = require('should'); +const nock = require('nock'); +const request = require('request'); +let contextBrokerMock; +const iotAgentConfig = { + logLevel: 'FATAL', + contextBroker: { + host: '192.168.1.1', + port: '1026' + }, + server: { + port: 4041, + baseRoot: '/' + }, + types: {}, + service: 'smartGondor', + subservice: 'gardens', + providerUrl: 'http://smartGondor.com', + deviceRegistrationDuration: 'P1M' +}; describe('Device provisioning API: Provision devices', function() { beforeEach(function(done) { @@ -68,25 +68,40 @@ describe('Device provisioning API: Provision devices', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', '/gardens') - .post('/NGSI9/registerContext', utils.readExampleFile( - './test/unit/examples/contextAvailabilityRequests/registerProvisionedDevice.json')) - .reply(200, utils.readExampleFile( - './test/unit/examples/contextAvailabilityResponses/registerProvisionedDeviceSuccess.json')); + .post( + '/NGSI9/registerContext', + utils.readExampleFile( + './test/unit/examples/contextAvailabilityRequests/registerProvisionedDevice.json' + ) + ) + .reply( + 200, + utils.readExampleFile( + './test/unit/examples/contextAvailabilityResponses/registerProvisionedDeviceSuccess.json' + ) + ); contextBrokerMock .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', '/gardens') - .post('/v1/updateContext', utils.readExampleFile( - './test/unit/examples/contextRequests/createProvisionedDeviceMultientity.json')) - .reply(200, utils.readExampleFile( - './test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json')); + .post( + '/v1/updateContext', + utils.readExampleFile( + './test/unit/examples/contextRequests/createProvisionedDeviceMultientity.json' + ) + ) + .reply( + 200, + utils.readExampleFile('./test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json') + ); }); - var options = { + const options = { url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices', method: 'POST', - json: utils.readExampleFile('./test/unit/examples/deviceProvisioningRequests/' + - 'provisionNewDeviceMultientity.json'), + json: utils.readExampleFile( + './test/unit/examples/deviceProvisioningRequests/provisionNewDeviceMultientity.json' + ), headers: { 'fiware-service': 'smartGondor', 'fiware-servicepath': '/gardens' @@ -106,6 +121,3 @@ describe('Device provisioning API: Provision devices', function() { }); }); }); - - - diff --git a/test/unit/provisioning/removeProvisionedDevice-test.js b/test/unit/provisioning/removeProvisionedDevice-test.js index f5d294832..ba540a096 100644 --- a/test/unit/provisioning/removeProvisionedDevice-test.js +++ b/test/unit/provisioning/removeProvisionedDevice-test.js @@ -20,124 +20,145 @@ * For those usages not covered by the GNU Affero General Public License * please contact with::[contacto@tid.es] */ -'use strict'; - -var iotAgentLib = require('../../../lib/fiware-iotagent-lib'), - utils = require('../../tools/utils'), - should = require('should'), - nock = require('nock'), - async = require('async'), - request = require('request'), - contextBrokerMock, - iotAgentConfig = { - logLevel: 'FATAL', - contextBroker: { - host: '192.168.1.1', - port: '1026' - }, - server: { - port: 4041, - baseRoot: '/' - }, - types: {}, - service: 'smartGondor', - subservice: 'gardens', - providerUrl: 'http://smartGondor.com', - deviceRegistrationDuration: 'P1M' - }; + +/* eslint-disable no-unused-vars */ + +const iotAgentLib = require('../../../lib/fiware-iotagent-lib'); +const utils = require('../../tools/utils'); +const should = require('should'); +const nock = require('nock'); +const async = require('async'); +const request = require('request'); +let contextBrokerMock; +const iotAgentConfig = { + logLevel: 'FATAL', + contextBroker: { + host: '192.168.1.1', + port: '1026' + }, + server: { + port: 4041, + baseRoot: '/' + }, + types: {}, + service: 'smartGondor', + subservice: 'gardens', + providerUrl: 'http://smartGondor.com', + deviceRegistrationDuration: 'P1M' +}; describe('Device provisioning API: Remove provisioned devices', function() { - var provisioning1Options = { - url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices', - method: 'POST', - headers: { - 'fiware-service': 'smartGondor', - 'fiware-servicepath': '/gardens' - }, - json: utils.readExampleFile('./test/unit/examples/deviceProvisioningRequests/provisionNewDevice.json') + const provisioning1Options = { + url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices', + method: 'POST', + headers: { + 'fiware-service': 'smartGondor', + 'fiware-servicepath': '/gardens' }, - provisioning2Options = { - url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices', - method: 'POST', - headers: { - 'fiware-service': 'smartGondor', - 'fiware-servicepath': '/gardens' - }, - json: utils.readExampleFile('./test/unit/examples/deviceProvisioningRequests/provisionAnotherDevice.json') + json: utils.readExampleFile('./test/unit/examples/deviceProvisioningRequests/provisionNewDevice.json') + }; + const provisioning2Options = { + url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices', + method: 'POST', + headers: { + 'fiware-service': 'smartGondor', + 'fiware-servicepath': '/gardens' }, - provisioning3Options = { - url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices', - method: 'POST', - headers: { - 'fiware-service': 'smartGondor', - 'fiware-servicepath': '/gardens' - }, - json: utils.readExampleFile('./test/unit/examples/deviceProvisioningRequests/' + - 'provisionDeviceActiveAtts.json') - }; + json: utils.readExampleFile('./test/unit/examples/deviceProvisioningRequests/provisionAnotherDevice.json') + }; + const provisioning3Options = { + url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices', + method: 'POST', + headers: { + 'fiware-service': 'smartGondor', + 'fiware-servicepath': '/gardens' + }, + json: utils.readExampleFile('./test/unit/examples/deviceProvisioningRequests/provisionDeviceActiveAtts.json') + }; beforeEach(function(done) { iotAgentLib.activate(iotAgentConfig, function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', '/gardens') - .post('/NGSI9/registerContext', - utils.readExampleFile( - './test/unit/examples/contextAvailabilityRequests/registerProvisionedDevice.json')) - .reply(200, - utils.readExampleFile( - './test/unit/examples/contextAvailabilityResponses/registerProvisionedDeviceSuccess.json')); + .post( + '/NGSI9/registerContext', + utils.readExampleFile( + './test/unit/examples/contextAvailabilityRequests/registerProvisionedDevice.json' + ) + ) + .reply( + 200, + utils.readExampleFile( + './test/unit/examples/contextAvailabilityResponses/registerProvisionedDeviceSuccess.json' + ) + ); contextBrokerMock .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', '/gardens') .post('/v1/updateContext') - .reply(200, - utils.readExampleFile( - './test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json')); + .reply( + 200, + utils.readExampleFile('./test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json') + ); contextBrokerMock .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', '/gardens') - .post('/NGSI9/registerContext', - utils.readExampleFile( - './test/unit/examples/contextAvailabilityRequests/registerProvisionedDevice2.json')) - .reply(200, - utils.readExampleFile( - './test/unit/examples/contextAvailabilityResponses/registerProvisionedDeviceSuccess.json')); + .post( + '/NGSI9/registerContext', + utils.readExampleFile( + './test/unit/examples/contextAvailabilityRequests/registerProvisionedDevice2.json' + ) + ) + .reply( + 200, + utils.readExampleFile( + './test/unit/examples/contextAvailabilityResponses/registerProvisionedDeviceSuccess.json' + ) + ); contextBrokerMock .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', '/gardens') .post('/v1/updateContext') - .reply(200, - utils.readExampleFile( - './test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json')); + .reply( + 200, + utils.readExampleFile('./test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json') + ); contextBrokerMock .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', '/gardens') .post('/NGSI9/registerContext') - .reply(200, - utils.readExampleFile( - './test/unit/examples/contextAvailabilityResponses/unregisterDevice1Success.json')); + .reply( + 200, + utils.readExampleFile( + './test/unit/examples/contextAvailabilityResponses/unregisterDevice1Success.json' + ) + ); contextBrokerMock .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', '/gardens') .post('/v1/updateContext') - .reply(200, - utils.readExampleFile( - './test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json')); - - async.series([ - iotAgentLib.clearAll, - async.apply(request, provisioning1Options), - async.apply(request, provisioning2Options), - async.apply(request, provisioning3Options) - ], function(error, results) { - done(); - }); + .reply( + 200, + utils.readExampleFile('./test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json') + ); + + async.series( + [ + iotAgentLib.clearAll, + async.apply(request, provisioning1Options), + async.apply(request, provisioning2Options), + async.apply(request, provisioning3Options) + ], + function(error, results) { + done(); + } + ); }); }); @@ -146,7 +167,7 @@ describe('Device provisioning API: Remove provisioned devices', function() { }); describe('When a request to remove a provision device arrives', function() { - var options = { + const options = { url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices/Light1', headers: { 'fiware-service': 'smartGondor', @@ -165,7 +186,7 @@ describe('Device provisioning API: Remove provisioned devices', function() { it('should remove the device from the provisioned devices list', function(done) { request(options, function(error, response, body) { - var options = { + const options = { url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices', headers: { 'fiware-service': 'smartGondor', @@ -175,7 +196,7 @@ describe('Device provisioning API: Remove provisioned devices', function() { }; request(options, function(error, response, body) { - var parsedBody = JSON.parse(body); + const parsedBody = JSON.parse(body); parsedBody.devices.length.should.equal(2); done(); }); @@ -184,7 +205,7 @@ describe('Device provisioning API: Remove provisioned devices', function() { it('should return a 404 error when asking for the particular device', function(done) { request(options, function(error, response, body) { - var options = { + const options = { url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices/Light1', headers: { 'fiware-service': 'smartGondor', @@ -203,7 +224,7 @@ describe('Device provisioning API: Remove provisioned devices', function() { }); describe('When a request to remove a provision device arrives. Device without lazy atts or commands', function() { - var options = { + const options = { url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices/Light3', headers: { 'fiware-service': 'smartGondor', diff --git a/test/unit/provisioning/singleConfigurationMode-test.js b/test/unit/provisioning/singleConfigurationMode-test.js index 32871edb2..9092ec69e 100644 --- a/test/unit/provisioning/singleConfigurationMode-test.js +++ b/test/unit/provisioning/singleConfigurationMode-test.js @@ -20,52 +20,50 @@ * For those usages not covered by the GNU Affero General Public License * please contact with::[contacto@tid.es] */ -'use strict'; - -/* jshint camelcase: false */ - -var iotAgentLib = require('../../../lib/fiware-iotagent-lib'), - utils = require('../../tools/utils'), - - should = require('should'), - nock = require('nock'), - contextBrokerMock, - request = require('request'), - iotAgentConfig = { - logLevel: 'FATAL', - contextBroker: { - host: '192.168.1.1', - port: '1026' - }, - server: { - port: 4041, - baseRoot: '/' - }, - types: {}, - service: 'smartGondor', - singleConfigurationMode: true, - subservice: 'gardens', - providerUrl: 'http://smartGondor.com', - deviceRegistrationDuration: 'P1M' + +/* eslint-disable no-unused-vars */ + +const iotAgentLib = require('../../../lib/fiware-iotagent-lib'); +const utils = require('../../tools/utils'); +const should = require('should'); +const nock = require('nock'); +let contextBrokerMock; +const request = require('request'); +const iotAgentConfig = { + logLevel: 'FATAL', + contextBroker: { + host: '192.168.1.1', + port: '1026' }, - groupCreation = { - url: 'http://localhost:4041/iot/services', - method: 'POST', - json: utils.readExampleFile('./test/unit/examples/groupProvisioningRequests/provisionFullGroup.json'), - headers: { - 'fiware-service': 'TestService', - 'fiware-servicepath': '/testingPath' - } + server: { + port: 4041, + baseRoot: '/' }, - deviceCreation = { - url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices', - method: 'POST', - json: utils.readExampleFile('./test/unit/examples/deviceProvisioningRequests/provisionNewDevice.json'), - headers: { - 'fiware-service': 'TestService', - 'fiware-servicepath': '/testingPath' - } - }; + types: {}, + service: 'smartGondor', + singleConfigurationMode: true, + subservice: 'gardens', + providerUrl: 'http://smartGondor.com', + deviceRegistrationDuration: 'P1M' +}; +const groupCreation = { + url: 'http://localhost:4041/iot/services', + method: 'POST', + json: utils.readExampleFile('./test/unit/examples/groupProvisioningRequests/provisionFullGroup.json'), + headers: { + 'fiware-service': 'TestService', + 'fiware-servicepath': '/testingPath' + } +}; +const deviceCreation = { + url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices', + method: 'POST', + json: utils.readExampleFile('./test/unit/examples/deviceProvisioningRequests/provisionNewDevice.json'), + headers: { + 'fiware-service': 'TestService', + 'fiware-servicepath': '/testingPath' + } +}; describe('Provisioning API: Single service mode', function() { beforeEach(function(done) { @@ -83,7 +81,7 @@ describe('Provisioning API: Single service mode', function() { }); describe('When a new configuration arrives to an already configured subservice', function() { - var groupCreationDuplicated = { + const groupCreationDuplicated = { url: 'http://localhost:4041/iot/services', method: 'POST', json: utils.readExampleFile('./test/unit/examples/groupProvisioningRequests/provisionDuplicateGroup.json'), @@ -108,7 +106,7 @@ describe('Provisioning API: Single service mode', function() { }); }); describe('When a device is provisioned with an ID that already exists in the configuration', function() { - var deviceCreationDuplicated = { + const deviceCreationDuplicated = { url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices', method: 'POST', json: utils.readExampleFile('./test/unit/examples/deviceProvisioningRequests/provisionDuplicatedDev.json'), @@ -125,15 +123,21 @@ describe('Provisioning API: Single service mode', function() { .matchHeader('fiware-service', 'TestService') .matchHeader('fiware-servicepath', '/testingPath') .post('/NGSI9/registerContext') - .reply(200, utils.readExampleFile( - './test/unit/examples/contextAvailabilityResponses/registerProvisionedDeviceSuccess.json')); + .reply( + 200, + utils.readExampleFile( + './test/unit/examples/contextAvailabilityResponses/registerProvisionedDeviceSuccess.json' + ) + ); contextBrokerMock .matchHeader('fiware-service', 'TestService') .matchHeader('fiware-servicepath', '/testingPath') .post('/v1/updateContext') - .reply(200, utils.readExampleFile( - './test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json')); + .reply( + 200, + utils.readExampleFile('./test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json') + ); request(groupCreation, function(error) { request(deviceCreation, function(error, response, body) { @@ -153,24 +157,24 @@ describe('Provisioning API: Single service mode', function() { }); }); describe('When a device is provisioned with an ID that exists globally but not in the configuration', function() { - var alternativeDeviceCreation = { - url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices', - method: 'POST', - json: utils.readExampleFile('./test/unit/examples/deviceProvisioningRequests/provisionNewDevice.json'), - headers: { - 'fiware-service': 'AlternateService', - 'fiware-servicepath': '/testingPath' - } - }, - alternativeGroupCreation = { - url: 'http://localhost:4041/iot/services', - method: 'POST', - json: utils.readExampleFile('./test/unit/examples/groupProvisioningRequests/provisionFullGroup.json'), - headers: { - 'fiware-service': 'AlternateService', - 'fiware-servicepath': '/testingPath' - } - }; + const alternativeDeviceCreation = { + url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices', + method: 'POST', + json: utils.readExampleFile('./test/unit/examples/deviceProvisioningRequests/provisionNewDevice.json'), + headers: { + 'fiware-service': 'AlternateService', + 'fiware-servicepath': '/testingPath' + } + }; + const alternativeGroupCreation = { + url: 'http://localhost:4041/iot/services', + method: 'POST', + json: utils.readExampleFile('./test/unit/examples/groupProvisioningRequests/provisionFullGroup.json'), + headers: { + 'fiware-service': 'AlternateService', + 'fiware-servicepath': '/testingPath' + } + }; beforeEach(function(done) { nock.cleanAll(); @@ -179,29 +183,41 @@ describe('Provisioning API: Single service mode', function() { .matchHeader('fiware-service', 'TestService') .matchHeader('fiware-servicepath', '/testingPath') .post('/NGSI9/registerContext') - .reply(200, utils.readExampleFile( - './test/unit/examples/contextAvailabilityResponses/registerProvisionedDeviceSuccess.json')); + .reply( + 200, + utils.readExampleFile( + './test/unit/examples/contextAvailabilityResponses/registerProvisionedDeviceSuccess.json' + ) + ); contextBrokerMock .matchHeader('fiware-service', 'TestService') .matchHeader('fiware-servicepath', '/testingPath') .post('/v1/updateContext') - .reply(200, utils.readExampleFile( - './test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json')); + .reply( + 200, + utils.readExampleFile('./test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json') + ); contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'AlternateService') .matchHeader('fiware-servicepath', '/testingPath') .post('/NGSI9/registerContext') - .reply(200, utils.readExampleFile( - './test/unit/examples/contextAvailabilityResponses/registerProvisionedDeviceSuccess.json')); + .reply( + 200, + utils.readExampleFile( + './test/unit/examples/contextAvailabilityResponses/registerProvisionedDeviceSuccess.json' + ) + ); contextBrokerMock .matchHeader('fiware-service', 'AlternateService') .matchHeader('fiware-servicepath', '/testingPath') .post('/v1/updateContext') - .reply(200, utils.readExampleFile( - './test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json')); + .reply( + 200, + utils.readExampleFile('./test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json') + ); request(groupCreation, function(error) { request(deviceCreation, function(error, response, body) { @@ -221,15 +237,15 @@ describe('Provisioning API: Single service mode', function() { }); }); describe('When a device is provisioned without a type and with a default configuration type', function() { - var getDevice = { - url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices/Light1', - method: 'GET', - headers: { - 'fiware-service': 'TestService', - 'fiware-servicepath': '/testingPath' - } - }, - oldType; + const getDevice = { + url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices/Light1', + method: 'GET', + headers: { + 'fiware-service': 'TestService', + 'fiware-servicepath': '/testingPath' + } + }; + let oldType; beforeEach(function(done) { nock.cleanAll(); @@ -238,15 +254,21 @@ describe('Provisioning API: Single service mode', function() { .matchHeader('fiware-service', 'TestService') .matchHeader('fiware-servicepath', '/testingPath') .post('/NGSI9/registerContext') - .reply(200, utils.readExampleFile( - './test/unit/examples/contextAvailabilityResponses/registerProvisionedDeviceSuccess.json')); + .reply( + 200, + utils.readExampleFile( + './test/unit/examples/contextAvailabilityResponses/registerProvisionedDeviceSuccess.json' + ) + ); contextBrokerMock .matchHeader('fiware-service', 'TestService') .matchHeader('fiware-servicepath', '/testingPath') .post('/v1/updateContext') - .reply(200, utils.readExampleFile( - './test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json')); + .reply( + 200, + utils.readExampleFile('./test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json') + ); oldType = deviceCreation.json.devices[0].entity_type; delete deviceCreation.json.devices[0].entity_type; @@ -260,9 +282,7 @@ describe('Provisioning API: Single service mode', function() { it('should be provisioned with the default type', function(done) { request(deviceCreation, function(error, response, body) { request(getDevice, function(error, response, body) { - var parsedBody; - - parsedBody = JSON.parse(body); + const parsedBody = JSON.parse(body); parsedBody.entity_type.should.equal('SensorMachine'); @@ -278,18 +298,32 @@ describe('Provisioning API: Single service mode', function() { contextBrokerMock = nock('http://unexistentHost:1026') .matchHeader('fiware-service', 'TestService') .matchHeader('fiware-servicepath', '/testingPath') - .post('/NGSI9/registerContext', utils.readExampleFile( - './test/unit/examples/contextAvailabilityRequests/registerProvisionedDeviceWithGroup.json')) - .reply(200, utils.readExampleFile( - './test/unit/examples/contextAvailabilityResponses/registerProvisionedDeviceSuccess.json')); + .post( + '/NGSI9/registerContext', + utils.readExampleFile( + './test/unit/examples/contextAvailabilityRequests/registerProvisionedDeviceWithGroup.json' + ) + ) + .reply( + 200, + utils.readExampleFile( + './test/unit/examples/contextAvailabilityResponses/registerProvisionedDeviceSuccess.json' + ) + ); contextBrokerMock .matchHeader('fiware-service', 'TestService') .matchHeader('fiware-servicepath', '/testingPath') - .post('/v1/updateContext', utils.readExampleFile( - './test/unit/examples/contextRequests/createProvisionedDeviceWithGroupAndStatic.json')) - .reply(200, utils.readExampleFile( - './test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json')); + .post( + '/v1/updateContext', + utils.readExampleFile( + './test/unit/examples/contextRequests/createProvisionedDeviceWithGroupAndStatic.json' + ) + ) + .reply( + 200, + utils.readExampleFile('./test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json') + ); request(groupCreation, done); }); @@ -308,6 +342,5 @@ describe('Provisioning API: Single service mode', function() { done(); }); }); - }); }); diff --git a/test/unit/provisioning/updateProvisionedDevices-test.js b/test/unit/provisioning/updateProvisionedDevices-test.js index 4615e678d..ed70304ff 100644 --- a/test/unit/provisioning/updateProvisionedDevices-test.js +++ b/test/unit/provisioning/updateProvisionedDevices-test.js @@ -20,60 +20,61 @@ * For those usages not covered by the GNU Affero General Public License * please contact with::[contacto@tid.es] */ -'use strict'; - -var iotAgentLib = require('../../../lib/fiware-iotagent-lib'), - utils = require('../../tools/utils'), - should = require('should'), - nock = require('nock'), - async = require('async'), - request = require('request'), - contextBrokerMock, - iotAgentConfig = { - logLevel: 'FATAL', - contextBroker: { - host: '192.168.1.1', - port: '1026' - }, - server: { - port: 4041, - baseRoot: '/' - }, - types: {}, - service: 'smartGondor', - subservice: 'gardens', - providerUrl: 'http://smartGondor.com', - deviceRegistrationDuration: 'P1M' - }; + +/* eslint-disable no-unused-vars */ + +const iotAgentLib = require('../../../lib/fiware-iotagent-lib'); +const utils = require('../../tools/utils'); +const should = require('should'); +const nock = require('nock'); +const async = require('async'); +const request = require('request'); +let contextBrokerMock; +const iotAgentConfig = { + logLevel: 'FATAL', + contextBroker: { + host: '192.168.1.1', + port: '1026' + }, + server: { + port: 4041, + baseRoot: '/' + }, + types: {}, + service: 'smartGondor', + subservice: 'gardens', + providerUrl: 'http://smartGondor.com', + deviceRegistrationDuration: 'P1M' +}; describe('Device provisioning API: Update provisioned devices', function() { - var provisioning1Options = { - url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices', - method: 'POST', - headers: { - 'fiware-service': 'smartGondor', - 'fiware-servicepath': '/gardens' - }, - json: utils.readExampleFile('./test/unit/examples/deviceProvisioningRequests/provisionNewDevice.json') + const provisioning1Options = { + url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices', + method: 'POST', + headers: { + 'fiware-service': 'smartGondor', + 'fiware-servicepath': '/gardens' }, - provisioning2Options = { - url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices', - method: 'POST', - headers: { - 'fiware-service': 'smartGondor', - 'fiware-servicepath': '/gardens' - }, - json: utils.readExampleFile('./test/unit/examples/deviceProvisioningRequests/provisionAnotherDevice.json') + json: utils.readExampleFile('./test/unit/examples/deviceProvisioningRequests/provisionNewDevice.json') + }; + const provisioning2Options = { + url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices', + method: 'POST', + headers: { + 'fiware-service': 'smartGondor', + 'fiware-servicepath': '/gardens' }, - provisioning3Options = { - url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices', - method: 'POST', - headers: { - 'fiware-service': 'smartGondor', - 'fiware-servicepath': '/gardens' - }, - json: utils.readExampleFile('./test/unit/examples/deviceProvisioningRequests/provisionMinimumDevice2.json') - }; + json: utils.readExampleFile('./test/unit/examples/deviceProvisioningRequests/provisionAnotherDevice.json') + }; + const provisioning3Options = { + url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices', + method: 'POST', + headers: { + 'fiware-service': 'smartGondor', + 'fiware-servicepath': '/gardens' + }, + json: utils.readExampleFile('./test/unit/examples/deviceProvisioningRequests/provisionMinimumDevice2.json') + }; beforeEach(function(done) { nock.cleanAll(); @@ -81,54 +82,75 @@ describe('Device provisioning API: Update provisioned devices', function() { contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', '/gardens') - .post('/NGSI9/registerContext', - utils.readExampleFile( - './test/unit/examples/contextAvailabilityRequests/registerProvisionedDevice.json')) - .reply(200, - utils.readExampleFile( - './test/unit/examples/contextAvailabilityResponses/registerProvisionedDeviceSuccess.json')); + .post( + '/NGSI9/registerContext', + utils.readExampleFile( + './test/unit/examples/contextAvailabilityRequests/registerProvisionedDevice.json' + ) + ) + .reply( + 200, + utils.readExampleFile( + './test/unit/examples/contextAvailabilityResponses/registerProvisionedDeviceSuccess.json' + ) + ); contextBrokerMock .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', '/gardens') .post('/v1/updateContext') - .reply(200, - utils.readExampleFile( - './test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json')); + .reply( + 200, + utils.readExampleFile('./test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json') + ); contextBrokerMock .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', '/gardens') - .post('/NGSI9/registerContext', - utils.readExampleFile( - './test/unit/examples/contextAvailabilityRequests/registerProvisionedDevice2.json')) - .reply(200, - utils.readExampleFile( - './test/unit/examples/contextAvailabilityResponses/registerProvisionedDeviceSuccess.json')); + .post( + '/NGSI9/registerContext', + utils.readExampleFile( + './test/unit/examples/contextAvailabilityRequests/registerProvisionedDevice2.json' + ) + ) + .reply( + 200, + utils.readExampleFile( + './test/unit/examples/contextAvailabilityResponses/registerProvisionedDeviceSuccess.json' + ) + ); contextBrokerMock .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', '/gardens') .post('/v1/updateContext') - .reply(200, - utils.readExampleFile( - './test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json')); + .reply( + 200, + utils.readExampleFile('./test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json') + ); contextBrokerMock .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', '/gardens') - .post('/NGSI9/registerContext', - utils.readExampleFile( - './test/unit/examples/contextAvailabilityRequests/updateIoTAgent2.json')) - .reply(200, - utils.readExampleFile( - './test/unit/examples/contextAvailabilityResponses/updateIoTAgent1Success.json')); - - async.series([ - iotAgentLib.clearAll, - async.apply(request, provisioning1Options), - async.apply(request, provisioning2Options) - ], done); + .post( + '/NGSI9/registerContext', + utils.readExampleFile('./test/unit/examples/contextAvailabilityRequests/updateIoTAgent2.json') + ) + .reply( + 200, + utils.readExampleFile( + './test/unit/examples/contextAvailabilityResponses/updateIoTAgent1Success.json' + ) + ); + + async.series( + [ + iotAgentLib.clearAll, + async.apply(request, provisioning1Options), + async.apply(request, provisioning2Options) + ], + done + ); }); }); @@ -139,7 +161,7 @@ describe('Device provisioning API: Update provisioned devices', function() { }); describe('When a request to update a provision device arrives', function() { - var optionsUpdate = { + const optionsUpdate = { url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices/Light1', method: 'PUT', headers: { @@ -153,17 +175,26 @@ describe('Device provisioning API: Update provisioned devices', function() { contextBrokerMock .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', '/gardens') - .post('/v1/updateContext', utils.readExampleFile( - './test/unit/examples/contextRequests/updateActiveAttributes.json')) - .reply(200, - utils.readExampleFile( - './test/unit/examples/contextResponses/updateActiveAttributesSuccess.json')); + .post( + '/v1/updateContext', + utils.readExampleFile('./test/unit/examples/contextRequests/updateActiveAttributes.json') + ) + .reply( + 200, + utils.readExampleFile('./test/unit/examples/contextResponses/updateActiveAttributesSuccess.json') + ); contextBrokerMock - .post('/NGSI9/registerContext', utils.readExampleFile( - './test/unit/examples/contextAvailabilityRequests/updateIoTAgent3.json')) - .reply(200, utils.readExampleFile( - './test/unit/examples/contextAvailabilityResponses/updateIoTAgent1Success.json')); + .post( + '/NGSI9/registerContext', + utils.readExampleFile('./test/unit/examples/contextAvailabilityRequests/updateIoTAgent3.json') + ) + .reply( + 200, + utils.readExampleFile( + './test/unit/examples/contextAvailabilityResponses/updateIoTAgent1Success.json' + ) + ); }); it('should return a 200 OK and no errors', function(done) { @@ -176,7 +207,7 @@ describe('Device provisioning API: Update provisioned devices', function() { it('should have updated the data when asking for the particular device', function(done) { request(optionsUpdate, function(error, response, body) { - var options = { + const options = { url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices/Light1', headers: { 'fiware-service': 'smartGondor', @@ -186,9 +217,7 @@ describe('Device provisioning API: Update provisioned devices', function() { }; request(options, function(error, response, body) { - /* jshint camelcase:false */ - - var parsedBody = JSON.parse(body); + const parsedBody = JSON.parse(body); parsedBody.entity_name.should.equal('ANewLightName'); parsedBody.timezone.should.equal('Europe/Madrid'); done(); @@ -198,7 +227,7 @@ describe('Device provisioning API: Update provisioned devices', function() { it('should not modify the attributes not present in the update request', function(done) { request(optionsUpdate, function(error, response, body) { - var options = { + const options = { url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices/Light1', headers: { 'fiware-service': 'smartGondor', @@ -208,9 +237,7 @@ describe('Device provisioning API: Update provisioned devices', function() { }; request(options, function(error, response, body) { - /* jshint camelcase:false */ - - var parsedBody = JSON.parse(body); + const parsedBody = JSON.parse(body); parsedBody.entity_type.should.equal('TheLightType'); parsedBody.service.should.equal('smartGondor'); done(); @@ -219,7 +246,7 @@ describe('Device provisioning API: Update provisioned devices', function() { }); }); describe('When an update request arrives with a new Device ID', function() { - var optionsUpdate = { + const optionsUpdate = { url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices/Light1', method: 'PUT', headers: { @@ -227,7 +254,8 @@ describe('Device provisioning API: Update provisioned devices', function() { 'fiware-servicepath': '/gardens' }, json: utils.readExampleFile( - './test/unit/examples/deviceProvisioningRequests/updateProvisionDeviceWithId.json') + './test/unit/examples/deviceProvisioningRequests/updateProvisionDeviceWithId.json' + ) }; it('should raise a 400 error', function(done) { @@ -239,7 +267,7 @@ describe('Device provisioning API: Update provisioned devices', function() { }); }); describe('When a wrong update request payload arrives', function() { - var optionsUpdate = { + const optionsUpdate = { url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices/Light1', method: 'PUT', headers: { @@ -247,7 +275,8 @@ describe('Device provisioning API: Update provisioned devices', function() { 'fiware-servicepath': '/gardens' }, json: utils.readExampleFile( - './test/unit/examples/deviceProvisioningRequests/updateProvisionDeviceWrong.json') + './test/unit/examples/deviceProvisioningRequests/updateProvisionDeviceWrong.json' + ) }; it('should raise a 400 error', function(done) { @@ -260,23 +289,23 @@ describe('Device provisioning API: Update provisioned devices', function() { }); describe('When a device is provisioned without attributes and new ones are added through an update', function() { - var optionsUpdate = { - url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices/MicroLight2', - method: 'PUT', - headers: { - 'fiware-service': 'smartGondor', - 'fiware-servicepath': '/gardens' - }, - json: utils.readExampleFile('./test/unit/examples/deviceProvisioningRequests/updateMinimumDevice.json') + const optionsUpdate = { + url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices/MicroLight2', + method: 'PUT', + headers: { + 'fiware-service': 'smartGondor', + 'fiware-servicepath': '/gardens' }, - optionsGetDevice = { - url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices/MicroLight2', - method: 'GET', - headers: { - 'fiware-service': 'smartGondor', - 'fiware-servicepath': '/gardens' - } - }; + json: utils.readExampleFile('./test/unit/examples/deviceProvisioningRequests/updateMinimumDevice.json') + }; + const optionsGetDevice = { + url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices/MicroLight2', + method: 'GET', + headers: { + 'fiware-service': 'smartGondor', + 'fiware-servicepath': '/gardens' + } + }; beforeEach(function(done) { nock.cleanAll(); @@ -284,23 +313,26 @@ describe('Device provisioning API: Update provisioned devices', function() { .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', '/gardens') .post('/v1/updateContext') - .reply(200, - utils.readExampleFile( - './test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json')); + .reply( + 200, + utils.readExampleFile('./test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json') + ); contextBrokerMock .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', '/gardens') - .post('/v1/updateContext', utils.readExampleFile( - './test/unit/examples/contextRequests/updateProvisionMinimumDevice.json')) - .reply(200, + .post( + '/v1/updateContext', + utils.readExampleFile('./test/unit/examples/contextRequests/updateProvisionMinimumDevice.json') + ) + .reply( + 200, utils.readExampleFile( - './test/unit/examples/contextResponses/updateProvisionMinimumDeviceSuccess.json')); + './test/unit/examples/contextResponses/updateProvisionMinimumDeviceSuccess.json' + ) + ); - async.series([ - iotAgentLib.clearAll, - async.apply(request, provisioning3Options) - ], done); + async.series([iotAgentLib.clearAll, async.apply(request, provisioning3Options)], done); }); it('should not raise any error', function(done) { @@ -313,11 +345,10 @@ describe('Device provisioning API: Update provisioned devices', function() { it('should provision the attributes appropriately', function(done) { request(optionsUpdate, function(error, response, body) { request(optionsGetDevice, function(error, response, body) { - var parsedBody; should.not.exist(error); response.statusCode.should.equal(200); - parsedBody = JSON.parse(body); + const parsedBody = JSON.parse(body); parsedBody.attributes.length.should.equal(1); parsedBody.attributes[0].name.should.equal('newAttribute'); @@ -335,25 +366,23 @@ describe('Device provisioning API: Update provisioned devices', function() { }); describe('When a device is updated to add static attributes', function() { - /* jshint camelcase: false */ - - var optionsUpdate = { - url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices/MicroLight2', - method: 'PUT', - headers: { - 'fiware-service': 'smartGondor', - 'fiware-servicepath': '/gardens' - }, - json: utils.readExampleFile('./test/unit/examples/deviceProvisioningRequests/updateDeviceStatic.json') + const optionsUpdate = { + url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices/MicroLight2', + method: 'PUT', + headers: { + 'fiware-service': 'smartGondor', + 'fiware-servicepath': '/gardens' }, - optionsGetDevice = { - url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices/MicroLight2', - method: 'GET', - headers: { - 'fiware-service': 'smartGondor', - 'fiware-servicepath': '/gardens' - } - }; + json: utils.readExampleFile('./test/unit/examples/deviceProvisioningRequests/updateDeviceStatic.json') + }; + const optionsGetDevice = { + url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices/MicroLight2', + method: 'GET', + headers: { + 'fiware-service': 'smartGondor', + 'fiware-servicepath': '/gardens' + } + }; beforeEach(function(done) { nock.cleanAll(); @@ -361,33 +390,35 @@ describe('Device provisioning API: Update provisioned devices', function() { .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', '/gardens') .post('/v1/updateContext') - .reply(200, - utils.readExampleFile( - './test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json')); + .reply( + 200, + utils.readExampleFile('./test/unit/examples/contextResponses/createProvisionedDeviceSuccess.json') + ); contextBrokerMock .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', '/gardens') - .post('/v1/updateContext', utils.readExampleFile( - './test/unit/examples/contextRequests/updateProvisionDeviceStatic.json')) - .reply(200, + .post( + '/v1/updateContext', + utils.readExampleFile('./test/unit/examples/contextRequests/updateProvisionDeviceStatic.json') + ) + .reply( + 200, utils.readExampleFile( - './test/unit/examples/contextResponses/updateProvisionMinimumDeviceSuccess.json')); + './test/unit/examples/contextResponses/updateProvisionMinimumDeviceSuccess.json' + ) + ); - async.series([ - iotAgentLib.clearAll, - async.apply(request, provisioning3Options) - ], done); + async.series([iotAgentLib.clearAll, async.apply(request, provisioning3Options)], done); }); it('should provision the attributes appropriately', function(done) { request(optionsUpdate, function(error, response, body) { request(optionsGetDevice, function(error, response, body) { - var parsedBody; should.not.exist(error); response.statusCode.should.equal(200); - parsedBody = JSON.parse(body); + const parsedBody = JSON.parse(body); parsedBody.static_attributes.length.should.equal(3); parsedBody.static_attributes[0].name.should.equal('cellID'); From 206886c229e3f6ab42889008c532ccda9c8b269a Mon Sep 17 00:00:00 2001 From: Jason Fox Date: Sat, 30 Nov 2019 13:51:24 +0100 Subject: [PATCH 02/27] Add CNR --- CHANGES_NEXT_RELEASE | 3 +++ doc/usermanual.md | 16 ++++++++-------- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/CHANGES_NEXT_RELEASE b/CHANGES_NEXT_RELEASE index e69de29bb..c2bb84226 100644 --- a/CHANGES_NEXT_RELEASE +++ b/CHANGES_NEXT_RELEASE @@ -0,0 +1,3 @@ +- Replace jshint with eslint +- Add prettier code formatting +- Add husky and lint-staged \ No newline at end of file diff --git a/doc/usermanual.md b/doc/usermanual.md index 20fef4199..b6afb1270 100644 --- a/doc/usermanual.md +++ b/doc/usermanual.md @@ -21,7 +21,7 @@ ## Usage ### Stats Registry The library provides a mechanism for the periodic reporting of stats related to the library's work. In order to activate -the use of the periodic stats, it must be configured in the config file, as described in the +the use of the periodic stats, it must be configured in the config file, as described in the [Configuration](installationguide.md#configuration) section. The Stats Registry holds two dictionaries, with the same set of stats. For each stat, one of the dictionaries holds the @@ -383,8 +383,8 @@ callback with no parameters (this handler should only be used for reconfiguratio For the cases of multiple updates (a single Device Configuration POST that will create several device groups), the handler will be called once for each of the configurations (both in the case of the creations and the updates). -The handler will be also called in the case of updates related to configurations. In that situation, the -`newConfiguration` parameter contains also the fields needed to identify the configuration to be updated, i.e., +The handler will be also called in the case of updates related to configurations. In that situation, the +`newConfiguration` parameter contains also the fields needed to identify the configuration to be updated, i.e., `service`, `subservice`, `resource` and `apikey`. ##### iotagentLib.setRemoveConfigurationHandler() @@ -581,7 +581,7 @@ function startServer(newConfig, iotAgent, callback) ###### Description Start the HTTP server either in single-thread or multi-thread (multi-core) based on the value of *multiCore* -variable (described in the [Configuration](installationguide.md#configuration) section). If the value is +variable (described in the [Configuration](installationguide.md#configuration) section). If the value is `False` (either was directly specified `False` in the `config.js` or it was not specified and by default is assigned `False`), it is a normal (single-thread) behaviour. Nevertheless, if *multiCore* is `True`, the IoTAgent is executed in multi-thread environment. @@ -590,7 +590,7 @@ The number of parallel processes is calculated based on the number of available unexpectedly dead, a new process is created automatically to keep always the maximum of them working in parallel. > Note: `startServer()` initializes the server but it does not activate the library. The function in the Node Lib -> will call the `iotAgent.start()` in order to complete the activation of the library. Therefore, it is expected that +> will call the `iotAgent.start()` in order to complete the activation of the library. Therefore, it is expected that > the IoT Agent implement the `iotAgent.start()` function with the proper invocation to the `iotAgentLib.activate()`. ###### Params @@ -684,7 +684,7 @@ Stores the information about the IoTAgent for further use in the `retrieveVersio ## Development documentation ### Contributions -All contributions to this project are welcome. Developers planning to contribute should follow the +All contributions to this project are welcome. Developers planning to contribute should follow the [Contribution Guidelines](Contribution.md) ### Project build @@ -712,9 +712,9 @@ npm test ``` ### Coding guidelines -jshint +eslint -Uses provided .jshintrc flag file. +Uses provided `.eslintrc.json` flag file. To check source code style, type ```bash From a5334ea868f0c68827b1465989f24642d4775f5e Mon Sep 17 00:00:00 2001 From: Jason Fox Date: Sat, 30 Nov 2019 14:19:14 +0100 Subject: [PATCH 03/27] Fixing test expectations --- lib/plugins/multiEntity.js | 3 ++- test/unit/ngsiService/active-devices-test.js | 2 +- test/unit/ngsiv2/ngsiService/active-devices-test.js | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/plugins/multiEntity.js b/lib/plugins/multiEntity.js index a714c33ff..88c36f03d 100644 --- a/lib/plugins/multiEntity.js +++ b/lib/plugins/multiEntity.js @@ -256,6 +256,7 @@ function extractTypes(attributeList, defaultType) { * */ function propagateTimestamp(entity, entities) { + let att; const ts = entity[constants.TIMESTAMP_ATTRIBUTE]; if (!ts) { return; @@ -263,7 +264,7 @@ function propagateTimestamp(entity, entities) { entities.map(function(en) { // Set timestamp metadata in attributes (except TimeInstant attribute itself) - for (const att in en && att !== constants.TIMESTAMP_ATTRIBUTE) { + for (att in en && att !== constants.TIMESTAMP_ATTRIBUTE) { if (en.hasOwnProperty(att) && att !== 'id' && att !== 'type') { if (!en[att].metadata) { en[att].metadata = {}; diff --git a/test/unit/ngsiService/active-devices-test.js b/test/unit/ngsiService/active-devices-test.js index 0f9771528..cef63eebb 100644 --- a/test/unit/ngsiService/active-devices-test.js +++ b/test/unit/ngsiService/active-devices-test.js @@ -420,7 +420,7 @@ describe('Active attributes test', function() { .post( '/v1/updateContext', utils.readExampleFile( - './test/unit/examples/contextRequests/ updateContextTimestampOverrideWithoutMilis.json' + './test/unit/examples/contextRequests/updateContext/TimestampOverrideWithoutMilis.json' ) ) .reply(200, utils.readExampleFile('./test/unit/examples/contextResponses/updateContext1Success.json')); diff --git a/test/unit/ngsiv2/ngsiService/active-devices-test.js b/test/unit/ngsiv2/ngsiService/active-devices-test.js index a7218e05d..716b77f52 100644 --- a/test/unit/ngsiv2/ngsiService/active-devices-test.js +++ b/test/unit/ngsiv2/ngsiService/active-devices-test.js @@ -343,7 +343,7 @@ describe('Active attributes test', function() { .post( '/v2/entities/light1/attrs', utils.readExampleFile( - './test/unit/ngsiv2/examples/contextRequests/ updateContextTimestampTimezone.json' + './test/unit/ngsiv2/examples/contextRequests/updateContextTimestampTimezone.json' ) ) .query({ type: 'Light' }) From e4df20558e10503b3a5ba1a2608104cb057662bb Mon Sep 17 00:00:00 2001 From: Jason Fox Date: Sat, 30 Nov 2019 14:24:49 +0100 Subject: [PATCH 04/27] Fixing test expectations --- test/unit/ngsiService/active-devices-test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/unit/ngsiService/active-devices-test.js b/test/unit/ngsiService/active-devices-test.js index cef63eebb..780411374 100644 --- a/test/unit/ngsiService/active-devices-test.js +++ b/test/unit/ngsiService/active-devices-test.js @@ -420,7 +420,7 @@ describe('Active attributes test', function() { .post( '/v1/updateContext', utils.readExampleFile( - './test/unit/examples/contextRequests/updateContext/TimestampOverrideWithoutMilis.json' + './test/unit/examples/contextRequests/updateContextTimestampOverrideWithoutMilis.json' ) ) .reply(200, utils.readExampleFile('./test/unit/examples/contextResponses/updateContext1Success.json')); From cd9475acb128f73d863d45bf99299f1dc5bb7aec Mon Sep 17 00:00:00 2001 From: Jason Fox Date: Sat, 21 Dec 2019 10:47:25 +0000 Subject: [PATCH 05/27] Add editorconfig --- .editorconfig | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 .editorconfig diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 000000000..75866cfb1 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,17 @@ +# editorconfig.org +root = true + +[*] +indent_style = tab +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +[*.{json,yml,md,babelrc,eslintrc,remarkrc}] +indent_style = space +indent_size = 2 + +[*.{js}] +indent_style = space +indent_size = 4 \ No newline at end of file From cbe8e4d2e26ba63d532ed137141c438001d1942b Mon Sep 17 00:00:00 2001 From: Jason Fox Date: Sat, 21 Dec 2019 11:22:01 +0000 Subject: [PATCH 06/27] Update coding guidelines to include eslint and editorconfig --- doc/usermanual.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/usermanual.md b/doc/usermanual.md index b6afb1270..9b5c8ca19 100644 --- a/doc/usermanual.md +++ b/doc/usermanual.md @@ -712,6 +712,7 @@ npm test ``` ### Coding guidelines + eslint Uses provided `.eslintrc.json` flag file. @@ -759,7 +760,7 @@ npm run clean ### Prettify Code -Runs the [prettier](https://prettier.io) code formatter to ensure consistent code style (whitespacing, parameter placement and breakup of long lines etc.) within the codebase. +Runs the [prettier](https://prettier.io) code formatter to ensure consistent code style (whitespacing, parameter placement and breakup of long lines etc.) within the codebase. Uses the and `prettierrc.json` flag file. ```bash # Use git-bash on Windows From 876ca4b7cce3baaa310182bbf402e82f27f114c0 Mon Sep 17 00:00:00 2001 From: Jason Fox Date: Sat, 21 Dec 2019 11:37:06 +0000 Subject: [PATCH 07/27] Amending text --- doc/usermanual.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/usermanual.md b/doc/usermanual.md index 9b5c8ca19..d6ba39e31 100644 --- a/doc/usermanual.md +++ b/doc/usermanual.md @@ -715,8 +715,7 @@ npm test eslint -Uses provided `.eslintrc.json` flag file. -To check source code style, type +Uses the provided `.eslintrc.json` flag files. To check source code style, type ```bash npm run lint @@ -760,7 +759,8 @@ npm run clean ### Prettify Code -Runs the [prettier](https://prettier.io) code formatter to ensure consistent code style (whitespacing, parameter placement and breakup of long lines etc.) within the codebase. Uses the and `prettierrc.json` flag file. +Runs the [prettier](https://prettier.io) code formatter to ensure consistent code style (whitespacing, parameter placement and breakup of long lines etc.) within the codebase. Uses the `prettierrc.json` flag file. The codebase +also offers an `.editorconfig` to maintain consistent coding styles across multiple IDEs. ```bash # Use git-bash on Windows From 0bd74e773652b93f0e4272691523d60350c4f612 Mon Sep 17 00:00:00 2001 From: Jason Fox Date: Sat, 21 Dec 2019 11:46:20 +0000 Subject: [PATCH 08/27] Capitalize ESLint --- doc/usermanual.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/usermanual.md b/doc/usermanual.md index d6ba39e31..1690b5a81 100644 --- a/doc/usermanual.md +++ b/doc/usermanual.md @@ -713,7 +713,7 @@ npm test ### Coding guidelines -eslint +ESLint Uses the provided `.eslintrc.json` flag files. To check source code style, type From 5e839d901571e059f7b62a552ac418eb63b14c26 Mon Sep 17 00:00:00 2001 From: Jason Fox Date: Thu, 9 Jan 2020 15:36:44 +0100 Subject: [PATCH 09/27] Update .editorconfig --- .editorconfig | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.editorconfig b/.editorconfig index 75866cfb1..68bf01fa0 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,17 +1,18 @@ # editorconfig.org root = true +# Unix-style newlines with a newline ending every file [*] -indent_style = tab end_of_line = lf charset = utf-8 -trim_trailing_whitespace = true insert_final_newline = true [*.{json,yml,md,babelrc,eslintrc,remarkrc}] indent_style = space indent_size = 2 +trim_trailing_whitespace = true [*.{js}] indent_style = space -indent_size = 4 \ No newline at end of file +indent_size = 4 +trim_trailing_whitespace = true From 4820c764ac65c337dd1d55af546bf07be9d38dad Mon Sep 17 00:00:00 2001 From: Jason Fox Date: Thu, 16 Jan 2020 10:01:35 +0100 Subject: [PATCH 10/27] Remove package lock. --- package-lock.json | 8405 --------------------------------------------- 1 file changed, 8405 deletions(-) delete mode 100644 package-lock.json diff --git a/package-lock.json b/package-lock.json deleted file mode 100644 index 3687a9d28..000000000 --- a/package-lock.json +++ /dev/null @@ -1,8405 +0,0 @@ -{ - "name": "iotagent-node-lib", - "version": "2.11.0-next", - "lockfileVersion": 1, - "requires": true, - "dependencies": { - "@azu/format-text": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@azu/format-text/-/format-text-1.0.1.tgz", - "integrity": "sha1-aWc1CpRkD2sChVFpvYl85U1s6+I=", - "dev": true - }, - "@azu/style-format": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@azu/style-format/-/style-format-1.0.0.tgz", - "integrity": "sha1-5wGH+Khi4ZGxvObAJo8TrNOlayA=", - "dev": true, - "requires": { - "@azu/format-text": "^1.0.1" - } - }, - "@babel/code-frame": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.5.5.tgz", - "integrity": "sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw==", - "dev": true, - "requires": { - "@babel/highlight": "^7.0.0" - } - }, - "@babel/highlight": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.5.0.tgz", - "integrity": "sha512-7dV4eu9gBxoM0dAnj/BCFDW9LFU0zvTrkq0ugM7pnHEgguOEeOz1so2ZghEdzviYzQEED0r4EAgpsBChKy1TRQ==", - "dev": true, - "requires": { - "chalk": "^2.0.0", - "esutils": "^2.0.2", - "js-tokens": "^4.0.0" - }, - "dependencies": { - "esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true - } - } - }, - "@samverschueren/stream-to-observable": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@samverschueren/stream-to-observable/-/stream-to-observable-0.3.0.tgz", - "integrity": "sha512-MI4Xx6LHs4Webyvi6EbspgyAb4D2Q2VtnCQ1blOJcoLS6mVa8lNN2rkIy1CVxfTUpoyIbCTkXES1rLXztFD1lg==", - "dev": true, - "requires": { - "any-observable": "^0.3.0" - } - }, - "@textlint/ast-node-types": { - "version": "4.2.5", - "resolved": "https://registry.npmjs.org/@textlint/ast-node-types/-/ast-node-types-4.2.5.tgz", - "integrity": "sha512-+rEx4jLOeZpUcdvll7jEg/7hNbwYvHWFy4IGW/tk2JdbyB3SJVyIP6arAwzTH/sp/pO9jftfyZnRj4//sLbLvQ==", - "dev": true - }, - "@textlint/ast-tester": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/@textlint/ast-tester/-/ast-tester-2.1.6.tgz", - "integrity": "sha512-i+UrSKZXs561g8LXsCBkgpNYkgBS3T3Pif2/+DraZmSKpQ2r2D1yCOdH82IGPWWpQ/GMSg6Z0qpLJpjnYz+bpg==", - "dev": true, - "requires": { - "@textlint/ast-node-types": "^4.2.5" - } - }, - "@textlint/ast-traverse": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/@textlint/ast-traverse/-/ast-traverse-2.1.6.tgz", - "integrity": "sha512-qSPTUptR/C4YwoeVXRLUij6TpxbXT7U0P9S0No+p9Q+EYJeNvl1NUTrcpQmzrRydo6vCR0RzVkHmj+gEckH2Ug==", - "dev": true, - "requires": { - "@textlint/ast-node-types": "^4.2.5" - } - }, - "@textlint/feature-flag": { - "version": "3.1.6", - "resolved": "https://registry.npmjs.org/@textlint/feature-flag/-/feature-flag-3.1.6.tgz", - "integrity": "sha512-R2s027/WG3zhCMHZG79OhRFmkSL2ghwvFYg/W+2VUva5aYC8i9yeuwRyWt7m83tP1qlI+bq7j3S04fyn6yNheg==", - "dev": true, - "requires": { - "map-like": "^2.0.0" - } - }, - "@textlint/fixer-formatter": { - "version": "3.1.12", - "resolved": "https://registry.npmjs.org/@textlint/fixer-formatter/-/fixer-formatter-3.1.12.tgz", - "integrity": "sha512-MQcVkr6WT4m31gG32IYoOJ+vMw+YI/hpO1S2gwfuQo7z+qBWoqByydbEn4H6dtJzWCX9RBgi8D1lAL2HPvASYw==", - "dev": true, - "requires": { - "@textlint/module-interop": "^1.0.2", - "@textlint/types": "^1.3.0", - "chalk": "^1.1.3", - "debug": "^4.1.1", - "diff": "^4.0.1", - "is-file": "^1.0.0", - "string-width": "^1.0.1", - "strip-ansi": "^6.0.0", - "text-table": "^0.2.0", - "try-resolve": "^1.0.1" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - }, - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - }, - "dependencies": { - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - } - } - }, - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - }, - "dependencies": { - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - } - } - }, - "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" - }, - "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 - } - } - }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - } - } - }, - "@textlint/kernel": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/@textlint/kernel/-/kernel-3.2.0.tgz", - "integrity": "sha512-1uir4V/fFSLl7vkbQUt4BYkXmwAwrT8En7RAv3o6t7EugCwyLlzCluFwCHrTLgVMTTZuS5NIqUQZREUMP7U/vg==", - "dev": true, - "requires": { - "@textlint/ast-node-types": "^4.2.5", - "@textlint/ast-tester": "^2.1.6", - "@textlint/ast-traverse": "^2.1.6", - "@textlint/feature-flag": "^3.1.6", - "@textlint/types": "^1.3.0", - "@textlint/utils": "^1.0.3", - "@types/bluebird": "^3.5.18", - "bluebird": "^3.7.0", - "debug": "^4.1.1", - "deep-equal": "^1.1.0", - "map-like": "^2.0.0", - "structured-source": "^3.0.2" - }, - "dependencies": { - "bluebird": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", - "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", - "dev": true - }, - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "deep-equal": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.1.tgz", - "integrity": "sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g==", - "dev": true, - "requires": { - "is-arguments": "^1.0.4", - "is-date-object": "^1.0.1", - "is-regex": "^1.0.4", - "object-is": "^1.0.1", - "object-keys": "^1.1.1", - "regexp.prototype.flags": "^1.2.0" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - } - } - }, - "@textlint/linter-formatter": { - "version": "3.1.11", - "resolved": "https://registry.npmjs.org/@textlint/linter-formatter/-/linter-formatter-3.1.11.tgz", - "integrity": "sha512-tPFz8sGXWuDrhDRiHrLceasAN8AGM2ctt5uLvCxGVJ4Lmx6O7o+kDnHNGfIuF8rTRRQKWJ9jR/SCCH1SZulXmw==", - "dev": true, - "requires": { - "@azu/format-text": "^1.0.1", - "@azu/style-format": "^1.0.0", - "@textlint/module-interop": "^1.0.2", - "@textlint/types": "^1.3.0", - "chalk": "^1.0.0", - "concat-stream": "^1.5.1", - "debug": "^4.1.1", - "is-file": "^1.0.0", - "js-yaml": "^3.2.4", - "optionator": "^0.8.1", - "pluralize": "^2.0.0", - "string-width": "^1.0.1", - "string.prototype.padstart": "^3.0.0", - "strip-ansi": "^6.0.0", - "table": "^3.7.8", - "text-table": "^0.2.0", - "try-resolve": "^1.0.1", - "xml-escape": "^1.0.0" - }, - "dependencies": { - "ajv": { - "version": "4.11.8", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", - "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=", - "dev": true, - "requires": { - "co": "^4.6.0", - "json-stable-stringify": "^1.0.1" - } - }, - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - }, - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - }, - "dependencies": { - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - } - } - }, - "co": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", - "dev": true - }, - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - }, - "dependencies": { - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - } - } - }, - "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" - }, - "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 - } - } - }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - }, - "table": { - "version": "3.8.3", - "resolved": "https://registry.npmjs.org/table/-/table-3.8.3.tgz", - "integrity": "sha1-K7xULw/amGGnVdOUf+/Ys/UThV8=", - "dev": true, - "requires": { - "ajv": "^4.7.0", - "ajv-keywords": "^1.0.0", - "chalk": "^1.1.1", - "lodash": "^4.0.0", - "slice-ansi": "0.0.4", - "string-width": "^2.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "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 - }, - "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true, - "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - } - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "^3.0.0" - } - } - } - } - } - }, - "@textlint/markdown-to-ast": { - "version": "6.1.6", - "resolved": "https://registry.npmjs.org/@textlint/markdown-to-ast/-/markdown-to-ast-6.1.6.tgz", - "integrity": "sha512-xIaMn6gW1Ig+M+2Xcdbxt4cgOqWJSuB0pIO98KppQyqPzQ5k5deea7SBABqLZiKeNIxLl+2C1vfIfnBFFjxlmg==", - "dev": true, - "requires": { - "@textlint/ast-node-types": "^4.2.5", - "debug": "^4.1.1", - "remark-frontmatter": "^1.2.0", - "remark-parse": "^5.0.0", - "structured-source": "^3.0.2", - "traverse": "^0.6.6", - "unified": "^6.1.6" - }, - "dependencies": { - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "remark-parse": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-5.0.0.tgz", - "integrity": "sha512-b3iXszZLH1TLoyUzrATcTQUZrwNl1rE70rVdSruJFlDaJ9z5aMkhrG43Pp68OgfHndL/ADz6V69Zow8cTQu+JA==", - "dev": true, - "requires": { - "collapse-white-space": "^1.0.2", - "is-alphabetical": "^1.0.0", - "is-decimal": "^1.0.0", - "is-whitespace-character": "^1.0.0", - "is-word-character": "^1.0.0", - "markdown-escapes": "^1.0.0", - "parse-entities": "^1.1.0", - "repeat-string": "^1.5.4", - "state-toggle": "^1.0.0", - "trim": "0.0.1", - "trim-trailing-lines": "^1.0.0", - "unherit": "^1.0.4", - "unist-util-remove-position": "^1.0.0", - "vfile-location": "^2.0.0", - "xtend": "^4.0.1" - } - }, - "unified": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/unified/-/unified-6.2.0.tgz", - "integrity": "sha512-1k+KPhlVtqmG99RaTbAv/usu85fcSRu3wY8X+vnsEhIxNP5VbVIDiXnLqyKIG+UMdyTg0ZX9EI6k2AfjJkHPtA==", - "dev": true, - "requires": { - "bail": "^1.0.0", - "extend": "^3.0.0", - "is-plain-obj": "^1.1.0", - "trough": "^1.0.0", - "vfile": "^2.0.0", - "x-is-string": "^0.1.0" - } - }, - "unist-util-stringify-position": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-1.1.2.tgz", - "integrity": "sha512-pNCVrk64LZv1kElr0N1wPiHEUoXNVFERp+mlTg/s9R5Lwg87f9bM/3sQB99w+N9D/qnM9ar3+AKDBwo/gm/iQQ==", - "dev": true - }, - "vfile": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/vfile/-/vfile-2.3.0.tgz", - "integrity": "sha512-ASt4mBUHcTpMKD/l5Q+WJXNtshlWxOogYyGYYrg4lt/vuRjC1EFQtlAofL5VmtVNIZJzWYFJjzGWZ0Gw8pzW1w==", - "dev": true, - "requires": { - "is-buffer": "^1.1.4", - "replace-ext": "1.0.0", - "unist-util-stringify-position": "^1.0.0", - "vfile-message": "^1.0.0" - } - }, - "vfile-message": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-1.1.1.tgz", - "integrity": "sha512-1WmsopSGhWt5laNir+633LszXvZ+Z/lxveBf6yhGsqnQIhlhzooZae7zV6YVM1Sdkw68dtAW3ow0pOdPANugvA==", - "dev": true, - "requires": { - "unist-util-stringify-position": "^1.1.1" - } - } - } - }, - "@textlint/module-interop": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@textlint/module-interop/-/module-interop-1.0.2.tgz", - "integrity": "sha512-qQ6dqlg4SYywCywimIbkveQZu1MG6ugf6fcJuWDi3D51FbdkSRsMrPusJ1YoW6Y3XBp0ww9fJjXWtlUStGeQsw==", - "dev": true - }, - "@textlint/text-to-ast": { - "version": "3.1.6", - "resolved": "https://registry.npmjs.org/@textlint/text-to-ast/-/text-to-ast-3.1.6.tgz", - "integrity": "sha512-w0oBF3OeTT8syF+Y3BT1/pFYhBT2ZbzBDGqFELZVeBQNtGUKCpvJtu4Q1fCftElTbOIY01aSecj3GJTS6tmlBg==", - "dev": true, - "requires": { - "@textlint/ast-node-types": "^4.2.5" - } - }, - "@textlint/textlint-plugin-markdown": { - "version": "5.1.11", - "resolved": "https://registry.npmjs.org/@textlint/textlint-plugin-markdown/-/textlint-plugin-markdown-5.1.11.tgz", - "integrity": "sha512-DnCtNI10kejLPdEFu5pBHCDoBLJQTLnxwu76Mr/5iSEcYcytK2X72qiuvtg3c3s/8+at53TPQ6+5/AmpQKdvfg==", - "dev": true, - "requires": { - "@textlint/markdown-to-ast": "^6.1.6" - } - }, - "@textlint/textlint-plugin-text": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/@textlint/textlint-plugin-text/-/textlint-plugin-text-4.1.11.tgz", - "integrity": "sha512-gbZyn0z4vYjsVLeqqWRBvy3pXlObEJXkl6V+xrGF25SjeJVLs4V9yXsXOAPh3NrTBYxRTkxTiuzsopZx4l7Wzg==", - "dev": true, - "requires": { - "@textlint/text-to-ast": "^3.1.6" - } - }, - "@textlint/types": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@textlint/types/-/types-1.3.0.tgz", - "integrity": "sha512-PJM3u0dnKyFCQJfhS+ft4OPse10P2PXz7bM2YJMyEs6kKOc2hDvZE7CH8F85GuSL9H5gToTqJ9/c3Yy4I3S+iA==", - "dev": true, - "requires": { - "@textlint/ast-node-types": "^4.2.5" - } - }, - "@textlint/utils": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@textlint/utils/-/utils-1.0.3.tgz", - "integrity": "sha512-6oGaBKXYpg5Ooph5p32OFdp1dXDUC1z5mpHg2gmQbx6QZjmP4QX+ygBQdNoCq15d1w88+We6koJl0n0WXjItYw==", - "dev": true - }, - "@types/bluebird": { - "version": "3.5.29", - "resolved": "https://registry.npmjs.org/@types/bluebird/-/bluebird-3.5.29.tgz", - "integrity": "sha512-kmVtnxTuUuhCET669irqQmPAez4KFnFVKvpleVRyfC3g+SHD1hIkFZcWLim9BVcwUBLO59o8VZE4yGCmTif8Yw==", - "dev": true - }, - "@types/node": { - "version": "13.1.7", - "resolved": "https://registry.npmjs.org/@types/node/-/node-13.1.7.tgz", - "integrity": "sha512-HU0q9GXazqiKwviVxg9SI/+t/nAsGkvLDkIdxz+ObejG2nX6Si00TeLqHMoS+a/1tjH7a8YpKVQwtgHuMQsldg==", - "dev": true - }, - "@types/unist": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.3.tgz", - "integrity": "sha512-FvUupuM3rlRsRtCN+fDudtmytGO6iHJuuRKS1Ss0pG5z8oX0diNEw94UEL7hgDbpN94rgaK5R7sWm6RrSkZuAQ==", - "dev": true - }, - "@types/vfile": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@types/vfile/-/vfile-3.0.2.tgz", - "integrity": "sha512-b3nLFGaGkJ9rzOcuXRfHkZMdjsawuDD0ENL9fzTophtBg8FJHSGbH7daXkEpcwy3v7Xol3pAvsmlYyFhR4pqJw==", - "dev": true, - "requires": { - "@types/node": "*", - "@types/unist": "*", - "@types/vfile-message": "*" - } - }, - "@types/vfile-message": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@types/vfile-message/-/vfile-message-2.0.0.tgz", - "integrity": "sha512-GpTIuDpb9u4zIO165fUy9+fXcULdD8HFRNli04GehoMVbeNq7D6OBnqSmg3lxZnC+UvgUhEWKxdKiwYUkGltIw==", - "dev": true, - "requires": { - "vfile-message": "*" - } - }, - "JSONSelect": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/JSONSelect/-/JSONSelect-0.4.0.tgz", - "integrity": "sha1-oI7cxn6z/L6Z7WMIVTRKDPKCu40=" - }, - "JSV": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/JSV/-/JSV-4.0.2.tgz", - "integrity": "sha1-0Hf2glVx+CEy+d/67Vh7QCn+/1c=" - }, - "abbrev": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz", - "integrity": "sha1-kbR5JYinc4wl813W9jdSovh3YTU=", - "dev": true - }, - "accepts": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz", - "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=", - "requires": { - "mime-types": "~2.1.18", - "negotiator": "0.6.1" - } - }, - "acorn": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.0.tgz", - "integrity": "sha512-gac8OEcQ2Li1dxIEWGZzsp2BitJxwkwcOm0zHAJLcPJaVvm58FRnk6RkuLRpU1EujipU2ZFODv2P9DLMfnV8mw==", - "dev": true - }, - "acorn-jsx": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.1.0.tgz", - "integrity": "sha512-tMUqwBWfLFbJbizRmEcWSLw6HnFzfdJs2sOJEOwwtVPMoH/0Ay+E703oZz78VSXZiiDcZrQ5XKjPIUQixhmgVw==", - "dev": true - }, - "adverb-where": { - "version": "0.0.9", - "resolved": "https://registry.npmjs.org/adverb-where/-/adverb-where-0.0.9.tgz", - "integrity": "sha1-CcXN3Y1QO5/l924LjcXHCo8ZPjQ=", - "dev": true - }, - "ajv": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.7.0.tgz", - "integrity": "sha512-RZXPviBTtfmtka9n9sy1N5M5b82CbxWIR6HIis4s3WQTXDJamc/0gpCWNGz6EWdWp4DOfjzJfhz/AS9zVPjjWg==", - "requires": { - "fast-deep-equal": "^2.0.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "ajv-keywords": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-1.5.1.tgz", - "integrity": "sha1-MU3QpLM2j609/NxU7eYXG4htrzw=", - "dev": true - }, - "amdefine": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", - "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", - "optional": true - }, - "ansi-colors": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.3.tgz", - "integrity": "sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw==", - "dev": true - }, - "ansi-escapes": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", - "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", - "dev": true - }, - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "any-observable": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/any-observable/-/any-observable-0.3.0.tgz", - "integrity": "sha512-/FQM1EDkTsf63Ub2C6O7GuYFDsSXUwsaZDurV0np41ocwq0jthUAYCmhBX9f+KwlaCgIuWyr/4WlUQUBfKfZog==", - "dev": true - }, - "anymatch": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", - "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", - "dev": true, - "requires": { - "micromatch": "^3.1.4", - "normalize-path": "^2.1.1" - }, - "dependencies": { - "normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "dev": true, - "requires": { - "remove-trailing-separator": "^1.0.1" - } - } - } - }, - "argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "requires": { - "sprintf-js": "~1.0.2" - } - }, - "arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", - "dev": true - }, - "arr-flatten": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", - "dev": true - }, - "arr-union": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", - "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", - "dev": true - }, - "array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" - }, - "array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", - "dev": true - }, - "asn1": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", - "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", - "requires": { - "safer-buffer": "~2.1.0" - } - }, - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" - }, - "assertion-error": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", - "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", - "dev": true - }, - "assign-symbols": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", - "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", - "dev": true - }, - "astral-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", - "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", - "dev": true - }, - "async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.2.tgz", - "integrity": "sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg==", - "requires": { - "lodash": "^4.17.11" - } - }, - "async-each": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz", - "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==", - "dev": true - }, - "asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" - }, - "atob": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", - "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", - "dev": true - }, - "aws-sign2": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" - }, - "aws4": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", - "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==" - }, - "bail": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/bail/-/bail-1.0.4.tgz", - "integrity": "sha512-S8vuDB4w6YpRhICUDET3guPlQpaJl7od94tpZ0Fvnyp+MKW/HyDTcRDck+29C9g+d/qQHnddRH3+94kZdrW0Ww==", - "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 - }, - "base": { - "version": "0.11.2", - "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", - "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", - "dev": true, - "requires": { - "cache-base": "^1.0.1", - "class-utils": "^0.3.5", - "component-emitter": "^1.2.1", - "define-property": "^1.0.0", - "isobject": "^3.0.1", - "mixin-deep": "^1.2.0", - "pascalcase": "^0.1.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } - } - }, - "bcrypt-pbkdf": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", - "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", - "requires": { - "tweetnacl": "^0.14.3" - } - }, - "binary-extensions": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", - "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", - "dev": true - }, - "bindings": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", - "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", - "dev": true, - "optional": true, - "requires": { - "file-uri-to-path": "1.0.0" - } - }, - "bluebird": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz", - "integrity": "sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA==" - }, - "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" - }, - "dependencies": { - "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" - } - }, - "mime-db": { - "version": "1.40.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz", - "integrity": "sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA==" - }, - "mime-types": { - "version": "2.1.24", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz", - "integrity": "sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==", - "requires": { - "mime-db": "1.40.0" - } - }, - "qs": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", - "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==" - }, - "setprototypeof": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", - "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" - }, - "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" - } - } - } - }, - "boundary": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/boundary/-/boundary-1.0.1.tgz", - "integrity": "sha1-TWfcJgLAzBbdm85+v4fpSCkPWBI=", - "dev": true - }, - "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": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "dev": true, - "requires": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "browser-stdout": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", - "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", - "dev": true - }, - "bson": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/bson/-/bson-1.1.1.tgz", - "integrity": "sha512-jCGVYLoYMHDkOsbwJZBCqwMHyH4c+wzgI9hG7Z6SZJRXWr+x58pdIbm2i9a/jFGCkRJqRUr8eoI7lDWa0hTkxg==" - }, - "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==" - }, - "cache-base": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", - "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", - "dev": true, - "requires": { - "collection-visit": "^1.0.0", - "component-emitter": "^1.2.1", - "get-value": "^2.0.6", - "has-value": "^1.0.0", - "isobject": "^3.0.1", - "set-value": "^2.0.0", - "to-object-path": "^0.3.0", - "union-value": "^1.0.0", - "unset-value": "^1.0.0" - } - }, - "caller-callsite": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/caller-callsite/-/caller-callsite-2.0.0.tgz", - "integrity": "sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ=", - "dev": true, - "requires": { - "callsites": "^2.0.0" - } - }, - "caller-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-2.0.0.tgz", - "integrity": "sha1-Ro+DBE42mrIBD6xfBs7uFbsssfQ=", - "dev": true, - "requires": { - "caller-callsite": "^2.0.0" - } - }, - "callsites": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz", - "integrity": "sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA=", - "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 - }, - "caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" - }, - "ccount": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/ccount/-/ccount-1.0.4.tgz", - "integrity": "sha512-fpZ81yYfzentuieinmGnphk0pLkOTMm6MZdVqwd77ROvhko6iujLNGrHH5E7utq3ygWklwfmwuG+A7P+NpqT6w==", - "dev": true - }, - "chai": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/chai/-/chai-4.2.0.tgz", - "integrity": "sha512-XQU3bhBukrOsQCuwZndwGcCVQHyZi53fQ6Ys1Fym7E4olpIqqZZhhoFJoaKVvV17lWQoXYwgWN2nF5crA8J2jw==", - "dev": true, - "requires": { - "assertion-error": "^1.1.0", - "check-error": "^1.0.2", - "deep-eql": "^3.0.1", - "get-func-name": "^2.0.0", - "pathval": "^1.1.0", - "type-detect": "^4.0.5" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "dependencies": { - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "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" - } - } - } - }, - "character-entities": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-1.2.3.tgz", - "integrity": "sha512-yB4oYSAa9yLcGyTbB4ItFwHw43QHdH129IJ5R+WvxOkWlyFnR5FAaBNnUq4mcxsTVZGh28bHoeTHMKXH1wZf3w==", - "dev": true - }, - "character-entities-html4": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-1.1.3.tgz", - "integrity": "sha512-SwnyZ7jQBCRHELk9zf2CN5AnGEc2nA+uKMZLHvcqhpPprjkYhiLn0DywMHgN5ttFZuITMATbh68M6VIVKwJbcg==", - "dev": true - }, - "character-entities-legacy": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-1.1.3.tgz", - "integrity": "sha512-YAxUpPoPwxYFsslbdKkhrGnXAtXoHNgYjlBM3WMXkWGTl5RsY3QmOyhwAgL8Nxm9l5LBThXGawxKPn68y6/fww==", - "dev": true - }, - "character-reference-invalid": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-1.1.3.tgz", - "integrity": "sha512-VOq6PRzQBam/8Jm6XBGk2fNEnHXAdGd6go0rtd4weAGECBamHDwwCQSOT12TACIYUZegUXnV6xBXqUssijtxIg==", - "dev": true - }, - "chardet": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", - "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", - "dev": true - }, - "charenc": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz", - "integrity": "sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc=", - "dev": true - }, - "check-error": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", - "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", - "dev": true - }, - "chokidar": { - "version": "2.1.8", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", - "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", - "dev": true, - "requires": { - "anymatch": "^2.0.0", - "async-each": "^1.0.1", - "braces": "^2.3.2", - "fsevents": "^1.2.7", - "glob-parent": "^3.1.0", - "inherits": "^2.0.3", - "is-binary-path": "^1.0.0", - "is-glob": "^4.0.0", - "normalize-path": "^3.0.0", - "path-is-absolute": "^1.0.0", - "readdirp": "^2.2.1", - "upath": "^1.1.1" - } - }, - "ci-info": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-1.6.0.tgz", - "integrity": "sha512-vsGdkwSCDpWmP80ncATX7iea5DWQemg1UgCW5J8tqjU3lYw4FBYuj89J0CTVomA7BEfvSZd84GmHko+MxFQU2A==", - "dev": true - }, - "cjson": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/cjson/-/cjson-0.3.0.tgz", - "integrity": "sha1-5kObkHA9MS/24iJAl76pLOPQKhQ=", - "requires": { - "jsonlint": "1.6.0" - } - }, - "class-utils": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", - "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", - "dev": true, - "requires": { - "arr-union": "^3.1.0", - "define-property": "^0.2.5", - "isobject": "^3.0.0", - "static-extend": "^0.1.1" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - } - } - }, - "cli-cursor": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", - "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", - "dev": true, - "requires": { - "restore-cursor": "^2.0.0" - } - }, - "cli-truncate": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-0.2.1.tgz", - "integrity": "sha1-nxXPuwcFAFNpIWxiasfQWrkN1XQ=", - "dev": true, - "requires": { - "slice-ansi": "0.0.4", - "string-width": "^1.0.1" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - } - } - }, - "cli-width": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", - "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=", - "dev": true - }, - "cliui": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", - "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", - "dev": true, - "requires": { - "string-width": "^2.1.1", - "strip-ansi": "^4.0.0", - "wrap-ansi": "^2.0.0" - } - }, - "co": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/co/-/co-3.1.0.tgz", - "integrity": "sha1-TqVOpaCJOBUxheFSEMaNkJK8G3g=", - "dev": true - }, - "code-point-at": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", - "dev": true - }, - "collapse-white-space": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-1.0.5.tgz", - "integrity": "sha512-703bOOmytCYAX9cXYqoikYIx6twmFCXsnzRQheBcTG3nzKYBR4P/+wkYeH+Mvj7qUz8zZDtdyzbxfnEi/kYzRQ==", - "dev": true - }, - "collection-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", - "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", - "dev": true, - "requires": { - "map-visit": "^1.0.0", - "object-visit": "^1.0.0" - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, - "colors": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/colors/-/colors-0.5.1.tgz", - "integrity": "sha1-fQAj6usVTo7p/Oddy5I9DtFmd3Q=" - }, - "combined-stream": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz", - "integrity": "sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w==", - "requires": { - "delayed-stream": "~1.0.0" - } - }, - "command-shell-lib": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/command-shell-lib/-/command-shell-lib-1.0.0.tgz", - "integrity": "sha1-KWC3MJvpBwojAYYjcvvjjtL3+RA=", - "requires": { - "async": "*" - } - }, - "commander": { - "version": "2.20.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.0.tgz", - "integrity": "sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==", - "dev": true - }, - "component-emitter": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", - "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", - "dev": true - }, - "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 - }, - "concat-stream": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", - "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", - "dev": true, - "requires": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^2.2.2", - "typedarray": "^0.0.6" - } - }, - "content-disposition": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", - "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ=" - }, - "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.3.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", - "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=" - }, - "cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" - }, - "copy-descriptor": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", - "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", - "dev": true - }, - "core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" - }, - "cosmiconfig": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.1.tgz", - "integrity": "sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==", - "dev": true, - "requires": { - "import-fresh": "^2.0.0", - "is-directory": "^0.3.1", - "js-yaml": "^3.13.1", - "parse-json": "^4.0.0" - } - }, - "coveralls": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/coveralls/-/coveralls-3.0.3.tgz", - "integrity": "sha512-viNfeGlda2zJr8Gj1zqXpDMRjw9uM54p7wzZdvLRyOgnAfCe974Dq4veZkjJdxQXbmdppu6flEajFYseHYaUhg==", - "dev": true, - "requires": { - "growl": "~> 1.10.0", - "js-yaml": "^3.11.0", - "lcov-parse": "^0.0.10", - "log-driver": "^1.2.7", - "minimist": "^1.2.0", - "request": "^2.86.0" - } - }, - "cross-spawn": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", - "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", - "dev": true, - "requires": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - } - }, - "crypt": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz", - "integrity": "sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs=", - "dev": true - }, - "dashdash": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", - "requires": { - "assert-plus": "^1.0.0" - } - }, - "date-fns": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-1.30.1.tgz", - "integrity": "sha512-hBSVCvSmWC+QypYObzwGOd9wqdDpOt+0wl0KbU+R+uuZBS1jN8VsD1ss3irQDknRj5NvxiTF6oj/nDRnN/UQNw==", - "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" - } - }, - "decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", - "dev": true - }, - "decode-uri-component": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", - "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=" - }, - "dedent": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", - "integrity": "sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw=", - "dev": true - }, - "deep-eql": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", - "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", - "dev": true, - "requires": { - "type-detect": "^4.0.0" - } - }, - "deep-equal": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz", - "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=", - "dev": true - }, - "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 - }, - "deep-is": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", - "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", - "dev": true - }, - "define-properties": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", - "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", - "dev": true, - "requires": { - "object-keys": "^1.0.12" - } - }, - "define-property": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", - "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", - "dev": true, - "requires": { - "is-descriptor": "^1.0.2", - "isobject": "^3.0.1" - }, - "dependencies": { - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } - } - }, - "delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" - }, - "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": "3.5.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", - "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", - "dev": true - }, - "doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "requires": { - "esutils": "^2.0.2" - }, - "dependencies": { - "esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true - } - } - }, - "e-prime": { - "version": "0.10.2", - "resolved": "https://registry.npmjs.org/e-prime/-/e-prime-0.10.2.tgz", - "integrity": "sha1-6pN165hWNt6IATx6n7EprZ4V7/g=", - "dev": true - }, - "ebnf-parser": { - "version": "0.1.10", - "resolved": "https://registry.npmjs.org/ebnf-parser/-/ebnf-parser-0.1.10.tgz", - "integrity": "sha1-zR9rpHfFY4xAyX7ZtXLbW6tdgzE=" - }, - "ecc-jsbn": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", - "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", - "requires": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" - } - }, - "ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" - }, - "elegant-spinner": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/elegant-spinner/-/elegant-spinner-1.0.1.tgz", - "integrity": "sha1-2wQ1IcldfjA/2PNFvtwzSc+wcp4=", - "dev": true - }, - "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.1", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", - "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", - "dev": true, - "requires": { - "once": "^1.4.0" - } - }, - "error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, - "requires": { - "is-arrayish": "^0.2.1" - } - }, - "es-abstract": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.13.0.tgz", - "integrity": "sha512-vDZfg/ykNxQVwup/8E1BZhVzFfBxs9NqMzGcvIJrqg5k2/5Za2bWo40dK2J1pgLngZ7c+Shh8lwYtLGyrwPutg==", - "dev": true, - "requires": { - "es-to-primitive": "^1.2.0", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "is-callable": "^1.1.4", - "is-regex": "^1.0.4", - "object-keys": "^1.0.12" - } - }, - "es-to-primitive": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz", - "integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==", - "dev": true, - "requires": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - } - }, - "escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true - }, - "escodegen": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.3.3.tgz", - "integrity": "sha1-8CQBb1qI4Eb9EgBQVek5gC5sXyM=", - "requires": { - "esprima": "~1.1.1", - "estraverse": "~1.5.0", - "esutils": "~1.0.0", - "source-map": "~0.1.33" - } - }, - "eslint": { - "version": "5.16.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-5.16.0.tgz", - "integrity": "sha512-S3Rz11i7c8AA5JPv7xAH+dOyq/Cu/VXHiHXBPOU1k/JAM5dXqQPt3qcrhpHSorXmrpu2g0gkIBVXAqCpzfoZIg==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.0.0", - "ajv": "^6.9.1", - "chalk": "^2.1.0", - "cross-spawn": "^6.0.5", - "debug": "^4.0.1", - "doctrine": "^3.0.0", - "eslint-scope": "^4.0.3", - "eslint-utils": "^1.3.1", - "eslint-visitor-keys": "^1.0.0", - "espree": "^5.0.1", - "esquery": "^1.0.1", - "esutils": "^2.0.2", - "file-entry-cache": "^5.0.1", - "functional-red-black-tree": "^1.0.1", - "glob": "^7.1.2", - "globals": "^11.7.0", - "ignore": "^4.0.6", - "import-fresh": "^3.0.0", - "imurmurhash": "^0.1.4", - "inquirer": "^6.2.2", - "js-yaml": "^3.13.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.3.0", - "lodash": "^4.17.11", - "minimatch": "^3.0.4", - "mkdirp": "^0.5.1", - "natural-compare": "^1.4.0", - "optionator": "^0.8.2", - "path-is-inside": "^1.0.2", - "progress": "^2.0.0", - "regexpp": "^2.0.1", - "semver": "^5.5.1", - "strip-ansi": "^4.0.0", - "strip-json-comments": "^2.0.1", - "table": "^5.2.3", - "text-table": "^0.2.0" - }, - "dependencies": { - "ajv": { - "version": "6.10.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz", - "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==", - "dev": true, - "requires": { - "fast-deep-equal": "^2.0.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true - }, - "glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "import-fresh": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.1.tgz", - "integrity": "sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ==", - "dev": true, - "requires": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true - }, - "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 - } - } - }, - "eslint-config-tamia": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/eslint-config-tamia/-/eslint-config-tamia-6.2.1.tgz", - "integrity": "sha512-DZgK/08P1OshIwEWBzpGzRFYTL8wDQcuyBKPy16xR6dT1gg4Dapf7/5vWj88djwpW5XrzTvXv2G1yrIfH1ygkQ==", - "dev": true - }, - "eslint-plugin-prettier": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-3.1.1.tgz", - "integrity": "sha512-A+TZuHZ0KU0cnn56/9mfR7/KjUJ9QNVXUhwvRFSR7PGPe0zQR6PTkmyqg1AtUUEOzTqeRsUwyKFh0oVZKVCrtA==", - "dev": true, - "requires": { - "prettier-linter-helpers": "^1.0.0" - } - }, - "eslint-scope": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", - "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==", - "dev": true, - "requires": { - "esrecurse": "^4.1.0", - "estraverse": "^4.1.1" - }, - "dependencies": { - "estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true - } - } - }, - "eslint-utils": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.3.tgz", - "integrity": "sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q==", - "dev": true, - "requires": { - "eslint-visitor-keys": "^1.1.0" - } - }, - "eslint-visitor-keys": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz", - "integrity": "sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A==", - "dev": true - }, - "espree": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-5.0.1.tgz", - "integrity": "sha512-qWAZcWh4XE/RwzLJejfcofscgMc9CamR6Tn1+XRXNzrvUSSbiAjGOI/fggztjIi7y9VLPqnICMIPiGyr8JaZ0A==", - "dev": true, - "requires": { - "acorn": "^6.0.7", - "acorn-jsx": "^5.0.0", - "eslint-visitor-keys": "^1.0.0" - } - }, - "esprima": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-1.1.1.tgz", - "integrity": "sha1-W28VR/TRAuZw4UDFCb5ncdautUk=" - }, - "esquery": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.1.tgz", - "integrity": "sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA==", - "dev": true, - "requires": { - "estraverse": "^4.0.0" - }, - "dependencies": { - "estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true - } - } - }, - "esrecurse": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", - "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", - "dev": true, - "requires": { - "estraverse": "^4.1.0" - }, - "dependencies": { - "estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true - } - } - }, - "estraverse": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.5.1.tgz", - "integrity": "sha1-hno+jlip+EYYr7bC3bzZFrfLr3E=" - }, - "esutils": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-1.0.0.tgz", - "integrity": "sha1-gVHTWOIMisx/t0XnRywAJf5JZXA=" - }, - "etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" - }, - "eventemitter3": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.0.tgz", - "integrity": "sha512-qerSRB0p+UDEssxTtm6EDKcE7W4OaoisfIMl4CngyEhjpYglocpNg6UEqCvemdGhosAsg4sO2dXJOdyBifPGCg==", - "dev": true - }, - "exec-sh": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/exec-sh/-/exec-sh-0.2.2.tgz", - "integrity": "sha512-FIUCJz1RbuS0FKTdaAafAByGS0CPvU3R0MeHxgtl+djzCc//F8HakL8GzmVNZanasTbTAY/3DRFA0KpVqj/eAw==", - "dev": true, - "requires": { - "merge": "^1.2.0" - } - }, - "execa": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", - "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", - "dev": true, - "requires": { - "cross-spawn": "^6.0.0", - "get-stream": "^4.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" - } - }, - "expand-brackets": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", - "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", - "dev": true, - "requires": { - "debug": "^2.3.3", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "posix-character-classes": "^0.1.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "express": { - "version": "4.16.4", - "resolved": "https://registry.npmjs.org/express/-/express-4.16.4.tgz", - "integrity": "sha512-j12Uuyb4FMrd/qQAm6uCHAkPtO8FDTRJZBDd5D2KOL2eLaz1yUNdUB/NOIyq0iU4q4cFarsUCrnFDPBcnksuOg==", - "requires": { - "accepts": "~1.3.5", - "array-flatten": "1.1.1", - "body-parser": "1.18.3", - "content-disposition": "0.5.2", - "content-type": "~1.0.4", - "cookie": "0.3.1", - "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.1", - "fresh": "0.5.2", - "merge-descriptors": "1.0.1", - "methods": "~1.1.2", - "on-finished": "~2.3.0", - "parseurl": "~1.3.2", - "path-to-regexp": "0.1.7", - "proxy-addr": "~2.0.4", - "qs": "6.5.2", - "range-parser": "~1.2.0", - "safe-buffer": "5.1.2", - "send": "0.16.2", - "serve-static": "1.13.2", - "setprototypeof": "1.1.0", - "statuses": "~1.4.0", - "type-is": "~1.6.16", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - }, - "dependencies": { - "body-parser": { - "version": "1.18.3", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.3.tgz", - "integrity": "sha1-WykhmP/dVTs6DyDe0FkrlWlVyLQ=", - "requires": { - "bytes": "3.0.0", - "content-type": "~1.0.4", - "debug": "2.6.9", - "depd": "~1.1.2", - "http-errors": "~1.6.3", - "iconv-lite": "0.4.23", - "on-finished": "~2.3.0", - "qs": "6.5.2", - "raw-body": "2.3.3", - "type-is": "~1.6.16" - } - }, - "bytes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", - "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=" - }, - "iconv-lite": { - "version": "0.4.23", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", - "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "raw-body": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.3.tgz", - "integrity": "sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw==", - "requires": { - "bytes": "3.0.0", - "http-errors": "1.6.3", - "iconv-lite": "0.4.23", - "unpipe": "1.0.0" - } - }, - "statuses": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", - "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==" - } - } - }, - "extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" - }, - "extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "dev": true, - "requires": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - }, - "dependencies": { - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4" - } - } - } - }, - "external-editor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", - "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", - "dev": true, - "requires": { - "chardet": "^0.7.0", - "iconv-lite": "^0.4.24", - "tmp": "^0.0.33" - } - }, - "extglob": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", - "dev": true, - "requires": { - "array-unique": "^0.3.2", - "define-property": "^1.0.0", - "expand-brackets": "^2.1.4", - "extend-shallow": "^2.0.1", - "fragment-cache": "^0.2.1", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } - } - }, - "extsprintf": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" - }, - "fast-deep-equal": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", - "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=" - }, - "fast-diff": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz", - "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==", - "dev": true - }, - "fast-json-stable-stringify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", - "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" - }, - "fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", - "dev": true - }, - "fault": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/fault/-/fault-1.0.3.tgz", - "integrity": "sha512-sfFuP4X0hzrbGKjAUNXYvNqsZ5F6ohx/dZ9I0KQud/aiZNwg263r5L9yGB0clvXHCkzXh5W3t7RSHchggYIFmA==", - "dev": true, - "requires": { - "format": "^0.2.2" - } - }, - "figures": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", - "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", - "dev": true, - "requires": { - "escape-string-regexp": "^1.0.5", - "object-assign": "^4.1.0" - } - }, - "file-entry-cache": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz", - "integrity": "sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==", - "dev": true, - "requires": { - "flat-cache": "^2.0.1" - } - }, - "file-uri-to-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", - "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", - "dev": true, - "optional": true - }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "finalhandler": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz", - "integrity": "sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg==", - "requires": { - "debug": "2.6.9", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "on-finished": "~2.3.0", - "parseurl": "~1.3.2", - "statuses": "~1.4.0", - "unpipe": "~1.0.0" - }, - "dependencies": { - "statuses": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", - "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==" - } - } - }, - "find-parent-dir": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/find-parent-dir/-/find-parent-dir-0.3.0.tgz", - "integrity": "sha1-M8RLQpqysvBkYpnF+fcY83b/jVQ=", - "dev": true - }, - "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "requires": { - "locate-path": "^3.0.0" - } - }, - "flat": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/flat/-/flat-4.1.0.tgz", - "integrity": "sha512-Px/TiLIznH7gEDlPXcUD4KnBusa6kR6ayRUVcnEAbreRIuhkqow/mun59BuRXwoYk7ZQOLW1ZM05ilIvK38hFw==", - "dev": true, - "requires": { - "is-buffer": "~2.0.3" - } - }, - "flat-cache": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz", - "integrity": "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==", - "dev": true, - "requires": { - "flatted": "^2.0.0", - "rimraf": "2.6.3", - "write": "1.0.3" - } - }, - "flatted": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.1.tgz", - "integrity": "sha512-a1hQMktqW9Nmqr5aktAux3JMNqaucxGcjtjWnZLHX7yyPCmlSV3M54nGYbqT8K+0GhF3NBgmJCc3ma+WOgX8Jg==", - "dev": true - }, - "fn-name": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/fn-name/-/fn-name-2.0.1.tgz", - "integrity": "sha1-UhTXU3pNBqSjAcDMJi/rhBiAAuc=", - "dev": true - }, - "for-in": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", - "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", - "dev": true - }, - "forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" - }, - "form-data": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", - "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - } - }, - "format": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/format/-/format-0.2.2.tgz", - "integrity": "sha1-1hcBB+nv3E7TDJ3DkBbflCtctYs=", - "dev": true - }, - "forwarded": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", - "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=" - }, - "fragment-cache": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", - "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", - "dev": true, - "requires": { - "map-cache": "^0.2.2" - } - }, - "fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" - }, - "fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", - "dev": true, - "requires": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - } - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true - }, - "fsevents": { - "version": "1.2.11", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.11.tgz", - "integrity": "sha512-+ux3lx6peh0BpvY0JebGyZoiR4D+oYzdPZMKJwkZ+sFkNJzpL7tXc/wehS49gUAxg3tmMHPHZkA8JU2rhhgDHw==", - "dev": true, - "optional": true, - "requires": { - "bindings": "^1.5.0", - "nan": "^2.12.1", - "node-pre-gyp": "*" - }, - "dependencies": { - "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, - "optional": true - }, - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true, - "optional": true - }, - "aproba": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", - "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", - "dev": true, - "optional": true - }, - "are-we-there-yet": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz", - "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", - "dev": true, - "optional": true, - "requires": { - "delegates": "^1.0.0", - "readable-stream": "^2.0.6" - } - }, - "balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", - "dev": true, - "optional": true - }, - "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, - "optional": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "chownr": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.3.tgz", - "integrity": "sha512-i70fVHhmV3DtTl6nqvZOnIjbY0Pe4kAUjwHj8z0zAdgBtYrJyYwLKCCuRBQ5ppkyL0AkN7HKRnETdmdp1zqNXw==", - "dev": true, - "optional": true - }, - "code-point-at": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", - "dev": true, - "optional": true - }, - "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, - "optional": true - }, - "console-control-strings": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", - "dev": true, - "optional": true - }, - "core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", - "dev": true, - "optional": true - }, - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true, - "optional": true, - "requires": { - "ms": "^2.1.1" - } - }, - "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, - "optional": true - }, - "delegates": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", - "dev": true, - "optional": true - }, - "detect-libc": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", - "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=", - "dev": true, - "optional": true - }, - "fs-minipass": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz", - "integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==", - "dev": true, - "optional": true, - "requires": { - "minipass": "^2.6.0" - } - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true, - "optional": true - }, - "gauge": { - "version": "2.7.4", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", - "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", - "dev": true, - "optional": true, - "requires": { - "aproba": "^1.0.3", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.0", - "object-assign": "^4.1.0", - "signal-exit": "^3.0.0", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wide-align": "^1.1.0" - } - }, - "glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", - "dev": true, - "optional": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "has-unicode": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", - "dev": true, - "optional": true - }, - "iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, - "optional": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "ignore-walk": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.3.tgz", - "integrity": "sha512-m7o6xuOaT1aqheYHKf8W6J5pYH85ZI9w077erOzLje3JsB1gkafkAhHHY19dqjulgIZHFm32Cp5uNZgcQqdJKw==", - "dev": true, - "optional": true, - "requires": { - "minimatch": "^3.0.4" - } - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, - "optional": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true, - "optional": true - }, - "ini": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", - "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", - "dev": true, - "optional": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "optional": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true, - "optional": true - }, - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, - "optional": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", - "dev": true, - "optional": true - }, - "minipass": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz", - "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", - "dev": true, - "optional": true, - "requires": { - "safe-buffer": "^5.1.2", - "yallist": "^3.0.0" - } - }, - "minizlib": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz", - "integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==", - "dev": true, - "optional": true, - "requires": { - "minipass": "^2.9.0" - } - }, - "mkdirp": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", - "dev": true, - "optional": true, - "requires": { - "minimist": "0.0.8" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true, - "optional": true - }, - "needle": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/needle/-/needle-2.4.0.tgz", - "integrity": "sha512-4Hnwzr3mi5L97hMYeNl8wRW/Onhy4nUKR/lVemJ8gJedxxUyBLm9kkrDColJvoSfwi0jCNhD+xCdOtiGDQiRZg==", - "dev": true, - "optional": true, - "requires": { - "debug": "^3.2.6", - "iconv-lite": "^0.4.4", - "sax": "^1.2.4" - } - }, - "node-pre-gyp": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.14.0.tgz", - "integrity": "sha512-+CvDC7ZttU/sSt9rFjix/P05iS43qHCOOGzcr3Ry99bXG7VX953+vFyEuph/tfqoYu8dttBkE86JSKBO2OzcxA==", - "dev": true, - "optional": true, - "requires": { - "detect-libc": "^1.0.2", - "mkdirp": "^0.5.1", - "needle": "^2.2.1", - "nopt": "^4.0.1", - "npm-packlist": "^1.1.6", - "npmlog": "^4.0.2", - "rc": "^1.2.7", - "rimraf": "^2.6.1", - "semver": "^5.3.0", - "tar": "^4.4.2" - } - }, - "nopt": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.1.tgz", - "integrity": "sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=", - "dev": true, - "optional": true, - "requires": { - "abbrev": "1", - "osenv": "^0.1.4" - } - }, - "npm-bundled": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.1.1.tgz", - "integrity": "sha512-gqkfgGePhTpAEgUsGEgcq1rqPXA+tv/aVBlgEzfXwA1yiUJF7xtEt3CtVwOjNYQOVknDk0F20w58Fnm3EtG0fA==", - "dev": true, - "optional": true, - "requires": { - "npm-normalize-package-bin": "^1.0.1" - } - }, - "npm-normalize-package-bin": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz", - "integrity": "sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==", - "dev": true, - "optional": true - }, - "npm-packlist": { - "version": "1.4.7", - "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.4.7.tgz", - "integrity": "sha512-vAj7dIkp5NhieaGZxBJB8fF4R0078rqsmhJcAfXZ6O7JJhjhPK96n5Ry1oZcfLXgfun0GWTZPOxaEyqv8GBykQ==", - "dev": true, - "optional": true, - "requires": { - "ignore-walk": "^3.0.1", - "npm-bundled": "^1.0.1" - } - }, - "npmlog": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", - "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", - "dev": true, - "optional": true, - "requires": { - "are-we-there-yet": "~1.1.2", - "console-control-strings": "~1.1.0", - "gauge": "~2.7.3", - "set-blocking": "~2.0.0" - } - }, - "number-is-nan": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", - "dev": true, - "optional": true - }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "dev": true, - "optional": true - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, - "optional": true, - "requires": { - "wrappy": "1" - } - }, - "os-homedir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", - "dev": true, - "optional": true - }, - "os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", - "dev": true, - "optional": true - }, - "osenv": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", - "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", - "dev": true, - "optional": true, - "requires": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.0" - } - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true, - "optional": true - }, - "process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true, - "optional": true - }, - "rc": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", - "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", - "dev": true, - "optional": true, - "requires": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true, - "optional": true - } - } - }, - "readable-stream": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "dev": true, - "optional": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "dev": true, - "optional": true, - "requires": { - "glob": "^7.1.3" - } - }, - "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==", - "dev": true, - "optional": true - }, - "safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true, - "optional": true - }, - "sax": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", - "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", - "dev": true, - "optional": true - }, - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "optional": true - }, - "set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", - "dev": true, - "optional": true - }, - "signal-exit": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", - "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", - "dev": true, - "optional": true - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, - "optional": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "optional": true, - "requires": { - "safe-buffer": "~5.1.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "optional": true, - "requires": { - "ansi-regex": "^2.0.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, - "optional": true - }, - "tar": { - "version": "4.4.13", - "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.13.tgz", - "integrity": "sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA==", - "dev": true, - "optional": true, - "requires": { - "chownr": "^1.1.1", - "fs-minipass": "^1.2.5", - "minipass": "^2.8.6", - "minizlib": "^1.2.1", - "mkdirp": "^0.5.0", - "safe-buffer": "^5.1.2", - "yallist": "^3.0.3" - } - }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true, - "optional": true - }, - "wide-align": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", - "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", - "dev": true, - "optional": true, - "requires": { - "string-width": "^1.0.2 || 2" - } - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true, - "optional": true - }, - "yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true, - "optional": true - } - } - }, - "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true - }, - "functional-red-black-tree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", - "dev": true - }, - "get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true - }, - "get-func-name": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", - "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", - "dev": true - }, - "get-own-enumerable-property-symbols": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.0.tgz", - "integrity": "sha512-CIJYJC4GGF06TakLg8z4GQKvDsx9EMspVxOYih7LerEL/WosUnFIww45CGfxfeKHqlg3twgUrYRT1O3WQqjGCg==", - "dev": true - }, - "get-stdin": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-6.0.0.tgz", - "integrity": "sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g==", - "dev": 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" - } - }, - "get-url-origin": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/get-url-origin/-/get-url-origin-1.0.1.tgz", - "integrity": "sha512-MMSKo16gB2+6CjWy55jNdIAqUEaKgw3LzZCb8wVVtFrhoQ78EXyuYXxDdn3COI3A4Xr4ZfM3fZa9RTjO6DOTxw==", - "dev": true - }, - "get-value": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", - "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", - "dev": true - }, - "getpass": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", - "requires": { - "assert-plus": "^1.0.0" - } - }, - "glob": { - "version": "5.0.15", - "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", - "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", - "dev": true, - "requires": { - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "2 || 3", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "glob-parent": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", - "dev": true, - "requires": { - "is-glob": "^3.1.0", - "path-dirname": "^1.0.0" - }, - "dependencies": { - "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true, - "requires": { - "is-extglob": "^2.1.0" - } - } - } - }, - "globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true - }, - "graceful-fs": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz", - "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==", - "dev": true - }, - "growl": { - "version": "1.10.5", - "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", - "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", - "dev": true - }, - "handlebars": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.1.2.tgz", - "integrity": "sha512-nvfrjqvt9xQ8Z/w0ijewdD/vvWDTOweBUm96NTr66Wfvo1mJenBLwcYmPs3TIBP5ruzYGD7Hx/DaM9RmhroGPw==", - "dev": true, - "requires": { - "neo-async": "^2.6.0", - "optimist": "^0.6.1", - "source-map": "^0.6.1", - "uglify-js": "^3.1.4" - }, - "dependencies": { - "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 - } - } - }, - "har-schema": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" - }, - "har-validator": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", - "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", - "requires": { - "ajv": "^6.5.5", - "har-schema": "^2.0.0" - } - }, - "has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "requires": { - "function-bind": "^1.1.1" - } - }, - "has-ansi": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", - "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - } - } - }, - "has-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", - "dev": true - }, - "has-symbols": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz", - "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=", - "dev": true - }, - "has-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", - "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", - "dev": true, - "requires": { - "get-value": "^2.0.6", - "has-values": "^1.0.0", - "isobject": "^3.0.0" - } - }, - "has-values": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", - "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", - "dev": true, - "requires": { - "is-number": "^3.0.0", - "kind-of": "^4.0.0" - }, - "dependencies": { - "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "kind-of": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", - "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", - "dev": true - }, - "hosted-git-info": { - "version": "2.8.4", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.4.tgz", - "integrity": "sha512-pzXIvANXEFrc5oFFXRMkbLPQ2rXRoDERwDLyrcUxGhaZhgP54BBSl9Oheh7Vv0T090cszWBxPjkQQ5Sq1PbBRQ==", - "dev": true - }, - "http-errors": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", - "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", - "requires": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.0", - "statuses": ">= 1.4.0 < 2" - } - }, - "http-signature": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", - "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", - "requires": { - "assert-plus": "^1.0.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" - } - }, - "husky": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/husky/-/husky-1.1.4.tgz", - "integrity": "sha512-cZjGpS7qsaBSo3fOMUuR7erQloX3l5XzL1v/RkIqU6zrQImDdU70z5Re9fGDp7+kbYlM2EtS4aYMlahBeiCUGw==", - "dev": true, - "requires": { - "cosmiconfig": "^5.0.6", - "execa": "^1.0.0", - "find-up": "^3.0.0", - "get-stdin": "^6.0.0", - "is-ci": "^1.2.1", - "pkg-dir": "^3.0.0", - "please-upgrade-node": "^3.1.1", - "read-pkg": "^4.0.1", - "run-node": "^1.0.0", - "slash": "^2.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": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", - "dev": true - }, - "import-fresh": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz", - "integrity": "sha1-2BNVwVYS04bGH53dOSLUMEgipUY=", - "dev": true, - "requires": { - "caller-path": "^2.0.0", - "resolve-from": "^3.0.0" - }, - "dependencies": { - "resolve-from": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", - "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", - "dev": true - } - } - }, - "imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", - "dev": true - }, - "indent-string": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-3.2.0.tgz", - "integrity": "sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok=", - "dev": true - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" - }, - "ini": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", - "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", - "dev": true - }, - "inquirer": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.5.2.tgz", - "integrity": "sha512-cntlB5ghuB0iuO65Ovoi8ogLHiWGs/5yNrtUcKjFhSSiVeAIVpD7koaSU9RM8mpXw5YDi9RdYXGQMaOURB7ycQ==", - "dev": true, - "requires": { - "ansi-escapes": "^3.2.0", - "chalk": "^2.4.2", - "cli-cursor": "^2.1.0", - "cli-width": "^2.0.0", - "external-editor": "^3.0.3", - "figures": "^2.0.0", - "lodash": "^4.17.12", - "mute-stream": "0.0.7", - "run-async": "^2.2.0", - "rxjs": "^6.4.0", - "string-width": "^2.1.0", - "strip-ansi": "^5.1.0", - "through": "^2.3.6" - }, - "dependencies": { - "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 - }, - "figures": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", - "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", - "dev": true, - "requires": { - "escape-string-regexp": "^1.0.5" - } - }, - "lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", - "dev": true - }, - "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" - } - } - } - }, - "invert-kv": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz", - "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==", - "dev": true - }, - "ipaddr.js": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.8.0.tgz", - "integrity": "sha1-6qM9bd16zo9/b+DJygRA5wZzix4=" - }, - "irregular-plurals": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/irregular-plurals/-/irregular-plurals-2.0.0.tgz", - "integrity": "sha512-Y75zBYLkh0lJ9qxeHlMjQ7bSbyiSqNW/UOPWDmzC7cXskL1hekSITh1Oc6JV0XCWWZ9DE8VYSB71xocLk3gmGw==", - "dev": true - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-alphabetical": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-1.0.3.tgz", - "integrity": "sha512-eEMa6MKpHFzw38eKm56iNNi6GJ7lf6aLLio7Kr23sJPAECscgRtZvOBYybejWDQ2bM949Y++61PY+udzj5QMLA==", - "dev": true - }, - "is-alphanumeric": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-alphanumeric/-/is-alphanumeric-1.0.0.tgz", - "integrity": "sha1-Spzvcdr0wAHB2B1j0UDPU/1oifQ=", - "dev": true - }, - "is-alphanumerical": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-1.0.3.tgz", - "integrity": "sha512-A1IGAPO5AW9vSh7omxIlOGwIqEvpW/TA+DksVOPM5ODuxKlZS09+TEM1E3275lJqO2oJ38vDpeAL3DCIiHE6eA==", - "dev": true, - "requires": { - "is-alphabetical": "^1.0.0", - "is-decimal": "^1.0.0" - } - }, - "is-arguments": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.0.4.tgz", - "integrity": "sha512-xPh0Rmt8NE65sNzvyUmWgI1tz3mKq74lGA0mL8LYZcoIzKOzDh6HmrYm3d18k60nHerC8A9Km8kYu87zfSFnLA==", - "dev": true - }, - "is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", - "dev": true - }, - "is-binary-path": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", - "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", - "dev": true, - "requires": { - "binary-extensions": "^1.0.0" - } - }, - "is-buffer": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.3.tgz", - "integrity": "sha512-U15Q7MXTuZlrbymiz95PJpZxu8IlipAp4dtS3wOdgPXx3mqBnslrWU14kxfHB+Py/+2PVKSr37dMAgM2A4uArw==", - "dev": true - }, - "is-callable": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz", - "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==", - "dev": true - }, - "is-ci": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-1.2.1.tgz", - "integrity": "sha512-s6tfsaQaQi3JNciBH6shVqEDvhGut0SUXr31ag8Pd8BBbVVlcGfWhpPmEOoM6RJ5TFhbypvf5yyRw/VXW1IiWg==", - "dev": true, - "requires": { - "ci-info": "^1.5.0" - } - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-date-object": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", - "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=", - "dev": true - }, - "is-decimal": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-1.0.3.tgz", - "integrity": "sha512-bvLSwoDg2q6Gf+E2LEPiklHZxxiSi3XAh4Mav65mKqTfCO1HM3uBs24TjEH8iJX3bbDdLXKJXBTmGzuTUuAEjQ==", - "dev": true - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - }, - "dependencies": { - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true - } - } - }, - "is-directory": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz", - "integrity": "sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE=", - "dev": true - }, - "is-empty": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/is-empty/-/is-empty-1.2.0.tgz", - "integrity": "sha1-3pu1snhzigWgsJpX4ftNSjQan2s=", - "dev": true - }, - "is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true - }, - "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-file": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-file/-/is-file-1.0.0.tgz", - "integrity": "sha1-KKRM+9nT2xkwRfIrZfzo7fliBZY=", - "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-hexadecimal": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-1.0.3.tgz", - "integrity": "sha512-zxQ9//Q3D/34poZf8fiy3m3XVpbQc7ren15iKqrTtLPwkPD/t3Scy9Imp63FujULGxuK0ZlCwoo5xNpktFgbOA==", - "dev": true - }, - "is-hidden": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-hidden/-/is-hidden-1.1.2.tgz", - "integrity": "sha512-kytBeNVW2QTIqZdJBDKIjP+EkUTzDT07rsc111w/gxqR6wK3ODkOswcpxgED6HU6t7fEhOxqojVZ2a2kU9rj+A==", - "dev": true - }, - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", - "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=", - "dev": true - }, - "is-object": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.1.tgz", - "integrity": "sha1-iVJojF7C/9awPsyF52ngKQMINHA=", - "dev": true - }, - "is-observable": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-observable/-/is-observable-1.1.0.tgz", - "integrity": "sha512-NqCa4Sa2d+u7BWc6CukaObG3Fh+CU9bvixbpcXYhy2VvYS7vVGIdAgnIS5Ks3A/cqk4rebLJ9s8zBstT2aKnIA==", - "dev": true, - "requires": { - "symbol-observable": "^1.1.0" - } - }, - "is-plain-obj": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", - "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=", - "dev": true - }, - "is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "requires": { - "isobject": "^3.0.1" - } - }, - "is-promise": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", - "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", - "dev": true - }, - "is-regex": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", - "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", - "dev": true, - "requires": { - "has": "^1.0.1" - } - }, - "is-regexp": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz", - "integrity": "sha1-/S2INUXEa6xaYz57mgnof6LLUGk=", - "dev": true - }, - "is-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", - "dev": true - }, - "is-symbol": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz", - "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==", - "dev": true, - "requires": { - "has-symbols": "^1.0.0" - } - }, - "is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" - }, - "is-utf8": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", - "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", - "dev": true - }, - "is-whitespace-character": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-whitespace-character/-/is-whitespace-character-1.0.3.tgz", - "integrity": "sha512-SNPgMLz9JzPccD3nPctcj8sZlX9DAMJSKH8bP7Z6bohCwuNgX8xbWr1eTAYXX9Vpi/aSn8Y1akL9WgM3t43YNQ==", - "dev": true - }, - "is-windows": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", - "dev": true - }, - "is-word-character": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-word-character/-/is-word-character-1.0.3.tgz", - "integrity": "sha512-0wfcrFgOOOBdgRNT9H33xe6Zi6yhX/uoc4U8NBZGeQQB0ctU1dnlNTyL9JM2646bHDTpsDm1Brb3VPoCIMrd/A==", - "dev": true - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - }, - "isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" - }, - "istanbul": { - "version": "0.4.5", - "resolved": "https://registry.npmjs.org/istanbul/-/istanbul-0.4.5.tgz", - "integrity": "sha1-ZcfXPUxNqE1POsMQuRj7C4Azczs=", - "dev": true, - "requires": { - "abbrev": "1.0.x", - "async": "1.x", - "escodegen": "1.8.x", - "esprima": "2.7.x", - "glob": "^5.0.15", - "handlebars": "^4.0.1", - "js-yaml": "3.x", - "mkdirp": "0.5.x", - "nopt": "3.x", - "once": "1.x", - "resolve": "1.1.x", - "supports-color": "^3.1.0", - "which": "^1.1.1", - "wordwrap": "^1.0.0" - }, - "dependencies": { - "async": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", - "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", - "dev": true - }, - "escodegen": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.8.1.tgz", - "integrity": "sha1-WltTr0aTEQvrsIZ6o0MN07cKEBg=", - "dev": true, - "requires": { - "esprima": "^2.7.1", - "estraverse": "^1.9.1", - "esutils": "^2.0.2", - "optionator": "^0.8.1", - "source-map": "~0.2.0" - } - }, - "esprima": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", - "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", - "dev": true - }, - "estraverse": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.3.tgz", - "integrity": "sha1-r2fy3JIlgkFZUJJgkaQAXSnJu0Q=", - "dev": true - }, - "esutils": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", - "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", - "dev": true - }, - "source-map": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz", - "integrity": "sha1-2rc/vPwrqBm03gO9b26qSBZLP50=", - "dev": true, - "optional": true, - "requires": { - "amdefine": ">=0.0.4" - } - } - } - }, - "jest-get-type": { - "version": "22.4.3", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-22.4.3.tgz", - "integrity": "sha512-/jsz0Y+V29w1chdXVygEKSz2nBoHoYqNShPe+QgxSNjAuP1i8+k4LbQNrfoliKej0P45sivkSCh7yiD6ubHS3w==", - "dev": true - }, - "jest-validate": { - "version": "23.6.0", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-23.6.0.tgz", - "integrity": "sha512-OFKapYxe72yz7agrDAWi8v2WL8GIfVqcbKRCLbRG9PAxtzF9b1SEDdTpytNDN12z2fJynoBwpMpvj2R39plI2A==", - "dev": true, - "requires": { - "chalk": "^2.0.1", - "jest-get-type": "^22.1.0", - "leven": "^2.1.0", - "pretty-format": "^23.6.0" - } - }, - "jison": { - "version": "0.4.18", - "resolved": "https://registry.npmjs.org/jison/-/jison-0.4.18.tgz", - "integrity": "sha512-FKkCiJvozgC7VTHhMJ00a0/IApSxhlGsFIshLW6trWJ8ONX2TQJBBz6DlcO1Gffy4w9LT+uL+PA+CVnUSJMF7w==", - "requires": { - "JSONSelect": "0.4.0", - "cjson": "0.3.0", - "ebnf-parser": "0.1.10", - "escodegen": "1.3.x", - "esprima": "1.1.x", - "jison-lex": "0.3.x", - "lex-parser": "~0.1.3", - "nomnom": "1.5.2" - } - }, - "jison-lex": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/jison-lex/-/jison-lex-0.3.4.tgz", - "integrity": "sha1-gcoo2E+ESZ36jFlNzePYo/Jux6U=", - "requires": { - "lex-parser": "0.1.x", - "nomnom": "1.5.2" - } - }, - "js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, - "js-yaml": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", - "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", - "dev": true, - "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "dependencies": { - "esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true - } - } - }, - "jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" - }, - "json-parse-better-errors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", - "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", - "dev": true - }, - "json-schema": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", - "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" - }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" - }, - "json-stable-stringify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", - "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", - "dev": true, - "requires": { - "jsonify": "~0.0.0" - } - }, - "json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", - "dev": true - }, - "json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" - }, - "json5": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", - "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", - "dev": true, - "requires": { - "minimist": "^1.2.0" - } - }, - "jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.6" - } - }, - "jsonify": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", - "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", - "dev": true - }, - "jsonlint": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/jsonlint/-/jsonlint-1.6.0.tgz", - "integrity": "sha1-iKpGvCiaesk7tGyuLVihh6m7SUo=", - "requires": { - "JSV": ">= 4.0.x", - "nomnom": ">= 1.5.x" - } - }, - "jsprim": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", - "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", - "requires": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.2.3", - "verror": "1.10.0" - } - }, - "kareem": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/kareem/-/kareem-2.3.1.tgz", - "integrity": "sha512-l3hLhffs9zqoDe8zjmb/mAN4B8VT3L56EUvKNqLFVs9YlFA+zx7ke1DO8STAdDyYNkeSo1nKmjuvQeI12So8Xw==" - }, - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", - "dev": true - }, - "lcid": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz", - "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==", - "dev": true, - "requires": { - "invert-kv": "^2.0.0" - } - }, - "lcov-parse": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/lcov-parse/-/lcov-parse-0.0.10.tgz", - "integrity": "sha1-GwuP+ayceIklBYK3C3ExXZ2m2aM=", - "dev": true - }, - "leven": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz", - "integrity": "sha1-wuep93IJTe6dNCAq6KzORoeHVYA=", - "dev": true - }, - "levn": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", - "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", - "dev": true, - "requires": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" - } - }, - "lex-parser": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/lex-parser/-/lex-parser-0.1.4.tgz", - "integrity": "sha1-ZMTwJfF/1Tv7RXY/rrFvAVp0dVA=" - }, - "lint-staged": { - "version": "7.3.0", - "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-7.3.0.tgz", - "integrity": "sha512-AXk40M9DAiPi7f4tdJggwuKIViUplYtVj1os1MVEteW7qOkU50EOehayCfO9TsoGK24o/EsWb41yrEgfJDDjCw==", - "dev": true, - "requires": { - "chalk": "^2.3.1", - "commander": "^2.14.1", - "cosmiconfig": "^5.0.2", - "debug": "^3.1.0", - "dedent": "^0.7.0", - "execa": "^0.9.0", - "find-parent-dir": "^0.3.0", - "is-glob": "^4.0.0", - "is-windows": "^1.0.2", - "jest-validate": "^23.5.0", - "listr": "^0.14.1", - "lodash": "^4.17.5", - "log-symbols": "^2.2.0", - "micromatch": "^3.1.8", - "npm-which": "^3.0.1", - "p-map": "^1.1.1", - "path-is-inside": "^1.0.2", - "pify": "^3.0.0", - "please-upgrade-node": "^3.0.2", - "staged-git-files": "1.1.1", - "string-argv": "^0.0.2", - "stringify-object": "^3.2.2" - }, - "dependencies": { - "cross-spawn": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", - "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", - "dev": true, - "requires": { - "lru-cache": "^4.0.1", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - } - }, - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "execa": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-0.9.0.tgz", - "integrity": "sha512-BbUMBiX4hqiHZUA5+JujIjNb6TyAlp2D5KLheMjMluwOuzcnylDL4AxZYLLn1n2AGB49eSWwyKvvEQoRpnAtmA==", - "dev": true, - "requires": { - "cross-spawn": "^5.0.1", - "get-stream": "^3.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" - } - }, - "get-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", - "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", - "dev": true - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - } - } - }, - "listr": { - "version": "0.14.3", - "resolved": "https://registry.npmjs.org/listr/-/listr-0.14.3.tgz", - "integrity": "sha512-RmAl7su35BFd/xoMamRjpIE4j3v+L28o8CT5YhAXQJm1fD+1l9ngXY8JAQRJ+tFK2i5njvi0iRUKV09vPwA0iA==", - "dev": true, - "requires": { - "@samverschueren/stream-to-observable": "^0.3.0", - "is-observable": "^1.1.0", - "is-promise": "^2.1.0", - "is-stream": "^1.1.0", - "listr-silent-renderer": "^1.1.1", - "listr-update-renderer": "^0.5.0", - "listr-verbose-renderer": "^0.5.0", - "p-map": "^2.0.0", - "rxjs": "^6.3.3" - }, - "dependencies": { - "p-map": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", - "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", - "dev": true - } - } - }, - "listr-silent-renderer": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/listr-silent-renderer/-/listr-silent-renderer-1.1.1.tgz", - "integrity": "sha1-kktaN1cVN3C/Go4/v3S4u/P5JC4=", - "dev": true - }, - "listr-update-renderer": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/listr-update-renderer/-/listr-update-renderer-0.5.0.tgz", - "integrity": "sha512-tKRsZpKz8GSGqoI/+caPmfrypiaq+OQCbd+CovEC24uk1h952lVj5sC7SqyFUm+OaJ5HN/a1YLt5cit2FMNsFA==", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "cli-truncate": "^0.2.1", - "elegant-spinner": "^1.0.1", - "figures": "^1.7.0", - "indent-string": "^3.0.0", - "log-symbols": "^1.0.2", - "log-update": "^2.3.0", - "strip-ansi": "^3.0.1" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - }, - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - } - }, - "log-symbols": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-1.0.2.tgz", - "integrity": "sha1-N2/3tY6jCGoPCfrMdGF+ylAeGhg=", - "dev": true, - "requires": { - "chalk": "^1.0.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - } - } - }, - "listr-verbose-renderer": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/listr-verbose-renderer/-/listr-verbose-renderer-0.5.0.tgz", - "integrity": "sha512-04PDPqSlsqIOaaaGZ+41vq5FejI9auqTInicFRndCBgE3bXG8D6W1I+mWhk+1nqbHmyhla/6BUrd5OSiHwKRXw==", - "dev": true, - "requires": { - "chalk": "^2.4.1", - "cli-cursor": "^2.1.0", - "date-fns": "^1.27.2", - "figures": "^2.0.0" - }, - "dependencies": { - "figures": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", - "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", - "dev": true, - "requires": { - "escape-string-regexp": "^1.0.5" - } - } - } - }, - "load-json-file": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", - "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0", - "strip-bom": "^2.0.0" - }, - "dependencies": { - "parse-json": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", - "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "dev": true, - "requires": { - "error-ex": "^1.2.0" - } - }, - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - } - } - }, - "load-plugin": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/load-plugin/-/load-plugin-2.3.1.tgz", - "integrity": "sha512-dYB1lbwqHgPTrruy9glukCu8Ya9vzj6TMfouCtj2H/GuJ+8syioisgKTBPxnCi6m8K8jINKfTOxOHngFkUYqHw==", - "dev": true, - "requires": { - "npm-prefix": "^1.2.0", - "resolve-from": "^5.0.0" - }, - "dependencies": { - "resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true - } - } - }, - "locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, - "requires": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - } - }, - "lodash": { - "version": "4.17.11", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", - "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==" - }, - "log-driver": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/log-driver/-/log-driver-1.2.7.tgz", - "integrity": "sha512-U7KCmLdqsGHBLeWqYlFA0V0Sl6P08EE1ZrmA9cxjUE0WVqT9qnyVDPz1kzpFEP0jdJuFnasWIfSd7fsaNXkpbg==", - "dev": true - }, - "log-symbols": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", - "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", - "dev": true, - "requires": { - "chalk": "^2.0.1" - } - }, - "log-update": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/log-update/-/log-update-2.3.0.tgz", - "integrity": "sha1-iDKP19HOeTiykoN0bwsbwSayRwg=", - "dev": true, - "requires": { - "ansi-escapes": "^3.0.0", - "cli-cursor": "^2.0.0", - "wrap-ansi": "^3.0.1" - }, - "dependencies": { - "wrap-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-3.0.1.tgz", - "integrity": "sha1-KIoE2H7aXChuBg3+jxNc6NAH+Lo=", - "dev": true, - "requires": { - "string-width": "^2.1.1", - "strip-ansi": "^4.0.0" - } - } - } - }, - "logops": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/logops/-/logops-2.1.0.tgz", - "integrity": "sha1-mHIkVNeHG9KqR2j7QWZvFCuVNc8=", - "requires": { - "colors": "^1.1.2", - "lodash": "^4.1.0", - "safe-json-stringify": "^1.0.4", - "serr": "^1.0.0" - }, - "dependencies": { - "colors": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.3.3.tgz", - "integrity": "sha512-mmGt/1pZqYRjMxB1axhTo16/snVZ5krrKkcmMeVKxzECMMXoCgnvTPp10QgHfcbQZw8Dq2jMNG6je4JlWU0gWg==" - } - } - }, - "longest-streak": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-2.0.3.tgz", - "integrity": "sha512-9lz5IVdpwsKLMzQi0MQ+oD9EA0mIGcWYP7jXMTZVXP8D42PwuAk+M/HBFYQoxt1G5OR8m7aSIgb1UymfWGBWEw==", - "dev": true - }, - "lru-cache": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", - "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", - "dev": true, - "requires": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" - } - }, - "map-age-cleaner": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz", - "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==", - "dev": true, - "requires": { - "p-defer": "^1.0.0" - } - }, - "map-cache": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", - "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", - "dev": true - }, - "map-like": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/map-like/-/map-like-2.0.0.tgz", - "integrity": "sha1-lEltSa0zPA3DI0snrbvR6FNZU7Q=", - "dev": true - }, - "map-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", - "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", - "dev": true, - "requires": { - "object-visit": "^1.0.0" - } - }, - "markdown-escapes": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/markdown-escapes/-/markdown-escapes-1.0.3.tgz", - "integrity": "sha512-XUi5HJhhV5R74k8/0H2oCbCiYf/u4cO/rX8tnGkRvrqhsr5BRNU6Mg0yt/8UIx1iIS8220BNJsDb7XnILhLepw==", - "dev": true - }, - "markdown-extensions": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/markdown-extensions/-/markdown-extensions-1.1.1.tgz", - "integrity": "sha512-WWC0ZuMzCyDHYCasEGs4IPvLyTGftYwh6wIEOULOF0HXcqZlhwRzrK0w2VUlxWA98xnvb/jszw4ZSkJ6ADpM6Q==", - "dev": true - }, - "markdown-table": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-1.1.3.tgz", - "integrity": "sha512-1RUZVgQlpJSPWYbFSpmudq5nHY1doEIv89gBtF0s4gW1GF2XorxcA/70M5vq7rLv0a6mhOUccRsqkwhwLCIQ2Q==", - "dev": true - }, - "md5": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/md5/-/md5-2.2.1.tgz", - "integrity": "sha1-U6s41f48iJG6RlMp6iP6wFQBJvk=", - "dev": true, - "requires": { - "charenc": "~0.0.1", - "crypt": "~0.0.1", - "is-buffer": "~1.1.1" - }, - "dependencies": { - "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - } - } - }, - "mdast-comment-marker": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/mdast-comment-marker/-/mdast-comment-marker-1.1.1.tgz", - "integrity": "sha512-TWZDaUtPLwKX1pzDIY48MkSUQRDwX/HqbTB4m3iYdL/zosi/Z6Xqfdv0C0hNVKvzrPjZENrpWDt4p4odeVO0Iw==", - "dev": true - }, - "mdast-util-compact": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mdast-util-compact/-/mdast-util-compact-1.0.4.tgz", - "integrity": "sha512-3YDMQHI5vRiS2uygEFYaqckibpJtKq5Sj2c8JioeOQBU6INpKbdWzfyLqFFnDwEcEnRFIdMsguzs5pC1Jp4Isg==", - "dev": true, - "requires": { - "unist-util-visit": "^1.1.0" - } - }, - "mdast-util-heading-style": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/mdast-util-heading-style/-/mdast-util-heading-style-1.0.5.tgz", - "integrity": "sha512-8zQkb3IUwiwOdUw6jIhnwM6DPyib+mgzQuHAe7j2Hy1rIarU4VUxe472bp9oktqULW3xqZE+Kz6OD4Gi7IA3vw==", - "dev": true - }, - "mdast-util-to-string": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-1.0.7.tgz", - "integrity": "sha512-P+gdtssCoHOX+eJUrrC30Sixqao86ZPlVjR5NEAoy0U79Pfxb1Y0Gntei0+GrnQD4T04X9xA8tcugp90cSmNow==", - "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=" - }, - "mem": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/mem/-/mem-4.3.0.tgz", - "integrity": "sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==", - "dev": true, - "requires": { - "map-age-cleaner": "^0.1.1", - "mimic-fn": "^2.0.0", - "p-is-promise": "^2.0.0" - } - }, - "memory-pager": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz", - "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==", - "optional": true - }, - "merge": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/merge/-/merge-1.2.1.tgz", - "integrity": "sha512-VjFo4P5Whtj4vsLzsYBu5ayHhoHJ0UqNm7ibvShmbmoz7tGi0vXaoJbGdB+GmDMLUdg8DpQXEIeVDAe8MaABvQ==", - "dev": true - }, - "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=" - }, - "micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dev": true, - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - } - }, - "mime": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz", - "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==" - }, - "mime-db": { - "version": "1.37.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.37.0.tgz", - "integrity": "sha512-R3C4db6bgQhlIhPU48fUtdVmKnflq+hRdad7IyKhtFj06VPNVdk2RhiYL3UjQIlso8L+YxAtFkobT0VK+S/ybg==" - }, - "mime-types": { - "version": "2.1.21", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.21.tgz", - "integrity": "sha512-3iL6DbwpyLzjR3xHSFNFeb9Nz/M8WDkX33t1GFQnFOllWk8pOrh/LSrB5OXlnlW5P9LH73X6loW/eogc+F5lJg==", - "requires": { - "mime-db": "~1.37.0" - } - }, - "mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "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.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - }, - "misspellings": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/misspellings/-/misspellings-1.1.0.tgz", - "integrity": "sha1-U9UAJmy9Cc2p2UxM85LmBYm1syQ=", - "dev": true - }, - "mixin-deep": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", - "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", - "dev": true, - "requires": { - "for-in": "^1.0.2", - "is-extendable": "^1.0.1" - }, - "dependencies": { - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4" - } - } - } - }, - "mkdirp": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", - "dev": true, - "requires": { - "minimist": "0.0.8" - }, - "dependencies": { - "minimist": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", - "dev": true - } - } - }, - "mocha": { - "version": "6.1.4", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-6.1.4.tgz", - "integrity": "sha512-PN8CIy4RXsIoxoFJzS4QNnCH4psUCPWc4/rPrst/ecSJJbLBkubMiyGCP2Kj/9YnWbotFqAoeXyXMucj7gwCFg==", - "dev": true, - "requires": { - "ansi-colors": "3.2.3", - "browser-stdout": "1.3.1", - "debug": "3.2.6", - "diff": "3.5.0", - "escape-string-regexp": "1.0.5", - "find-up": "3.0.0", - "glob": "7.1.3", - "growl": "1.10.5", - "he": "1.2.0", - "js-yaml": "3.13.1", - "log-symbols": "2.2.0", - "minimatch": "3.0.4", - "mkdirp": "0.5.1", - "ms": "2.1.1", - "node-environment-flags": "1.0.5", - "object.assign": "4.1.0", - "strip-json-comments": "2.0.1", - "supports-color": "6.0.0", - "which": "1.3.1", - "wide-align": "1.1.3", - "yargs": "13.2.2", - "yargs-parser": "13.0.0", - "yargs-unparser": "1.5.0" - }, - "dependencies": { - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "glob": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", - "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "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==", - "dev": true - }, - "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": "6.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.0.0.tgz", - "integrity": "sha512-on9Kwidc1IUQo+bQdhi8+Tijpo0e1SS6RoGo2guUwn5vdaxw8RXOF9Vb2ws+ihWOmh4JnCJOvaziZWP1VABaLg==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "moment": { - "version": "2.24.0", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.24.0.tgz", - "integrity": "sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg==" - }, - "moment-timezone": { - "version": "0.5.25", - "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.25.tgz", - "integrity": "sha512-DgEaTyN/z0HFaVcVbSyVCUU6HeFdnNC3vE4c9cgu2dgMTvjBUBdBzWfasTBmAW45u5OIMeCJtU8yNjM22DHucw==", - "requires": { - "moment": ">= 2.9.0" - } - }, - "mongodb": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.2.3.tgz", - "integrity": "sha512-jw8UyPsq4QleZ9z+t/pIVy3L++51vKdaJ2Q/XXeYxk/3cnKioAH8H6f5tkkDivrQL4PUgUOHe9uZzkpRFH1XtQ==", - "requires": { - "mongodb-core": "^3.2.3", - "safe-buffer": "^5.1.2" - } - }, - "mongodb-core": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/mongodb-core/-/mongodb-core-3.2.3.tgz", - "integrity": "sha512-UyI0rmvPPkjOJV8XGWa9VCTq7R4hBVipimhnAXeSXnuAPjuTqbyfA5Ec9RcYJ1Hhu+ISnc8bJ1KfGZd4ZkYARQ==", - "requires": { - "bson": "^1.1.1", - "require_optional": "^1.0.1", - "safe-buffer": "^5.1.2", - "saslprep": "^1.0.0" - } - }, - "mongoose": { - "version": "5.7.5", - "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-5.7.5.tgz", - "integrity": "sha512-BZ4FxtnbTurc/wcm/hLltLdI4IDxo4nsE0D9q58YymTdZwreNzwO62CcjVtaHhmr8HmJtOInp2W/T12FZaMf8g==", - "requires": { - "bson": "~1.1.1", - "kareem": "2.3.1", - "mongodb": "3.3.2", - "mongoose-legacy-pluralize": "1.0.2", - "mpath": "0.6.0", - "mquery": "3.2.2", - "ms": "2.1.2", - "regexp-clone": "1.0.0", - "safe-buffer": "5.1.2", - "sift": "7.0.1", - "sliced": "1.0.1" - }, - "dependencies": { - "mongodb": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.3.2.tgz", - "integrity": "sha512-fqJt3iywelk4yKu/lfwQg163Bjpo5zDKhXiohycvon4iQHbrfflSAz9AIlRE6496Pm/dQKQK5bMigdVo2s6gBg==", - "requires": { - "bson": "^1.1.1", - "require_optional": "^1.0.1", - "safe-buffer": "^5.1.2" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - } - } - }, - "mongoose-legacy-pluralize": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/mongoose-legacy-pluralize/-/mongoose-legacy-pluralize-1.0.2.tgz", - "integrity": "sha512-Yo/7qQU4/EyIS8YDFSeenIvXxZN+ld7YdV9LqFVQJzTLye8unujAWPZ4NWKfFA+RNjh+wvTWKY9Z3E5XM6ZZiQ==" - }, - "mpath": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.6.0.tgz", - "integrity": "sha512-i75qh79MJ5Xo/sbhxrDrPSEG0H/mr1kcZXJ8dH6URU5jD/knFxCVqVC/gVSW7GIXL/9hHWlT9haLbCXWOll3qw==" - }, - "mquery": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/mquery/-/mquery-3.2.2.tgz", - "integrity": "sha512-XB52992COp0KP230I3qloVUbkLUxJIu328HBP2t2EsxSFtf4W1HPSOBWOXf1bqxK4Xbb66lfMJ+Bpfd9/yZE1Q==", - "requires": { - "bluebird": "3.5.1", - "debug": "3.1.0", - "regexp-clone": "^1.0.0", - "safe-buffer": "5.1.2", - "sliced": "1.0.1" - }, - "dependencies": { - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "requires": { - "ms": "2.0.0" - } - } - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - }, - "mu2": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/mu2/-/mu2-0.5.21.tgz", - "integrity": "sha1-iIqPD9kOsc/anbgUdvbhmcyeWNM=" - }, - "mute-stream": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", - "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", - "dev": true - }, - "nan": { - "version": "2.14.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz", - "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==", - "dev": true, - "optional": true - }, - "nanomatch": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", - "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", - "dev": true, - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "fragment-cache": "^0.2.1", - "is-windows": "^1.0.2", - "kind-of": "^6.0.2", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - } - }, - "natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", - "dev": true - }, - "negotiator": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", - "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=" - }, - "neo-async": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.0.tgz", - "integrity": "sha512-MFh0d/Wa7vkKO3Y3LlacqAEeHK0mckVqzDieUKTT+KGxi+zIpeVsFxymkIiRpbpDziHc290Xr9A1O4Om7otoRA==", - "dev": true - }, - "nice-try": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", - "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", - "dev": true - }, - "no-cliches": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/no-cliches/-/no-cliches-0.1.1.tgz", - "integrity": "sha512-mYihjs47X5+N71CN3P+QBrEIBuclIfMMpgWEpkmLqFPvrOXdzokvDlhbLfjdBNZOqYgniaeZC6J1ZCgxFdyvXw==", - "dev": true - }, - "nock": { - "version": "10.0.6", - "resolved": "https://registry.npmjs.org/nock/-/nock-10.0.6.tgz", - "integrity": "sha512-b47OWj1qf/LqSQYnmokNWM8D88KvUl2y7jT0567NB3ZBAZFz2bWp2PC81Xn7u8F2/vJxzkzNZybnemeFa7AZ2w==", - "dev": true, - "requires": { - "chai": "^4.1.2", - "debug": "^4.1.0", - "deep-equal": "^1.0.0", - "json-stringify-safe": "^5.0.1", - "lodash": "^4.17.5", - "mkdirp": "^0.5.0", - "propagate": "^1.0.0", - "qs": "^6.5.1", - "semver": "^5.5.0" - }, - "dependencies": { - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "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==", - "dev": true - } - } - }, - "node-environment-flags": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/node-environment-flags/-/node-environment-flags-1.0.5.tgz", - "integrity": "sha512-VNYPRfGfmZLx0Ye20jWzHUjyTW/c+6Wq+iLhDzUI4XmhrDd9l/FozXV3F2xOaXjvp0co0+v1YSR3CMP6g+VvLQ==", - "dev": true, - "requires": { - "object.getownpropertydescriptors": "^2.0.3", - "semver": "^5.7.0" - } - }, - "node-fetch": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.0.tgz", - "integrity": "sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA==", - "dev": true - }, - "nomnom": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/nomnom/-/nomnom-1.5.2.tgz", - "integrity": "sha1-9DRUSKhTz71cDSYyDyR3qwUm/i8=", - "requires": { - "colors": "0.5.x", - "underscore": "1.1.x" - }, - "dependencies": { - "underscore": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.1.7.tgz", - "integrity": "sha1-QLq4S60Z0jAJbo1u9ii/8FXYPbA=" - } - } - }, - "nopt": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", - "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", - "dev": true, - "requires": { - "abbrev": "1" - } - }, - "normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "dev": true, - "requires": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - }, - "dependencies": { - "resolve": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.12.0.tgz", - "integrity": "sha512-B/dOmuoAik5bKcD6s6nXDCjzUKnaDvdkRyAk6rsmsKLipWj4797iothd7jmmUhWTfinVMU+wc56rYKsit2Qy4w==", - "dev": true, - "requires": { - "path-parse": "^1.0.6" - } - } - } - }, - "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 - }, - "npm-path": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/npm-path/-/npm-path-2.0.4.tgz", - "integrity": "sha512-IFsj0R9C7ZdR5cP+ET342q77uSRdtWOlWpih5eC+lu29tIDbNEgDbzgVJ5UFvYHWhxDZ5TFkJafFioO0pPQjCw==", - "dev": true, - "requires": { - "which": "^1.2.10" - } - }, - "npm-prefix": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/npm-prefix/-/npm-prefix-1.2.0.tgz", - "integrity": "sha1-5hlFX3B0ulTMZtbQ033Z8b5ry8A=", - "dev": true, - "requires": { - "rc": "^1.1.0", - "shellsubstitute": "^1.1.0", - "untildify": "^2.1.0" - } - }, - "npm-run-path": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", - "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", - "dev": true, - "requires": { - "path-key": "^2.0.0" - } - }, - "npm-which": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/npm-which/-/npm-which-3.0.1.tgz", - "integrity": "sha1-kiXybsOihcIJyuZ8OxGmtKtxQKo=", - "dev": true, - "requires": { - "commander": "^2.9.0", - "npm-path": "^2.0.2", - "which": "^1.2.10" - } - }, - "number-is-nan": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", - "dev": true - }, - "oauth-sign": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", - "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" - }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "dev": true - }, - "object-copy": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", - "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", - "dev": true, - "requires": { - "copy-descriptor": "^0.1.0", - "define-property": "^0.2.5", - "kind-of": "^3.0.3" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "object-inspect": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.7.0.tgz", - "integrity": "sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw==", - "dev": true - }, - "object-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.0.2.tgz", - "integrity": "sha512-Epah+btZd5wrrfjkJZq1AOB9O6OxUQto45hzFd7lXGrpHPGE0W1k+426yrZV+k6NJOzLNNW/nVsmZdIWsAqoOQ==", - "dev": true - }, - "object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true - }, - "object-visit": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", - "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", - "dev": true, - "requires": { - "isobject": "^3.0.0" - } - }, - "object.assign": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", - "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", - "dev": true, - "requires": { - "define-properties": "^1.1.2", - "function-bind": "^1.1.1", - "has-symbols": "^1.0.0", - "object-keys": "^1.0.11" - } - }, - "object.getownpropertydescriptors": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz", - "integrity": "sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY=", - "dev": true, - "requires": { - "define-properties": "^1.1.2", - "es-abstract": "^1.5.1" - } - }, - "object.pick": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", - "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", - "dev": true, - "requires": { - "isobject": "^3.0.1" - } - }, - "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" - } - }, - "onetime": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", - "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", - "dev": true, - "requires": { - "mimic-fn": "^1.0.0" - }, - "dependencies": { - "mimic-fn": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", - "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", - "dev": true - } - } - }, - "optimist": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", - "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", - "dev": true, - "requires": { - "minimist": "~0.0.1", - "wordwrap": "~0.0.2" - }, - "dependencies": { - "minimist": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", - "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=", - "dev": true - }, - "wordwrap": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", - "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", - "dev": true - } - } - }, - "optionator": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", - "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", - "dev": true, - "requires": { - "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.4", - "levn": "~0.3.0", - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2", - "wordwrap": "~1.0.0" - } - }, - "os-homedir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", - "dev": true - }, - "os-locale": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz", - "integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==", - "dev": true, - "requires": { - "execa": "^1.0.0", - "lcid": "^2.0.0", - "mem": "^4.0.0" - } - }, - "os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", - "dev": true - }, - "p-defer": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz", - "integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=", - "dev": true - }, - "p-finally": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", - "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", - "dev": true - }, - "p-is-promise": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-2.1.0.tgz", - "integrity": "sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg==", - "dev": true - }, - "p-limit": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.0.tgz", - "integrity": "sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==", - "dev": true, - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, - "requires": { - "p-limit": "^2.0.0" - } - }, - "p-map": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-1.2.0.tgz", - "integrity": "sha512-r6zKACMNhjPJMTl8KcFH4li//gkrXWfbD6feV8l6doRHlzljFWGJ2AP6iKaCJXyZmAUMOPtvbW7EXkbWO/pLEA==", - "dev": true - }, - "p-memoize": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-memoize/-/p-memoize-3.1.0.tgz", - "integrity": "sha512-e5tIvrsr7ydUUnxb534iQWtXxWgk/86IsH+H+nV4FHouIggBt4coXboKBt26o4lTu7JbEnGSeXdEsYR8BhAHFA==", - "dev": true, - "requires": { - "mem": "^4.3.0", - "mimic-fn": "^2.1.0" - } - }, - "p-queue": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-6.2.1.tgz", - "integrity": "sha512-wV8yC/rkuWpgu9LGKJIb48OynYSrE6lVl2Bx6r8WjbyVKrFAzzQ/QevAvwnDjlD+mLt8xy0LTDOU1freOvMTCg==", - "dev": true, - "requires": { - "eventemitter3": "^4.0.0", - "p-timeout": "^3.1.0" - } - }, - "p-timeout": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-3.2.0.tgz", - "integrity": "sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==", - "dev": true, - "requires": { - "p-finally": "^1.0.0" - } - }, - "p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true - }, - "parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "requires": { - "callsites": "^3.0.0" - }, - "dependencies": { - "callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true - } - } - }, - "parse-entities": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-1.2.2.tgz", - "integrity": "sha512-NzfpbxW/NPrzZ/yYSoQxyqUZMZXIdCfE0OIN4ESsnptHJECoUk3FZktxNuzQf4tjt5UEopnxpYJbvYuxIFDdsg==", - "dev": true, - "requires": { - "character-entities": "^1.0.0", - "character-entities-legacy": "^1.0.0", - "character-reference-invalid": "^1.0.0", - "is-alphanumerical": "^1.0.0", - "is-decimal": "^1.0.0", - "is-hexadecimal": "^1.0.0" - } - }, - "parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", - "dev": true, - "requires": { - "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1" - } - }, - "parseurl": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", - "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=" - }, - "pascalcase": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", - "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", - "dev": true - }, - "passive-voice": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/passive-voice/-/passive-voice-0.1.0.tgz", - "integrity": "sha1-Fv+RrkC6DpLEPmcXY/3IQqcCcLE=", - "dev": true - }, - "path-dirname": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", - "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", - "dev": true - }, - "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", - "dev": true - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true - }, - "path-is-inside": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", - "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", - "dev": true - }, - "path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", - "dev": true - }, - "path-parse": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", - "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", - "dev": true - }, - "path-to-glob-pattern": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-to-glob-pattern/-/path-to-glob-pattern-1.0.2.tgz", - "integrity": "sha1-Rz5qOikqnRP7rj7czuctO6uoxhk=", - "dev": true - }, - "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=" - }, - "path-type": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", - "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" - }, - "dependencies": { - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - } - } - }, - "pathval": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.0.tgz", - "integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA=", - "dev": true - }, - "performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" - }, - "pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", - "dev": true - }, - "pinkie": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", - "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", - "dev": true - }, - "pinkie-promise": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", - "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", - "dev": true, - "requires": { - "pinkie": "^2.0.0" - } - }, - "pkg-dir": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", - "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", - "dev": true, - "requires": { - "find-up": "^3.0.0" - } - }, - "please-upgrade-node": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/please-upgrade-node/-/please-upgrade-node-3.2.0.tgz", - "integrity": "sha512-gQR3WpIgNIKwBMVLkpMUeR3e1/E1y42bqDQZfql+kDeXd8COYfM8PQA4X6y7a8u9Ua9FHmsrrmirW2vHs45hWg==", - "dev": true, - "requires": { - "semver-compare": "^1.0.0" - } - }, - "plur": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/plur/-/plur-3.1.1.tgz", - "integrity": "sha512-t1Ax8KUvV3FFII8ltczPn2tJdjqbd1sIzu6t4JL7nQ3EyeL/lTrj5PWKb06ic5/6XYDr65rQ4uzQEGN70/6X5w==", - "dev": true, - "requires": { - "irregular-plurals": "^2.0.0" - } - }, - "pluralize": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-2.0.0.tgz", - "integrity": "sha1-crcmqm+sHt7uQiVsfY3CVrM1Z38=", - "dev": true - }, - "posix-character-classes": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", - "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", - "dev": true - }, - "prelude-ls": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", - "dev": true - }, - "prettier": { - "version": "1.18.2", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.18.2.tgz", - "integrity": "sha512-OeHeMc0JhFE9idD4ZdtNibzY0+TPHSpSSb9h8FqtP+YnoZZ1sl8Vc9b1sasjfymH3SonAF4QcA2+mzHPhMvIiw==", - "dev": true - }, - "prettier-linter-helpers": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", - "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", - "dev": true, - "requires": { - "fast-diff": "^1.1.2" - } - }, - "pretty-format": { - "version": "23.6.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-23.6.0.tgz", - "integrity": "sha512-zf9NV1NSlDLDjycnwm6hpFATCGl/K1lt0R/GdkAK2O5LN/rwJoB+Mh93gGJjut4YbmecbfgLWVGSTCr0Ewvvbw==", - "dev": true, - "requires": { - "ansi-regex": "^3.0.0", - "ansi-styles": "^3.2.0" - } - }, - "process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true - }, - "progress": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", - "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", - "dev": true - }, - "propagate": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/propagate/-/propagate-1.0.0.tgz", - "integrity": "sha1-AMLa7t2iDofjeCs0Stuhzd1q1wk=", - "dev": true - }, - "proxy-addr": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.4.tgz", - "integrity": "sha512-5erio2h9jp5CHGwcybmxmVqHmnCBZeewlfJ0pex+UW7Qny7OOZXTtH56TGNyBizkgiOwhJtMKrVzDTeKcySZwA==", - "requires": { - "forwarded": "~0.1.2", - "ipaddr.js": "1.8.0" - } - }, - "pseudomap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", - "dev": true - }, - "psl": { - "version": "1.1.31", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.31.tgz", - "integrity": "sha512-/6pt4+C+T+wZUieKR620OpzN/LlnNKuWjy1iFLQ/UG35JqHlR/89MP1d96dUfkf6Dne3TuLQzOYEYshJ+Hx8mw==" - }, - "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" - } - }, - "punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" - }, - "qs": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", - "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" - }, - "query-string": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/query-string/-/query-string-6.5.0.tgz", - "integrity": "sha512-TYC4hDjZSvVxLMEucDMySkuAS9UIzSbAiYGyA9GWCjLKB8fQpviFbjd20fD7uejCDxZS+ftSdBKE6DS+xucJFg==", - "requires": { - "decode-uri-component": "^0.2.0", - "split-on-first": "^1.0.0", - "strict-uri-encode": "^2.0.0" - } - }, - "range-parser": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", - "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=" - }, - "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" - }, - "dependencies": { - "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" - } - }, - "setprototypeof": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", - "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" - } - } - }, - "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" - } - }, - "rc-config-loader": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/rc-config-loader/-/rc-config-loader-2.0.5.tgz", - "integrity": "sha512-T464K2MQlnNWOblUDIglpFhyN+zYJq7jSlL++/N0hUkcmIXeNFumwXFVdtf8qhUGohn4RYQ0wdi74R575I44PQ==", - "dev": true, - "requires": { - "debug": "^4.1.1", - "js-yaml": "^3.12.0", - "json5": "^2.1.0", - "object-assign": "^4.1.0", - "object-keys": "^1.0.12", - "path-exists": "^3.0.0", - "require-from-string": "^2.0.2" - }, - "dependencies": { - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "json5": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.1.tgz", - "integrity": "sha512-l+3HXD0GEI3huGq1njuqtzYK8OYJyXMkOLtQ53pjWh89tvWS2h6l+1zMkYWqlb57+SiQodKZyvMEFb2X+KrFhQ==", - "dev": true, - "requires": { - "minimist": "^1.2.0" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - } - } - }, - "read-pkg": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-4.0.1.tgz", - "integrity": "sha1-ljYlN48+HE1IyFhytabsfV0JMjc=", - "dev": true, - "requires": { - "normalize-package-data": "^2.3.2", - "parse-json": "^4.0.0", - "pify": "^3.0.0" - } - }, - "read-pkg-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-3.0.0.tgz", - "integrity": "sha1-PtSWaF26D4/hGNBpHcUfSh/5bwc=", - "dev": true, - "requires": { - "find-up": "^2.0.0", - "read-pkg": "^3.0.0" - }, - "dependencies": { - "find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true, - "requires": { - "locate-path": "^2.0.0" - } - }, - "load-json-file": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", - "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^4.0.0", - "pify": "^3.0.0", - "strip-bom": "^3.0.0" - } - }, - "locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", - "dev": true, - "requires": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" - } - }, - "p-limit": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", - "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", - "dev": true, - "requires": { - "p-try": "^1.0.0" - } - }, - "p-locate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", - "dev": true, - "requires": { - "p-limit": "^1.1.0" - } - }, - "p-try": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", - "dev": true - }, - "path-type": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", - "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", - "dev": true, - "requires": { - "pify": "^3.0.0" - } - }, - "read-pkg": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", - "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", - "dev": true, - "requires": { - "load-json-file": "^4.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^3.0.0" - } - }, - "strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", - "dev": true - } - } - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "readdirp": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", - "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.11", - "micromatch": "^3.1.10", - "readable-stream": "^2.0.2" - } - }, - "regex-not": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", - "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", - "dev": true, - "requires": { - "extend-shallow": "^3.0.2", - "safe-regex": "^1.1.0" - } - }, - "regexp-clone": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/regexp-clone/-/regexp-clone-1.0.0.tgz", - "integrity": "sha512-TuAasHQNamyyJ2hb97IuBEif4qBHGjPHBS64sZwytpLEqtBQ1gPJTnOaQ6qmpET16cK14kkjbazl6+p0RRv0yw==" - }, - "regexp.prototype.flags": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.3.0.tgz", - "integrity": "sha512-2+Q0C5g951OlYlJz6yu5/M33IcsESLlLfsyIaLJaG4FA2r4yP8MvVMJUUP/fVBkSpbbbZlS5gynbEWLipiiXiQ==", - "dev": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.0-next.1" - }, - "dependencies": { - "es-abstract": { - "version": "1.17.2", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.2.tgz", - "integrity": "sha512-YoKuru3Lyoy7yVTBSH2j7UxTqe/je3dWAruC0sHvZX1GNd5zX8SSLvQqEgO9b3Ex8IW+goFI9arEEsFIbulhOw==", - "dev": true, - "requires": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.1.5", - "is-regex": "^1.0.5", - "object-inspect": "^1.7.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.0", - "string.prototype.trimleft": "^2.1.1", - "string.prototype.trimright": "^2.1.1" - } - }, - "es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "dev": true, - "requires": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - } - }, - "has-symbols": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", - "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", - "dev": true - }, - "is-callable": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.5.tgz", - "integrity": "sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q==", - "dev": true - }, - "is-regex": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.5.tgz", - "integrity": "sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ==", - "dev": true, - "requires": { - "has": "^1.0.3" - } - } - } - }, - "regexpp": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz", - "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==", - "dev": true - }, - "remark": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/remark/-/remark-10.0.1.tgz", - "integrity": "sha512-E6lMuoLIy2TyiokHprMjcWNJ5UxfGQjaMSMhV+f4idM625UjjK4j798+gPs5mfjzDE6vL0oFKVeZM6gZVSVrzQ==", - "dev": true, - "requires": { - "remark-parse": "^6.0.0", - "remark-stringify": "^6.0.0", - "unified": "^7.0.0" - } - }, - "remark-cli": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/remark-cli/-/remark-cli-6.0.1.tgz", - "integrity": "sha512-h7Hwnfdcm5J03t2mxhl9BAav+Goqauqfz3LhpE7TP+RIiPnK6njU7qRDD7qlUd/hLyMSB+WBjYc7gVDQT3pv0A==", - "dev": true, - "requires": { - "markdown-extensions": "^1.1.0", - "remark": "^10.0.0", - "unified-args": "^6.0.0" - } - }, - "remark-frontmatter": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/remark-frontmatter/-/remark-frontmatter-1.3.2.tgz", - "integrity": "sha512-2eayxITZ8rezsXdgcXnYB3iLivohm2V/ZT4Ne8uhua6A4pk6GdLE2ZzJnbnINtD1HRLaTdB7RwF9sgUbMptJZA==", - "dev": true, - "requires": { - "fault": "^1.0.1", - "xtend": "^4.0.1" - } - }, - "remark-lint": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/remark-lint/-/remark-lint-6.0.5.tgz", - "integrity": "sha512-o1I3ddm+KNsTxk60wWGI+p2yU1jB1gcm8jo2Sy6VhJ4ab2TrQIp1oQbp5xeLoFXYSh/NAqCpKjHkCM/BYpkFdQ==", - "dev": true, - "requires": { - "remark-message-control": "^4.0.0" - } - }, - "remark-lint-final-newline": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/remark-lint-final-newline/-/remark-lint-final-newline-1.0.3.tgz", - "integrity": "sha512-ETAadktv75EwUS3XDhyZUVstXKxfPAEn7SmfN9kZ4+Jb4qo4hHE9gtTOzhE6HxLUxxl9BBhpC5mMO3JcL8UZ5A==", - "dev": true, - "requires": { - "unified-lint-rule": "^1.0.0" - } - }, - "remark-lint-hard-break-spaces": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/remark-lint-hard-break-spaces/-/remark-lint-hard-break-spaces-1.0.4.tgz", - "integrity": "sha512-YM82UpgliZCZhGNmFxEe7ArfhqR5CplFf2bc0k0+8w3rKWKx7EJcGMar2NK410tIi40gGeWtH/pIEypPJFCCiA==", - "dev": true, - "requires": { - "unified-lint-rule": "^1.0.0", - "unist-util-generated": "^1.1.0", - "unist-util-position": "^3.0.0", - "unist-util-visit": "^1.1.1" - } - }, - "remark-lint-list-item-bullet-indent": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/remark-lint-list-item-bullet-indent/-/remark-lint-list-item-bullet-indent-1.0.3.tgz", - "integrity": "sha512-iVxQbrgzLpMHG3C6o6wRta/+Bc96etOiBYJnh2zm/aWz6DJ7cGLDykngblP/C4he7LYSeWOD/8Y57HbXZwM2Og==", - "dev": true, - "requires": { - "plur": "^3.0.0", - "unified-lint-rule": "^1.0.0", - "unist-util-generated": "^1.1.0", - "unist-util-position": "^3.0.0", - "unist-util-visit": "^1.1.1" - } - }, - "remark-lint-list-item-indent": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/remark-lint-list-item-indent/-/remark-lint-list-item-indent-1.0.4.tgz", - "integrity": "sha512-Sv0gVH6qP1/nFpbJuyyguB9sAD2o42StD2WbEZeUcEexXwRO4u/YaX0Pm5pMtCiEHyN+qyL6ShKBQMtgol9BeA==", - "dev": true, - "requires": { - "plur": "^3.0.0", - "unified-lint-rule": "^1.0.0", - "unist-util-generated": "^1.1.0", - "unist-util-position": "^3.0.0", - "unist-util-visit": "^1.1.1" - } - }, - "remark-lint-no-auto-link-without-protocol": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/remark-lint-no-auto-link-without-protocol/-/remark-lint-no-auto-link-without-protocol-1.0.3.tgz", - "integrity": "sha512-k+hg2mXnO4Q9WV+UShPLen5oThvFxcRVWkx2hviVd/nu3eiszBKH3o38csBwjeJoMG3l2ZhdUW8dlOBhq8670Q==", - "dev": true, - "requires": { - "mdast-util-to-string": "^1.0.2", - "unified-lint-rule": "^1.0.0", - "unist-util-generated": "^1.1.0", - "unist-util-position": "^3.0.0", - "unist-util-visit": "^1.1.1" - } - }, - "remark-lint-no-blockquote-without-marker": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/remark-lint-no-blockquote-without-marker/-/remark-lint-no-blockquote-without-marker-2.0.3.tgz", - "integrity": "sha512-faDzKrA6aKidsRXG6gcIlCO8TexLxIxe+n9B3mdnl8mhZGgE0FfWTkIWVMj0IYps/xVsVMf45KxhXgc1wU9kwg==", - "dev": true, - "requires": { - "unified-lint-rule": "^1.0.0", - "unist-util-generated": "^1.1.0", - "unist-util-position": "^3.0.0", - "unist-util-visit": "^1.1.1", - "vfile-location": "^2.0.1" - } - }, - "remark-lint-no-duplicate-definitions": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/remark-lint-no-duplicate-definitions/-/remark-lint-no-duplicate-definitions-1.0.5.tgz", - "integrity": "sha512-zKXmfNUODXhJsGQdqfguMG9Nl9v1sLaDsQgMjUtmOSoQRnNud9ThQAZl62eX5jBn5HKcpOifG80tgkyBvU5eEw==", - "dev": true, - "requires": { - "unified-lint-rule": "^1.0.0", - "unist-util-generated": "^1.1.0", - "unist-util-position": "^3.0.0", - "unist-util-stringify-position": "^2.0.0", - "unist-util-visit": "^1.4.0" - } - }, - "remark-lint-no-heading-content-indent": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/remark-lint-no-heading-content-indent/-/remark-lint-no-heading-content-indent-1.0.3.tgz", - "integrity": "sha512-7xM6X5E/dt8OXOHdejH+sfYb139a3kMr8ZSSkcp90Ab1y+ZQBNaWsR3mYh8FRKkYPTN5eyd+KjhNpLWyqqCbgg==", - "dev": true, - "requires": { - "mdast-util-heading-style": "^1.0.2", - "plur": "^3.0.0", - "unified-lint-rule": "^1.0.0", - "unist-util-generated": "^1.1.0", - "unist-util-position": "^3.0.0", - "unist-util-visit": "^1.1.1" - } - }, - "remark-lint-no-inline-padding": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/remark-lint-no-inline-padding/-/remark-lint-no-inline-padding-1.0.4.tgz", - "integrity": "sha512-u5rgbDkcfVv645YxxOwoGBBJbsHEwWm/XqnO8EhfKTxkfKOF4ZItG7Ajhj89EDaeXMkvCcB/avBl4bj50eJH3g==", - "dev": true, - "requires": { - "mdast-util-to-string": "^1.0.2", - "unified-lint-rule": "^1.0.0", - "unist-util-generated": "^1.1.0", - "unist-util-visit": "^1.4.0" - } - }, - "remark-lint-no-literal-urls": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/remark-lint-no-literal-urls/-/remark-lint-no-literal-urls-1.0.3.tgz", - "integrity": "sha512-H5quyMzl2kaewK+jYD1FI0G1SIinIsIp4DEyOUwIR+vYUoKwo0B4vvW0cmPpD1dgqqxHYx0B2B0JQQKFVWzGiw==", - "dev": true, - "requires": { - "mdast-util-to-string": "^1.0.2", - "unified-lint-rule": "^1.0.0", - "unist-util-generated": "^1.1.0", - "unist-util-position": "^3.0.0", - "unist-util-visit": "^1.1.1" - } - }, - "remark-lint-no-shortcut-reference-image": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/remark-lint-no-shortcut-reference-image/-/remark-lint-no-shortcut-reference-image-1.0.3.tgz", - "integrity": "sha512-CGm27X54kXp/5ehXejDTsZjqzK4uIhLGcrFzN3k/KjdwunQouEY92AARGrLSEuJ1hQx0bJsmnvr/hvQyWAfNJg==", - "dev": true, - "requires": { - "unified-lint-rule": "^1.0.0", - "unist-util-generated": "^1.1.0", - "unist-util-visit": "^1.1.1" - } - }, - "remark-lint-no-shortcut-reference-link": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/remark-lint-no-shortcut-reference-link/-/remark-lint-no-shortcut-reference-link-1.0.4.tgz", - "integrity": "sha512-FXdMJYqspZBhPlxYqfVgVluVXjxStg0RHJzqrk8G9wS8fCS62AE3reoaoiCahwoH1tfKcA+poktbKqDAmZo7Jg==", - "dev": true, - "requires": { - "unified-lint-rule": "^1.0.0", - "unist-util-generated": "^1.1.0", - "unist-util-visit": "^1.1.1" - } - }, - "remark-lint-no-undefined-references": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/remark-lint-no-undefined-references/-/remark-lint-no-undefined-references-1.1.1.tgz", - "integrity": "sha512-b1eIjWFaCu6m16Ax2uG33o1v+eRYqDTQRUqU6UeQ76JXmDmVtVO75ZuyRpqqE7VTZRW8YLVurXfJPDXfIa5Wng==", - "dev": true, - "requires": { - "collapse-white-space": "^1.0.4", - "unified-lint-rule": "^1.0.0", - "unist-util-generated": "^1.1.0", - "unist-util-visit": "^1.4.0" - } - }, - "remark-lint-no-unused-definitions": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/remark-lint-no-unused-definitions/-/remark-lint-no-unused-definitions-1.0.5.tgz", - "integrity": "sha512-Bo22e0RNzc1QMW317KTuStGFDG7uTDUQhm/TrW6Qzud0WXnNnqUyvts+e7wTYoj8VnwhhjyjyoA9lKA3uXMdAQ==", - "dev": true, - "requires": { - "unified-lint-rule": "^1.0.0", - "unist-util-generated": "^1.1.0", - "unist-util-visit": "^1.4.0" - } - }, - "remark-lint-ordered-list-marker-style": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/remark-lint-ordered-list-marker-style/-/remark-lint-ordered-list-marker-style-1.0.3.tgz", - "integrity": "sha512-24TmW1eUa/2JlwprZg9jJ8LKLxNGKnlKiI5YOhN4taUp2yv8daqlV9vR54yfn/ZZQh6EQvbIX0jeVY9NYgQUtw==", - "dev": true, - "requires": { - "unified-lint-rule": "^1.0.0", - "unist-util-generated": "^1.1.0", - "unist-util-position": "^3.0.0", - "unist-util-visit": "^1.1.1" - } - }, - "remark-message-control": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/remark-message-control/-/remark-message-control-4.2.0.tgz", - "integrity": "sha512-WXH2t5ljTyhsXlK1zPBLF3iPHbXl58R94phPMreS1xcHWBZJt6Oiu8RtNjy1poZFb3PqKnbYLJeR/CWcZ1bTFw==", - "dev": true, - "requires": { - "mdast-comment-marker": "^1.0.0", - "unified-message-control": "^1.0.0", - "xtend": "^4.0.1" - } - }, - "remark-parse": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-6.0.3.tgz", - "integrity": "sha512-QbDXWN4HfKTUC0hHa4teU463KclLAnwpn/FBn87j9cKYJWWawbiLgMfP2Q4XwhxxuuuOxHlw+pSN0OKuJwyVvg==", - "dev": true, - "requires": { - "collapse-white-space": "^1.0.2", - "is-alphabetical": "^1.0.0", - "is-decimal": "^1.0.0", - "is-whitespace-character": "^1.0.0", - "is-word-character": "^1.0.0", - "markdown-escapes": "^1.0.0", - "parse-entities": "^1.1.0", - "repeat-string": "^1.5.4", - "state-toggle": "^1.0.0", - "trim": "0.0.1", - "trim-trailing-lines": "^1.0.0", - "unherit": "^1.0.4", - "unist-util-remove-position": "^1.0.0", - "vfile-location": "^2.0.0", - "xtend": "^4.0.1" - } - }, - "remark-preset-lint-recommended": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/remark-preset-lint-recommended/-/remark-preset-lint-recommended-3.0.3.tgz", - "integrity": "sha512-5sQ34j1Irlsj6Tt4WWRylZ7UU+1jD5es/LfDZBZp/LXDwC4ldGqKpMmCCR6Z00x1jYM1phmS4M+eGqTdah0qkQ==", - "dev": true, - "requires": { - "remark-lint": "^6.0.0", - "remark-lint-final-newline": "^1.0.0", - "remark-lint-hard-break-spaces": "^1.0.0", - "remark-lint-list-item-bullet-indent": "^1.0.0", - "remark-lint-list-item-indent": "^1.0.0", - "remark-lint-no-auto-link-without-protocol": "^1.0.0", - "remark-lint-no-blockquote-without-marker": "^2.0.0", - "remark-lint-no-duplicate-definitions": "^1.0.0", - "remark-lint-no-heading-content-indent": "^1.0.0", - "remark-lint-no-inline-padding": "^1.0.0", - "remark-lint-no-literal-urls": "^1.0.0", - "remark-lint-no-shortcut-reference-image": "^1.0.0", - "remark-lint-no-shortcut-reference-link": "^1.0.0", - "remark-lint-no-undefined-references": "^1.0.0", - "remark-lint-no-unused-definitions": "^1.0.0", - "remark-lint-ordered-list-marker-style": "^1.0.0" - } - }, - "remark-stringify": { - "version": "6.0.4", - "resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-6.0.4.tgz", - "integrity": "sha512-eRWGdEPMVudijE/psbIDNcnJLRVx3xhfuEsTDGgH4GsFF91dVhw5nhmnBppafJ7+NWINW6C7ZwWbi30ImJzqWg==", - "dev": true, - "requires": { - "ccount": "^1.0.0", - "is-alphanumeric": "^1.0.0", - "is-decimal": "^1.0.0", - "is-whitespace-character": "^1.0.0", - "longest-streak": "^2.0.1", - "markdown-escapes": "^1.0.0", - "markdown-table": "^1.1.0", - "mdast-util-compact": "^1.0.0", - "parse-entities": "^1.0.2", - "repeat-string": "^1.5.4", - "state-toggle": "^1.0.0", - "stringify-entities": "^1.0.1", - "unherit": "^1.0.4", - "xtend": "^4.0.1" - } - }, - "remove-trailing-separator": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", - "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", - "dev": true - }, - "repeat-element": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", - "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==", - "dev": true - }, - "repeat-string": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", - "dev": true - }, - "replace-ext": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz", - "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=", - "dev": true - }, - "request": { - "version": "2.88.0", - "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", - "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", - "requires": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "har-validator": "~5.1.0", - "http-signature": "~1.2.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "oauth-sign": "~0.9.0", - "performance-now": "^2.1.0", - "qs": "~6.5.2", - "safe-buffer": "^5.1.2", - "tough-cookie": "~2.4.3", - "tunnel-agent": "^0.6.0", - "uuid": "^3.3.2" - }, - "dependencies": { - "uuid": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", - "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==" - } - } - }, - "require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", - "dev": true - }, - "require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "dev": true - }, - "require-main-filename": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", - "dev": true - }, - "require_optional": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/require_optional/-/require_optional-1.0.1.tgz", - "integrity": "sha512-qhM/y57enGWHAe3v/NcwML6a3/vfESLe/sGM2dII+gEO0BpKRUkWZow/tyloNqJyN6kXSl3RyyM8Ll5D/sJP8g==", - "requires": { - "resolve-from": "^2.0.0", - "semver": "^5.1.0" - } - }, - "resolve": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", - "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", - "dev": true - }, - "resolve-from": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-2.0.0.tgz", - "integrity": "sha1-lICrIOlP+h2egKgEx+oUdhGWa1c=" - }, - "resolve-url": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", - "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", - "dev": true - }, - "restore-cursor": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", - "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", - "dev": true, - "requires": { - "onetime": "^2.0.0", - "signal-exit": "^3.0.2" - } - }, - "ret": { - "version": "0.1.15", - "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", - "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", - "dev": true - }, - "revalidator": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/revalidator/-/revalidator-0.3.1.tgz", - "integrity": "sha1-/yzEz3zHxjhaxxAXgnbm280Ddi8=" - }, - "rimraf": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", - "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - }, - "dependencies": { - "glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - } - } - }, - "run-async": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", - "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", - "dev": true, - "requires": { - "is-promise": "^2.1.0" - } - }, - "run-node": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/run-node/-/run-node-1.0.0.tgz", - "integrity": "sha512-kc120TBlQ3mih1LSzdAJXo4xn/GWS2ec0l3S+syHDXP9uRr0JAT8Qd3mdMuyjqCzeZktgP3try92cEgf9Nks8A==", - "dev": true - }, - "rxjs": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.2.tgz", - "integrity": "sha512-HUb7j3kvb7p7eCUHE3FqjoDsC1xfZQ4AHFWfTKSpZ+sAhhz5X1WX0ZuUqWbzB2QhSLp3DoLUG+hMdEDKqWo2Zg==", - "dev": true, - "requires": { - "tslib": "^1.9.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==" - }, - "safe-json-stringify": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/safe-json-stringify/-/safe-json-stringify-1.2.0.tgz", - "integrity": "sha512-gH8eh2nZudPQO6TytOvbxnuhYBOvDBBLW52tz5q6X58lJcd/tkmqFR+5Z9adS8aJtURSXWThWy/xJtJwixErvg==" - }, - "safe-regex": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", - "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", - "dev": true, - "requires": { - "ret": "~0.1.10" - } - }, - "safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" - }, - "saslprep": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/saslprep/-/saslprep-1.0.2.tgz", - "integrity": "sha512-4cDsYuAjXssUSjxHKRe4DTZC0agDwsCqcMqtJAQPzC74nJ7LfAJflAtC1Zed5hMzEQKj82d3tuzqdGNRsLJ4Gw==", - "optional": true, - "requires": { - "sparse-bitfield": "^3.0.3" - } - }, - "semver": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz", - "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==" - }, - "semver-compare": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", - "integrity": "sha1-De4hahyUGrN+nvsXiPavxf9VN/w=", - "dev": true - }, - "send": { - "version": "0.16.2", - "resolved": "https://registry.npmjs.org/send/-/send-0.16.2.tgz", - "integrity": "sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw==", - "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.6.2", - "mime": "1.4.1", - "ms": "2.0.0", - "on-finished": "~2.3.0", - "range-parser": "~1.2.0", - "statuses": "~1.4.0" - }, - "dependencies": { - "statuses": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", - "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==" - } - } - }, - "serr": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/serr/-/serr-1.0.1.tgz", - "integrity": "sha1-dKW55/rdW1X4qF5+crwApBm25II=", - "requires": { - "lodash": "^4.0.0" - } - }, - "serve-static": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.2.tgz", - "integrity": "sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw==", - "requires": { - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "parseurl": "~1.3.2", - "send": "0.16.2" - } - }, - "set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", - "dev": true - }, - "set-value": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", - "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-extendable": "^0.1.1", - "is-plain-object": "^2.0.3", - "split-string": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "setprototypeof": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", - "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" - }, - "shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", - "dev": true, - "requires": { - "shebang-regex": "^1.0.0" - } - }, - "shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", - "dev": true - }, - "shellsubstitute": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shellsubstitute/-/shellsubstitute-1.2.0.tgz", - "integrity": "sha1-5PcCpQxRiw9v6YRRiQ1wWvKba3A=", - "dev": true - }, - "should": { - "version": "13.2.3", - "resolved": "https://registry.npmjs.org/should/-/should-13.2.3.tgz", - "integrity": "sha512-ggLesLtu2xp+ZxI+ysJTmNjh2U0TsC+rQ/pfED9bUZZ4DKefP27D+7YJVVTvKsmjLpIi9jAa7itwDGkDDmt1GQ==", - "dev": true, - "requires": { - "should-equal": "^2.0.0", - "should-format": "^3.0.3", - "should-type": "^1.4.0", - "should-type-adaptors": "^1.0.1", - "should-util": "^1.0.0" - } - }, - "should-equal": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/should-equal/-/should-equal-2.0.0.tgz", - "integrity": "sha512-ZP36TMrK9euEuWQYBig9W55WPC7uo37qzAEmbjHz4gfyuXrEUgF8cUvQVO+w+d3OMfPvSRQJ22lSm8MQJ43LTA==", - "dev": true, - "requires": { - "should-type": "^1.4.0" - } - }, - "should-format": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/should-format/-/should-format-3.0.3.tgz", - "integrity": "sha1-m/yPdPo5IFxT04w01xcwPidxJPE=", - "dev": true, - "requires": { - "should-type": "^1.3.0", - "should-type-adaptors": "^1.0.1" - } - }, - "should-type": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/should-type/-/should-type-1.4.0.tgz", - "integrity": "sha1-B1bYzoRt/QmEOmlHcZ36DUz/XPM=", - "dev": true - }, - "should-type-adaptors": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/should-type-adaptors/-/should-type-adaptors-1.1.0.tgz", - "integrity": "sha512-JA4hdoLnN+kebEp2Vs8eBe9g7uy0zbRo+RMcU0EsNy+R+k049Ki+N5tT5Jagst2g7EAja+euFuoXFCa8vIklfA==", - "dev": true, - "requires": { - "should-type": "^1.3.0", - "should-util": "^1.0.0" - } - }, - "should-util": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/should-util/-/should-util-1.0.0.tgz", - "integrity": "sha1-yYzaN0qmsZDfi6h8mInCtNtiAGM=", - "dev": true - }, - "sift": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/sift/-/sift-7.0.1.tgz", - "integrity": "sha512-oqD7PMJ+uO6jV9EQCl0LrRw1OwsiPsiFQR5AR30heR+4Dl7jBBbDLnNvWiak20tzZlSE1H7RB30SX/1j/YYT7g==" - }, - "signal-exit": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", - "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", - "dev": true - }, - "slash": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", - "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", - "dev": true - }, - "slice-ansi": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz", - "integrity": "sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU=", - "dev": true - }, - "sliced": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/sliced/-/sliced-1.0.1.tgz", - "integrity": "sha1-CzpmK10Ewxd7GSa+qCsD+Dei70E=" - }, - "snapdragon": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", - "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", - "dev": true, - "requires": { - "base": "^0.11.1", - "debug": "^2.2.0", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "map-cache": "^0.2.2", - "source-map": "^0.5.6", - "source-map-resolve": "^0.5.0", - "use": "^3.1.0" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - } - } - }, - "snapdragon-node": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", - "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", - "dev": true, - "requires": { - "define-property": "^1.0.0", - "isobject": "^3.0.0", - "snapdragon-util": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } - } - }, - "snapdragon-util": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", - "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", - "dev": true, - "requires": { - "kind-of": "^3.2.0" - }, - "dependencies": { - "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "source-map": { - "version": "0.1.43", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", - "integrity": "sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y=", - "optional": true, - "requires": { - "amdefine": ">=0.0.4" - } - }, - "source-map-resolve": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz", - "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==", - "dev": true, - "requires": { - "atob": "^2.1.1", - "decode-uri-component": "^0.2.0", - "resolve-url": "^0.2.1", - "source-map-url": "^0.4.0", - "urix": "^0.1.0" - } - }, - "source-map-url": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", - "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", - "dev": true - }, - "sparse-bitfield": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", - "integrity": "sha1-/0rm5oZWBWuks+eSqzM004JzyhE=", - "optional": true, - "requires": { - "memory-pager": "^1.0.2" - } - }, - "spdx-correct": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz", - "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==", - "dev": true, - "requires": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-exceptions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", - "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==", - "dev": true - }, - "spdx-expression-parse": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", - "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", - "dev": true, - "requires": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-license-ids": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz", - "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==", - "dev": true - }, - "split-on-first": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/split-on-first/-/split-on-first-1.1.0.tgz", - "integrity": "sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw==" - }, - "split-string": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", - "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", - "dev": true, - "requires": { - "extend-shallow": "^3.0.0" - } - }, - "sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", - "dev": true - }, - "sshpk": { - "version": "1.16.1", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", - "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", - "requires": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "safer-buffer": "^2.0.2", - "tweetnacl": "~0.14.0" - } - }, - "staged-git-files": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/staged-git-files/-/staged-git-files-1.1.1.tgz", - "integrity": "sha512-H89UNKr1rQJvI1c/PIR3kiAMBV23yvR7LItZiV74HWZwzt7f3YHuujJ9nJZlt58WlFox7XQsOahexwk7nTe69A==", - "dev": true - }, - "state-toggle": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/state-toggle/-/state-toggle-1.0.2.tgz", - "integrity": "sha512-8LpelPGR0qQM4PnfLiplOQNJcIN1/r2Gy0xKB2zKnIW2YzPMt2sR4I/+gtPjhN7Svh9kw+zqEg2SFwpBO9iNiw==", - "dev": true - }, - "static-extend": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", - "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", - "dev": true, - "requires": { - "define-property": "^0.2.5", - "object-copy": "^0.1.0" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - } - } - }, - "statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" - }, - "strict-uri-encode": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz", - "integrity": "sha1-ucczDHBChi9rFC3CdLvMWGbONUY=" - }, - "string-argv": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.0.2.tgz", - "integrity": "sha1-2sMECGkMIfPDYwo/86BYd73L1zY=", - "dev": true - }, - "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true, - "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - } - }, - "string.prototype.padstart": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string.prototype.padstart/-/string.prototype.padstart-3.1.0.tgz", - "integrity": "sha512-envqZvUp2JItI+OeQ5UAh1ihbAV5G/2bixTojvlIa090GGqF+NQRxbWb2nv9fTGrZABv6+pE6jXoAZhhS2k4Hw==", - "dev": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.0-next.1" - }, - "dependencies": { - "es-abstract": { - "version": "1.17.2", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.2.tgz", - "integrity": "sha512-YoKuru3Lyoy7yVTBSH2j7UxTqe/je3dWAruC0sHvZX1GNd5zX8SSLvQqEgO9b3Ex8IW+goFI9arEEsFIbulhOw==", - "dev": true, - "requires": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.1.5", - "is-regex": "^1.0.5", - "object-inspect": "^1.7.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.0", - "string.prototype.trimleft": "^2.1.1", - "string.prototype.trimright": "^2.1.1" - } - }, - "es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "dev": true, - "requires": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - } - }, - "has-symbols": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", - "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", - "dev": true - }, - "is-callable": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.5.tgz", - "integrity": "sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q==", - "dev": true - }, - "is-regex": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.5.tgz", - "integrity": "sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ==", - "dev": true, - "requires": { - "has": "^1.0.3" - } - } - } - }, - "string.prototype.trimleft": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.1.tgz", - "integrity": "sha512-iu2AGd3PuP5Rp7x2kEZCrB2Nf41ehzh+goo8TV7z8/XDBbsvc6HQIlUl9RjkZ4oyrW1XM5UwlGl1oVEaDjg6Ag==", - "dev": true, - "requires": { - "define-properties": "^1.1.3", - "function-bind": "^1.1.1" - } - }, - "string.prototype.trimright": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.1.tgz", - "integrity": "sha512-qFvWL3/+QIgZXVmJBfpHmxLB7xsUXz6HsUmP8+5dRaC3Q7oKUv9Vo6aMCRZC1smrtyECFsIT30PqBJ1gTjAs+g==", - "dev": true, - "requires": { - "define-properties": "^1.1.3", - "function-bind": "^1.1.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - }, - "stringify-entities": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-1.3.2.tgz", - "integrity": "sha512-nrBAQClJAPN2p+uGCVJRPIPakKeKWZ9GtBCmormE7pWOSlHat7+x5A8gx85M7HM5Dt0BP3pP5RhVW77WdbJJ3A==", - "dev": true, - "requires": { - "character-entities-html4": "^1.0.0", - "character-entities-legacy": "^1.0.0", - "is-alphanumerical": "^1.0.0", - "is-hexadecimal": "^1.0.0" - } - }, - "stringify-object": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/stringify-object/-/stringify-object-3.3.0.tgz", - "integrity": "sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw==", - "dev": true, - "requires": { - "get-own-enumerable-property-symbols": "^3.0.0", - "is-obj": "^1.0.1", - "is-regexp": "^1.0.0" - } - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "^3.0.0" - } - }, - "strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "dev": true, - "requires": { - "is-utf8": "^0.2.0" - } - }, - "strip-eof": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", - "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", - "dev": true - }, - "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 - }, - "structured-source": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/structured-source/-/structured-source-3.0.2.tgz", - "integrity": "sha1-3YAkJeD1PcSm56yjdSkBoczaevU=", - "dev": true, - "requires": { - "boundary": "^1.0.1" - } - }, - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true, - "requires": { - "has-flag": "^1.0.0" - } - }, - "symbol-observable": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz", - "integrity": "sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==", - "dev": true - }, - "table": { - "version": "5.4.6", - "resolved": "https://registry.npmjs.org/table/-/table-5.4.6.tgz", - "integrity": "sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug==", - "dev": true, - "requires": { - "ajv": "^6.10.2", - "lodash": "^4.17.14", - "slice-ansi": "^2.1.0", - "string-width": "^3.0.0" - }, - "dependencies": { - "ajv": { - "version": "6.10.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz", - "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==", - "dev": true, - "requires": { - "fast-deep-equal": "^2.0.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "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 - }, - "lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", - "dev": true - }, - "slice-ansi": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz", - "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.0", - "astral-regex": "^1.0.0", - "is-fullwidth-code-point": "^2.0.0" - } - }, - "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" - } - }, - "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" - } - } - } - }, - "text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", - "dev": true - }, - "textlint": { - "version": "11.3.1", - "resolved": "https://registry.npmjs.org/textlint/-/textlint-11.3.1.tgz", - "integrity": "sha512-svbO/fhj7dLTJcdKgrW5fJtNRHoFFVL+sutsKBmNUcSJgvgWteLOUZAKT/dp/4S0QfkwkpNOts7Bzn9T+0h0Cw==", - "dev": true, - "requires": { - "@textlint/ast-node-types": "^4.2.4", - "@textlint/ast-traverse": "^2.1.5", - "@textlint/feature-flag": "^3.1.3", - "@textlint/fixer-formatter": "^3.1.8", - "@textlint/kernel": "^3.1.8", - "@textlint/linter-formatter": "^3.1.7", - "@textlint/module-interop": "^1.0.1", - "@textlint/textlint-plugin-markdown": "^5.1.8", - "@textlint/textlint-plugin-text": "^4.1.8", - "@textlint/types": "^1.2.1", - "@textlint/utils": "^1.0.2", - "@types/bluebird": "^3.5.18", - "bluebird": "^3.0.5", - "debug": "^4.1.1", - "deep-equal": "^1.0.1", - "file-entry-cache": "^5.0.1", - "get-stdin": "^5.0.1", - "glob": "^7.1.3", - "is-file": "^1.0.0", - "log-symbols": "^1.0.2", - "map-like": "^2.0.0", - "md5": "^2.2.1", - "mkdirp": "^0.5.0", - "optionator": "^0.8.0", - "path-to-glob-pattern": "^1.0.2", - "rc-config-loader": "^2.0.4", - "read-pkg": "^1.1.0", - "read-pkg-up": "^3.0.0", - "structured-source": "^3.0.2", - "try-resolve": "^1.0.1", - "unique-concat": "^0.2.2" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - }, - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - } - }, - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "get-stdin": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-5.0.1.tgz", - "integrity": "sha1-Ei4WFZHiH/TFJTAwVpPyDmOTo5g=", - "dev": true - }, - "glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "log-symbols": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-1.0.2.tgz", - "integrity": "sha1-N2/3tY6jCGoPCfrMdGF+ylAeGhg=", - "dev": true, - "requires": { - "chalk": "^1.0.0" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "read-pkg": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", - "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", - "dev": true, - "requires": { - "load-json-file": "^1.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^1.0.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - } - } - }, - "textlint-filter-rule-comments": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/textlint-filter-rule-comments/-/textlint-filter-rule-comments-1.2.2.tgz", - "integrity": "sha1-OnLElJlOBo4OSqrQ8k6nz+M4UDo=", - "dev": true - }, - "textlint-rule-common-misspellings": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/textlint-rule-common-misspellings/-/textlint-rule-common-misspellings-1.0.1.tgz", - "integrity": "sha1-jEEzzzu1mqFZGZ0sm87RJBM2V3Q=", - "dev": true, - "requires": { - "misspellings": "^1.0.1", - "textlint-rule-helper": "^1.1.5" - } - }, - "textlint-rule-helper": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/textlint-rule-helper/-/textlint-rule-helper-1.2.0.tgz", - "integrity": "sha1-vmjUelFGsW3RFieMmut701YxzNo=", - "dev": true, - "requires": { - "unist-util-visit": "^1.1.0" - } - }, - "textlint-rule-no-dead-link": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/textlint-rule-no-dead-link/-/textlint-rule-no-dead-link-4.6.2.tgz", - "integrity": "sha512-f11iwmihzQhWwO8KCa4sYMhiZhnfRYwXQbuFILZVoNhBRfcxYF3A19N/poYgAcCJRre9GkCv7/B2RiraxKUUjA==", - "dev": true, - "requires": { - "fs-extra": "^8.1.0", - "get-url-origin": "^1.0.1", - "minimatch": "^3.0.4", - "node-fetch": "^2.6.0", - "p-memoize": "^3.1.0", - "p-queue": "^6.2.0", - "textlint-rule-helper": "^2.1.1" - }, - "dependencies": { - "textlint-rule-helper": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/textlint-rule-helper/-/textlint-rule-helper-2.1.1.tgz", - "integrity": "sha512-6fxgHzoJVkjl3LaC1b2Egi+5wbhG4i0pU0knJmQujVhxIJ3D3AcQQZPs457xKAi5xKz1WayYeTeJ5jrD/hnO7g==", - "dev": true, - "requires": { - "@textlint/ast-node-types": "^4.2.1", - "@textlint/types": "^1.1.2", - "structured-source": "^3.0.2", - "unist-util-visit": "^1.1.0" - } - } - } - }, - "textlint-rule-terminology": { - "version": "1.1.30", - "resolved": "https://registry.npmjs.org/textlint-rule-terminology/-/textlint-rule-terminology-1.1.30.tgz", - "integrity": "sha512-PsLiridAdaLyho236adWnTEAbAcxxUsxVqaXWaJce+aRsjCOeyYPBLNRisFGz90KZ0S1NDYT/v5CvzBrgsiuzQ==", - "dev": true, - "requires": { - "lodash": "^4.17.4", - "strip-json-comments": "^2.0.1", - "textlint-rule-helper": "^2.0.0" - }, - "dependencies": { - "textlint-rule-helper": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/textlint-rule-helper/-/textlint-rule-helper-2.1.1.tgz", - "integrity": "sha512-6fxgHzoJVkjl3LaC1b2Egi+5wbhG4i0pU0knJmQujVhxIJ3D3AcQQZPs457xKAi5xKz1WayYeTeJ5jrD/hnO7g==", - "dev": true, - "requires": { - "@textlint/ast-node-types": "^4.2.1", - "@textlint/types": "^1.1.2", - "structured-source": "^3.0.2", - "unist-util-visit": "^1.1.0" - } - } - } - }, - "textlint-rule-write-good": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/textlint-rule-write-good/-/textlint-rule-write-good-1.6.2.tgz", - "integrity": "sha1-PHmwQJExnU6L5ftELFlr9QDoST4=", - "dev": true, - "requires": { - "textlint-rule-helper": "^2.0.0", - "write-good": "^0.11.0" - }, - "dependencies": { - "textlint-rule-helper": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/textlint-rule-helper/-/textlint-rule-helper-2.1.1.tgz", - "integrity": "sha512-6fxgHzoJVkjl3LaC1b2Egi+5wbhG4i0pU0knJmQujVhxIJ3D3AcQQZPs457xKAi5xKz1WayYeTeJ5jrD/hnO7g==", - "dev": true, - "requires": { - "@textlint/ast-node-types": "^4.2.1", - "@textlint/types": "^1.1.2", - "structured-source": "^3.0.2", - "unist-util-visit": "^1.1.0" - } - } - } - }, - "through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", - "dev": true - }, - "timekeeper": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/timekeeper/-/timekeeper-2.2.0.tgz", - "integrity": "sha512-W3AmPTJWZkRwu+iSNxPIsLZ2ByADsOLbbLxe46UJyWj3mlYLlwucKiq+/dPm0l9wTzqoF3/2PH0AGFCebjq23A==", - "dev": true - }, - "tmp": { - "version": "0.0.33", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", - "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", - "dev": true, - "requires": { - "os-tmpdir": "~1.0.2" - } - }, - "to-object-path": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", - "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "to-regex": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", - "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", - "dev": true, - "requires": { - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "regex-not": "^1.0.2", - "safe-regex": "^1.1.0" - } - }, - "to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", - "dev": true, - "requires": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" - } - }, - "to-vfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/to-vfile/-/to-vfile-4.0.0.tgz", - "integrity": "sha512-Y7EDM+uoU8TZxF5ej2mUR0dLO4qbuuNRnJKxEht2QJWEq2421pyG1D1x8YxPKmyTc6nHh7Td/jLGFxYo+9vkLA==", - "dev": true, - "requires": { - "is-buffer": "^2.0.0", - "vfile": "^3.0.0" - } - }, - "toidentifier": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", - "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==" - }, - "too-wordy": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/too-wordy/-/too-wordy-0.1.6.tgz", - "integrity": "sha512-MV5F74YF9+UYsvwXGXTh+5YP3EqH/ivwWfyFE2/YHWQQxm9jDPmkIC23nkN133Ye4nO3HTXmiMcfGqJ5xRPfOA==", - "dev": true - }, - "tough-cookie": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", - "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", - "requires": { - "psl": "^1.1.24", - "punycode": "^1.4.1" - }, - "dependencies": { - "punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" - } - } - }, - "traverse": { - "version": "0.6.6", - "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.6.6.tgz", - "integrity": "sha1-y99WD9e5r2MlAv7UD5GMFX6pcTc=", - "dev": true - }, - "trim": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/trim/-/trim-0.0.1.tgz", - "integrity": "sha1-WFhUf2spB1fulczMZm+1AITEYN0=", - "dev": true - }, - "trim-trailing-lines": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/trim-trailing-lines/-/trim-trailing-lines-1.1.2.tgz", - "integrity": "sha512-MUjYItdrqqj2zpcHFTkMa9WAv4JHTI6gnRQGPFLrt5L9a6tRMiDnIqYl8JBvu2d2Tc3lWJKQwlGCp0K8AvCM+Q==", - "dev": true - }, - "trough": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/trough/-/trough-1.0.4.tgz", - "integrity": "sha512-tdzBRDGWcI1OpPVmChbdSKhvSVurznZ8X36AYURAcl+0o2ldlCY2XPzyXNNxwJwwyIU+rIglTCG4kxtNKBQH7Q==", - "dev": true - }, - "try-resolve": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/try-resolve/-/try-resolve-1.0.1.tgz", - "integrity": "sha1-z95vq9ctY+V5fPqrhzq76OcA6RI=", - "dev": true - }, - "tslib": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", - "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==", - "dev": true - }, - "tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", - "requires": { - "safe-buffer": "^5.0.1" - } - }, - "tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" - }, - "type-check": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", - "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", - "dev": true, - "requires": { - "prelude-ls": "~1.1.2" - } - }, - "type-detect": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", - "dev": true - }, - "type-is": { - "version": "1.6.16", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz", - "integrity": "sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q==", - "requires": { - "media-typer": "0.3.0", - "mime-types": "~2.1.18" - } - }, - "typedarray": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", - "dev": true - }, - "uglify-js": { - "version": "3.5.9", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.5.9.tgz", - "integrity": "sha512-WpT0RqsDtAWPNJK955DEnb6xjymR8Fn0OlK4TT4pS0ASYsVPqr5ELhgwOwLCP5J5vHeJ4xmMmz3DEgdqC10JeQ==", - "dev": true, - "optional": true, - "requires": { - "commander": "~2.20.0", - "source-map": "~0.6.1" - }, - "dependencies": { - "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, - "optional": true - } - } - }, - "underscore": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.9.1.tgz", - "integrity": "sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg==" - }, - "unherit": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/unherit/-/unherit-1.1.2.tgz", - "integrity": "sha512-W3tMnpaMG7ZY6xe/moK04U9fBhi6wEiCYHUW5Mop/wQHf12+79EQGwxYejNdhEz2mkqkBlGwm7pxmgBKMVUj0w==", - "dev": true, - "requires": { - "inherits": "^2.0.1", - "xtend": "^4.0.1" - } - }, - "unified": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/unified/-/unified-7.1.0.tgz", - "integrity": "sha512-lbk82UOIGuCEsZhPj8rNAkXSDXd6p0QLzIuSsCdxrqnqU56St4eyOB+AlXsVgVeRmetPTYydIuvFfpDIed8mqw==", - "dev": true, - "requires": { - "@types/unist": "^2.0.0", - "@types/vfile": "^3.0.0", - "bail": "^1.0.0", - "extend": "^3.0.0", - "is-plain-obj": "^1.1.0", - "trough": "^1.0.0", - "vfile": "^3.0.0", - "x-is-string": "^0.1.0" - } - }, - "unified-args": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/unified-args/-/unified-args-6.0.0.tgz", - "integrity": "sha512-1m2pGiTClgcCtCvgtABkJLze8JJiZpzsqujRhzBjZsRwaIIU1Yj36YHY6t2RvidO8d6fucZdk3KX+8eS4+uv9g==", - "dev": true, - "requires": { - "camelcase": "^5.0.0", - "chalk": "^2.0.0", - "chokidar": "^2.0.0", - "fault": "^1.0.2", - "json5": "^1.0.0", - "minimist": "^1.2.0", - "text-table": "^0.2.0", - "unified-engine": "^6.0.0" - } - }, - "unified-engine": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/unified-engine/-/unified-engine-6.0.1.tgz", - "integrity": "sha512-iDJYH82TgcezQA4IZzhCNJQx7vBsGk4h9s4Q7Fscrb3qcPsxBqVrVNYez2W3sBVTxuU1bFAhyRpA6ba/R4j93A==", - "dev": true, - "requires": { - "concat-stream": "^1.5.1", - "debug": "^3.1.0", - "fault": "^1.0.0", - "fn-name": "^2.0.1", - "glob": "^7.0.3", - "ignore": "^3.2.0", - "is-empty": "^1.0.0", - "is-hidden": "^1.0.1", - "is-object": "^1.0.1", - "js-yaml": "^3.6.1", - "load-plugin": "^2.0.0", - "parse-json": "^4.0.0", - "to-vfile": "^4.0.0", - "trough": "^1.0.0", - "unist-util-inspect": "^4.1.2", - "vfile-reporter": "^5.0.0", - "vfile-statistics": "^1.1.0", - "x-is-string": "^0.1.0", - "xtend": "^4.0.1" - }, - "dependencies": { - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "ignore": { - "version": "3.3.10", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz", - "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==", - "dev": true - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - } - } - }, - "unified-lint-rule": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/unified-lint-rule/-/unified-lint-rule-1.0.4.tgz", - "integrity": "sha512-q9wY6S+d38xRAuWQVOMjBQYi7zGyKkY23ciNafB8JFVmDroyKjtytXHCg94JnhBCXrNqpfojo3+8D+gmF4zxJQ==", - "dev": true, - "requires": { - "wrapped": "^1.0.1" - } - }, - "unified-message-control": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/unified-message-control/-/unified-message-control-1.0.4.tgz", - "integrity": "sha512-e1dEtN4Z/TvLn/qHm+xeZpzqhJTtfZusFErk336kkZVpqrJYiV9ptxq+SbRPFMlN0OkjDYHmVJ929KYjsMTo3g==", - "dev": true, - "requires": { - "trim": "0.0.1", - "unist-util-visit": "^1.0.0", - "vfile-location": "^2.0.0" - } - }, - "union-value": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", - "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", - "dev": true, - "requires": { - "arr-union": "^3.1.0", - "get-value": "^2.0.6", - "is-extendable": "^0.1.1", - "set-value": "^2.0.1" - } - }, - "unique-concat": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/unique-concat/-/unique-concat-0.2.2.tgz", - "integrity": "sha1-khD5vcqsxeHjkpSQ18AZ35bxhxI=", - "dev": true - }, - "unist-util-generated": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/unist-util-generated/-/unist-util-generated-1.1.5.tgz", - "integrity": "sha512-1TC+NxQa4N9pNdayCYA1EGUOCAO0Le3fVp7Jzns6lnua/mYgwHo0tz5WUAfrdpNch1RZLHc61VZ1SDgrtNXLSw==", - "dev": true - }, - "unist-util-inspect": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/unist-util-inspect/-/unist-util-inspect-4.1.4.tgz", - "integrity": "sha512-7xxyvKiZ1SC9vL5qrMqKub1T31gRHfau4242F69CcaOrXt//5PmRVOmDZ36UAEgiT+tZWzmQmbNZn+mVtnR9HQ==", - "dev": true, - "requires": { - "is-empty": "^1.0.0" - } - }, - "unist-util-is": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-3.0.0.tgz", - "integrity": "sha512-sVZZX3+kspVNmLWBPAB6r+7D9ZgAFPNWm66f7YNb420RlQSbn+n8rG8dGZSkrER7ZIXGQYNm5pqC3v3HopH24A==", - "dev": true - }, - "unist-util-position": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-3.0.4.tgz", - "integrity": "sha512-tWvIbV8goayTjobxDIr4zVTyG+Q7ragMSMeKC3xnPl9xzIc0+she8mxXLM3JVNDDsfARPbCd3XdzkyLdo7fF3g==", - "dev": true - }, - "unist-util-remove-position": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-1.1.4.tgz", - "integrity": "sha512-tLqd653ArxJIPnKII6LMZwH+mb5q+n/GtXQZo6S6csPRs5zB0u79Yw8ouR3wTw8wxvdJFhpP6Y7jorWdCgLO0A==", - "dev": true, - "requires": { - "unist-util-visit": "^1.1.0" - } - }, - "unist-util-stringify-position": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-2.0.2.tgz", - "integrity": "sha512-nK5n8OGhZ7ZgUwoUbL8uiVRwAbZyzBsB/Ddrlbu6jwwubFza4oe15KlyEaLNMXQW1svOQq4xesUeqA85YrIUQA==", - "dev": true, - "requires": { - "@types/unist": "^2.0.2" - } - }, - "unist-util-visit": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-1.4.1.tgz", - "integrity": "sha512-AvGNk7Bb//EmJZyhtRUnNMEpId/AZ5Ph/KUpTI09WHQuDZHKovQ1oEv3mfmKpWKtoMzyMC4GLBm1Zy5k12fjIw==", - "dev": true, - "requires": { - "unist-util-visit-parents": "^2.0.0" - } - }, - "unist-util-visit-parents": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-2.1.2.tgz", - "integrity": "sha512-DyN5vD4NE3aSeB+PXYNKxzGsfocxp6asDc2XXE3b0ekO2BaRUpBicbbUygfSvYfUz1IkmjFR1YF7dPklraMZ2g==", - "dev": true, - "requires": { - "unist-util-is": "^3.0.0" - } - }, - "universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", - "dev": true - }, - "unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" - }, - "unset-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", - "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", - "dev": true, - "requires": { - "has-value": "^0.3.1", - "isobject": "^3.0.0" - }, - "dependencies": { - "has-value": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", - "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", - "dev": true, - "requires": { - "get-value": "^2.0.3", - "has-values": "^0.1.4", - "isobject": "^2.0.0" - }, - "dependencies": { - "isobject": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", - "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "dev": true, - "requires": { - "isarray": "1.0.0" - } - } - } - }, - "has-values": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", - "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", - "dev": true - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - } - } - }, - "untildify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/untildify/-/untildify-2.1.0.tgz", - "integrity": "sha1-F+soB5h/dpUunASF/DEdBqgmouA=", - "dev": true, - "requires": { - "os-homedir": "^1.0.0" - } - }, - "upath": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", - "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==", - "dev": true - }, - "uri-js": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", - "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", - "requires": { - "punycode": "^2.1.0" - } - }, - "urix": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", - "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", - "dev": true - }, - "use": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", - "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", - "dev": true - }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true - }, - "utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" - }, - "uuid": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", - "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==" - }, - "validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "dev": true, - "requires": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, - "vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" - }, - "verror": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", - "requires": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" - } - }, - "vfile": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/vfile/-/vfile-3.0.1.tgz", - "integrity": "sha512-y7Y3gH9BsUSdD4KzHsuMaCzRjglXN0W2EcMf0gpvu6+SbsGhMje7xDc8AEoeXy6mIwCKMI6BkjMsRjzQbhMEjQ==", - "dev": true, - "requires": { - "is-buffer": "^2.0.0", - "replace-ext": "1.0.0", - "unist-util-stringify-position": "^1.0.0", - "vfile-message": "^1.0.0" - }, - "dependencies": { - "unist-util-stringify-position": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-1.1.2.tgz", - "integrity": "sha512-pNCVrk64LZv1kElr0N1wPiHEUoXNVFERp+mlTg/s9R5Lwg87f9bM/3sQB99w+N9D/qnM9ar3+AKDBwo/gm/iQQ==", - "dev": true - }, - "vfile-message": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-1.1.1.tgz", - "integrity": "sha512-1WmsopSGhWt5laNir+633LszXvZ+Z/lxveBf6yhGsqnQIhlhzooZae7zV6YVM1Sdkw68dtAW3ow0pOdPANugvA==", - "dev": true, - "requires": { - "unist-util-stringify-position": "^1.1.1" - } - } - } - }, - "vfile-location": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-2.0.6.tgz", - "integrity": "sha512-sSFdyCP3G6Ka0CEmN83A2YCMKIieHx0EDaj5IDP4g1pa5ZJ4FJDvpO0WODLxo4LUX4oe52gmSCK7Jw4SBghqxA==", - "dev": true - }, - "vfile-message": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-2.0.2.tgz", - "integrity": "sha512-gNV2Y2fDvDOOqq8bEe7cF3DXU6QgV4uA9zMR2P8tix11l1r7zju3zry3wZ8sx+BEfuO6WQ7z2QzfWTvqHQiwsA==", - "dev": true, - "requires": { - "@types/unist": "^2.0.0", - "unist-util-stringify-position": "^2.0.0" - } - }, - "vfile-reporter": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/vfile-reporter/-/vfile-reporter-5.1.2.tgz", - "integrity": "sha512-b15sTuss1wOPWVlyWOvu+n6wGJ/eTYngz3uqMLimQvxZ+Q5oFQGYZZP1o3dR9sk58G5+wej0UPCZSwQBX/mzrQ==", - "dev": true, - "requires": { - "repeat-string": "^1.5.0", - "string-width": "^2.0.0", - "supports-color": "^5.0.0", - "unist-util-stringify-position": "^2.0.0", - "vfile-sort": "^2.1.2", - "vfile-statistics": "^1.1.0" - }, - "dependencies": { - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "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" - } - } - } - }, - "vfile-sort": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/vfile-sort/-/vfile-sort-2.2.1.tgz", - "integrity": "sha512-5dt7xEhC44h0uRQKhbM2JAe0z/naHphIZlMOygtMBM9Nn0pZdaX5fshhwWit9wvsuP8t/wp43nTDRRErO1WK8g==", - "dev": true - }, - "vfile-statistics": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/vfile-statistics/-/vfile-statistics-1.1.3.tgz", - "integrity": "sha512-CstaK/ebTz1W3Qp41Bt9Lj/2DmumFsCwC2sKahDNSPh0mPh7/UyMLCoU8ZBX34CRU0d61B4W41yIFsV0NKMZeA==", - "dev": true - }, - "watch": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/watch/-/watch-1.0.2.tgz", - "integrity": "sha1-NApxe952Vyb6CqB9ch4BR6VR3ww=", - "dev": true, - "requires": { - "exec-sh": "^0.2.0", - "minimist": "^1.2.0" - } - }, - "weasel-words": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/weasel-words/-/weasel-words-0.1.1.tgz", - "integrity": "sha1-cTeUZYXHP+RIggE4U70ADF1oek4=", - "dev": true - }, - "which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - }, - "which-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", - "dev": true - }, - "wide-align": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", - "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", - "dev": true, - "requires": { - "string-width": "^1.0.2 || 2" - } - }, - "wordwrap": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", - "dev": true - }, - "wrap-ansi": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", - "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", - "dev": true, - "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - } - } - }, - "wrapped": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/wrapped/-/wrapped-1.0.1.tgz", - "integrity": "sha1-x4PZ2Aeyc+mwHoUWgKk4yHyQckI=", - "dev": true, - "requires": { - "co": "3.1.0", - "sliced": "^1.0.1" - } - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true - }, - "write": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/write/-/write-1.0.3.tgz", - "integrity": "sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==", - "dev": true, - "requires": { - "mkdirp": "^0.5.1" - } - }, - "write-good": { - "version": "0.11.3", - "resolved": "https://registry.npmjs.org/write-good/-/write-good-0.11.3.tgz", - "integrity": "sha512-fDKIHO5wCzTLCOGNJl1rzzJrZlTIzfZl8msOoJQZzRhYo0X/tFTm4+2B1zTibFYK01Nnd1kLZBjj4xjcFLePNQ==", - "dev": true, - "requires": { - "adverb-where": "0.0.9", - "e-prime": "^0.10.2", - "no-cliches": "^0.1.0", - "object.assign": "^4.0.4", - "passive-voice": "^0.1.0", - "too-wordy": "^0.1.4", - "weasel-words": "^0.1.1" - } - }, - "x-is-string": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/x-is-string/-/x-is-string-0.1.0.tgz", - "integrity": "sha1-R0tQhlrzpJqcRlfwWs0UVFj3fYI=", - "dev": true - }, - "xml-escape": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/xml-escape/-/xml-escape-1.1.0.tgz", - "integrity": "sha1-OQTBQ/qOs6ADDsZG0pAqLxtwbEQ=", - "dev": true - }, - "xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "dev": true - }, - "y18n": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", - "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", - "dev": true - }, - "yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", - "dev": true - }, - "yargs": { - "version": "13.2.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.2.2.tgz", - "integrity": "sha512-WyEoxgyTD3w5XRpAQNYUB9ycVH/PQrToaTXdYXRdOXvEy1l19br+VJsc0vcO8PTGg5ro/l/GY7F/JMEBmI0BxA==", - "dev": true, - "requires": { - "cliui": "^4.0.0", - "find-up": "^3.0.0", - "get-caller-file": "^2.0.1", - "os-locale": "^3.1.0", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^3.0.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^13.0.0" - }, - "dependencies": { - "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 - }, - "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" - } - }, - "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" - } - } - } - }, - "yargs-parser": { - "version": "13.0.0", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.0.0.tgz", - "integrity": "sha512-w2LXjoL8oRdRQN+hOyppuXs+V/fVAYtpcrRxZuF7Kt/Oc+Jr2uAcVntaUTNT6w5ihoWfFDpNY8CPx1QskxZ/pw==", - "dev": true, - "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } - }, - "yargs-unparser": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-1.5.0.tgz", - "integrity": "sha512-HK25qidFTCVuj/D1VfNiEndpLIeJN78aqgR23nL3y4N0U/91cOAzqfHlF8n2BvoNDcZmJKin3ddNSvOxSr8flw==", - "dev": true, - "requires": { - "flat": "^4.1.0", - "lodash": "^4.17.11", - "yargs": "^12.0.5" - }, - "dependencies": { - "get-caller-file": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", - "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", - "dev": true - }, - "require-main-filename": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", - "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", - "dev": true - }, - "yargs": { - "version": "12.0.5", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.5.tgz", - "integrity": "sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw==", - "dev": true, - "requires": { - "cliui": "^4.0.0", - "decamelize": "^1.2.0", - "find-up": "^3.0.0", - "get-caller-file": "^1.0.1", - "os-locale": "^3.0.0", - "require-directory": "^2.1.1", - "require-main-filename": "^1.0.1", - "set-blocking": "^2.0.0", - "string-width": "^2.0.0", - "which-module": "^2.0.0", - "y18n": "^3.2.1 || ^4.0.0", - "yargs-parser": "^11.1.1" - } - }, - "yargs-parser": { - "version": "11.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-11.1.1.tgz", - "integrity": "sha512-C6kB/WJDiaxONLJQnF8ccx9SEeoTTLek8RVbaOIsrAUS8VrBEXfmeSnCZxygc+XC2sNMBIwOOnfcxiynjHsVSQ==", - "dev": true, - "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } - } - } - } - } -} From fe6f3dc2590bca966240e65fb9fd6b151d97ae53 Mon Sep 17 00:00:00 2001 From: Jason Fox Date: Wed, 26 Feb 2020 23:13:45 +0000 Subject: [PATCH 11/27] Re-add CNR --- CHANGES_NEXT_RELEASE | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGES_NEXT_RELEASE b/CHANGES_NEXT_RELEASE index cd1bf1039..e3b8a276e 100644 --- a/CHANGES_NEXT_RELEASE +++ b/CHANGES_NEXT_RELEASE @@ -1,3 +1,6 @@ +Replace jshint with eslint +Add prettier code formatting +Add husky and lint-staged Refresh Documentation Add NGSIv2 metadata support to device provisioned attributes Fix: Error message when sending measures with unknown/undefined attribute From 14e64a00793d3e358e57dd11a1b0c8e87de1cb57 Mon Sep 17 00:00:00 2001 From: Jason Fox Date: Mon, 22 Jun 2020 18:02:55 +0200 Subject: [PATCH 12/27] Remove package lock --- package-lock.json | 8552 --------------------------------------------- 1 file changed, 8552 deletions(-) delete mode 100644 package-lock.json diff --git a/package-lock.json b/package-lock.json deleted file mode 100644 index f95e76278..000000000 --- a/package-lock.json +++ /dev/null @@ -1,8552 +0,0 @@ -{ - "name": "iotagent-node-lib", - "version": "2.12.0-next", - "lockfileVersion": 1, - "requires": true, - "dependencies": { - "@azu/format-text": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@azu/format-text/-/format-text-1.0.1.tgz", - "integrity": "sha1-aWc1CpRkD2sChVFpvYl85U1s6+I=", - "dev": true - }, - "@azu/style-format": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@azu/style-format/-/style-format-1.0.0.tgz", - "integrity": "sha1-5wGH+Khi4ZGxvObAJo8TrNOlayA=", - "dev": true, - "requires": { - "@azu/format-text": "^1.0.1" - } - }, - "@babel/code-frame": { - "version": "7.10.3", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.3.tgz", - "integrity": "sha512-fDx9eNW0qz0WkUeqL6tXEXzVlPh6Y5aCDEZesl0xBGA8ndRukX91Uk44ZqnkECp01NAZUdCAl+aiQNGi0k88Eg==", - "dev": true, - "requires": { - "@babel/highlight": "^7.10.3" - } - }, - "@babel/helper-validator-identifier": { - "version": "7.10.3", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.3.tgz", - "integrity": "sha512-bU8JvtlYpJSBPuj1VUmKpFGaDZuLxASky3LhaKj3bmpSTY6VWooSM8msk+Z0CZoErFye2tlABF6yDkT3FOPAXw==", - "dev": true - }, - "@babel/highlight": { - "version": "7.10.3", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.3.tgz", - "integrity": "sha512-Ih9B/u7AtgEnySE2L2F0Xm0GaM729XqqLfHkalTsbjXGyqmf/6M0Cu0WpvqueUlW+xk88BHw9Nkpj49naU+vWw==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.10.3", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - } - }, - "@samverschueren/stream-to-observable": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@samverschueren/stream-to-observable/-/stream-to-observable-0.3.0.tgz", - "integrity": "sha512-MI4Xx6LHs4Webyvi6EbspgyAb4D2Q2VtnCQ1blOJcoLS6mVa8lNN2rkIy1CVxfTUpoyIbCTkXES1rLXztFD1lg==", - "dev": true, - "requires": { - "any-observable": "^0.3.0" - } - }, - "@sinonjs/commons": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.0.tgz", - "integrity": "sha512-wEj54PfsZ5jGSwMX68G8ZXFawcSglQSXqCftWX3ec8MDUzQdHgcKvw97awHbY0efQEL5iKUOAmmVtoYgmrSG4Q==", - "dev": true, - "requires": { - "type-detect": "4.0.8" - } - }, - "@sinonjs/fake-timers": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-6.0.1.tgz", - "integrity": "sha512-MZPUxrmFubI36XS1DI3qmI0YdN1gks62JtFZvxR67ljjSNCeK6U08Zx4msEWOXuofgqUt6zPHSi1H9fbjR/NRA==", - "dev": true, - "requires": { - "@sinonjs/commons": "^1.7.0" - } - }, - "@sinonjs/formatio": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@sinonjs/formatio/-/formatio-5.0.1.tgz", - "integrity": "sha512-KaiQ5pBf1MpS09MuA0kp6KBQt2JUOQycqVG1NZXvzeaXe5LGFqAKueIS0bw4w0P9r7KuBSVdUk5QjXsUdu2CxQ==", - "dev": true, - "requires": { - "@sinonjs/commons": "^1", - "@sinonjs/samsam": "^5.0.2" - } - }, - "@sinonjs/samsam": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-5.0.3.tgz", - "integrity": "sha512-QucHkc2uMJ0pFGjJUDP3F9dq5dx8QIaqISl9QgwLOh6P9yv877uONPGXh/OH/0zmM3tW1JjuJltAZV2l7zU+uQ==", - "dev": true, - "requires": { - "@sinonjs/commons": "^1.6.0", - "lodash.get": "^4.4.2", - "type-detect": "^4.0.8" - } - }, - "@sinonjs/text-encoding": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.1.tgz", - "integrity": "sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==", - "dev": true - }, - "@textlint/ast-node-types": { - "version": "4.2.5", - "resolved": "https://registry.npmjs.org/@textlint/ast-node-types/-/ast-node-types-4.2.5.tgz", - "integrity": "sha512-+rEx4jLOeZpUcdvll7jEg/7hNbwYvHWFy4IGW/tk2JdbyB3SJVyIP6arAwzTH/sp/pO9jftfyZnRj4//sLbLvQ==", - "dev": true - }, - "@textlint/ast-tester": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/@textlint/ast-tester/-/ast-tester-2.1.6.tgz", - "integrity": "sha512-i+UrSKZXs561g8LXsCBkgpNYkgBS3T3Pif2/+DraZmSKpQ2r2D1yCOdH82IGPWWpQ/GMSg6Z0qpLJpjnYz+bpg==", - "dev": true, - "requires": { - "@textlint/ast-node-types": "^4.2.5" - } - }, - "@textlint/ast-traverse": { - "version": "2.1.7", - "resolved": "https://registry.npmjs.org/@textlint/ast-traverse/-/ast-traverse-2.1.7.tgz", - "integrity": "sha512-73Nw0R4TaskPmF36Hop1DZ8AbH339WrGiLQjzbOLaXHaBHQ4hdNw28UMlw4glfPZb7/zvxPcJRtg9AB8F3ZW0g==", - "dev": true, - "requires": { - "@textlint/ast-node-types": "^4.2.5" - } - }, - "@textlint/feature-flag": { - "version": "3.1.6", - "resolved": "https://registry.npmjs.org/@textlint/feature-flag/-/feature-flag-3.1.6.tgz", - "integrity": "sha512-R2s027/WG3zhCMHZG79OhRFmkSL2ghwvFYg/W+2VUva5aYC8i9yeuwRyWt7m83tP1qlI+bq7j3S04fyn6yNheg==", - "dev": true, - "requires": { - "map-like": "^2.0.0" - } - }, - "@textlint/fixer-formatter": { - "version": "3.1.13", - "resolved": "https://registry.npmjs.org/@textlint/fixer-formatter/-/fixer-formatter-3.1.13.tgz", - "integrity": "sha512-FXqAJZ+5fLsOZjvFmn1JhCer8gQI4ZQk3R45bXizRJm6DASByPAGGh/MAQxxHSGeR5wR8miO/koxA2BrS8OhAw==", - "dev": true, - "requires": { - "@textlint/module-interop": "^1.0.2", - "@textlint/types": "^1.3.1", - "chalk": "^1.1.3", - "debug": "^4.1.1", - "diff": "^4.0.1", - "is-file": "^1.0.0", - "string-width": "^1.0.1", - "strip-ansi": "^6.0.0", - "text-table": "^0.2.0", - "try-resolve": "^1.0.1" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - }, - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - }, - "dependencies": { - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - } - } - }, - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - }, - "dependencies": { - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - } - } - }, - "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" - }, - "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 - } - } - }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - } - } - }, - "@textlint/kernel": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/@textlint/kernel/-/kernel-3.2.1.tgz", - "integrity": "sha512-gMCgP/tAjCX8dGqgu7nhUwaDC/TzDKeRZb9qa50nqbnILRasKplj3lOWn2osZdkScVZPLQp+al1pDh9pU4D+Dw==", - "dev": true, - "requires": { - "@textlint/ast-node-types": "^4.2.5", - "@textlint/ast-tester": "^2.1.6", - "@textlint/ast-traverse": "^2.1.7", - "@textlint/feature-flag": "^3.1.6", - "@textlint/types": "^1.3.1", - "@textlint/utils": "^1.0.3", - "debug": "^4.1.1", - "deep-equal": "^1.1.0", - "map-like": "^2.0.0", - "structured-source": "^3.0.2" - }, - "dependencies": { - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "deep-equal": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.1.tgz", - "integrity": "sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g==", - "dev": true, - "requires": { - "is-arguments": "^1.0.4", - "is-date-object": "^1.0.1", - "is-regex": "^1.0.4", - "object-is": "^1.0.1", - "object-keys": "^1.1.1", - "regexp.prototype.flags": "^1.2.0" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - } - } - }, - "@textlint/linter-formatter": { - "version": "3.1.12", - "resolved": "https://registry.npmjs.org/@textlint/linter-formatter/-/linter-formatter-3.1.12.tgz", - "integrity": "sha512-OEP4pklu01MEgBJrftD9vwe3HFx+jhiEe1JFIgf7GZ4a0fSer5vQWXBo5wHW6WtZtSa+iLBsLC3mI5VMeshzdA==", - "dev": true, - "requires": { - "@azu/format-text": "^1.0.1", - "@azu/style-format": "^1.0.0", - "@textlint/module-interop": "^1.0.2", - "@textlint/types": "^1.3.1", - "chalk": "^1.0.0", - "concat-stream": "^1.5.1", - "debug": "^4.1.1", - "is-file": "^1.0.0", - "js-yaml": "^3.2.4", - "optionator": "^0.8.1", - "pluralize": "^2.0.0", - "string-width": "^1.0.1", - "string.prototype.padstart": "^3.0.0", - "strip-ansi": "^6.0.0", - "table": "^3.7.8", - "text-table": "^0.2.0", - "try-resolve": "^1.0.1", - "xml-escape": "^1.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - }, - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - }, - "dependencies": { - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - } - } - }, - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - }, - "dependencies": { - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - } - } - }, - "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" - }, - "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 - } - } - }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - } - } - }, - "@textlint/markdown-to-ast": { - "version": "6.1.7", - "resolved": "https://registry.npmjs.org/@textlint/markdown-to-ast/-/markdown-to-ast-6.1.7.tgz", - "integrity": "sha512-B0QtokeQR4a9+4q0NQr8T9l7A1fFihTN5Ze57tVgqW+3ymzXEouh8DvPHeNQ4T6jEkAThvdjk95mxAMpGRJ79w==", - "dev": true, - "requires": { - "@textlint/ast-node-types": "^4.2.5", - "debug": "^4.1.1", - "remark-frontmatter": "^1.2.0", - "remark-parse": "^5.0.0", - "structured-source": "^3.0.2", - "traverse": "^0.6.6", - "unified": "^6.1.6" - }, - "dependencies": { - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "remark-parse": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-5.0.0.tgz", - "integrity": "sha512-b3iXszZLH1TLoyUzrATcTQUZrwNl1rE70rVdSruJFlDaJ9z5aMkhrG43Pp68OgfHndL/ADz6V69Zow8cTQu+JA==", - "dev": true, - "requires": { - "collapse-white-space": "^1.0.2", - "is-alphabetical": "^1.0.0", - "is-decimal": "^1.0.0", - "is-whitespace-character": "^1.0.0", - "is-word-character": "^1.0.0", - "markdown-escapes": "^1.0.0", - "parse-entities": "^1.1.0", - "repeat-string": "^1.5.4", - "state-toggle": "^1.0.0", - "trim": "0.0.1", - "trim-trailing-lines": "^1.0.0", - "unherit": "^1.0.4", - "unist-util-remove-position": "^1.0.0", - "vfile-location": "^2.0.0", - "xtend": "^4.0.1" - } - }, - "unified": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/unified/-/unified-6.2.0.tgz", - "integrity": "sha512-1k+KPhlVtqmG99RaTbAv/usu85fcSRu3wY8X+vnsEhIxNP5VbVIDiXnLqyKIG+UMdyTg0ZX9EI6k2AfjJkHPtA==", - "dev": true, - "requires": { - "bail": "^1.0.0", - "extend": "^3.0.0", - "is-plain-obj": "^1.1.0", - "trough": "^1.0.0", - "vfile": "^2.0.0", - "x-is-string": "^0.1.0" - } - }, - "unist-util-stringify-position": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-1.1.2.tgz", - "integrity": "sha512-pNCVrk64LZv1kElr0N1wPiHEUoXNVFERp+mlTg/s9R5Lwg87f9bM/3sQB99w+N9D/qnM9ar3+AKDBwo/gm/iQQ==", - "dev": true - }, - "vfile": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/vfile/-/vfile-2.3.0.tgz", - "integrity": "sha512-ASt4mBUHcTpMKD/l5Q+WJXNtshlWxOogYyGYYrg4lt/vuRjC1EFQtlAofL5VmtVNIZJzWYFJjzGWZ0Gw8pzW1w==", - "dev": true, - "requires": { - "is-buffer": "^1.1.4", - "replace-ext": "1.0.0", - "unist-util-stringify-position": "^1.0.0", - "vfile-message": "^1.0.0" - } - }, - "vfile-message": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-1.1.1.tgz", - "integrity": "sha512-1WmsopSGhWt5laNir+633LszXvZ+Z/lxveBf6yhGsqnQIhlhzooZae7zV6YVM1Sdkw68dtAW3ow0pOdPANugvA==", - "dev": true, - "requires": { - "unist-util-stringify-position": "^1.1.1" - } - } - } - }, - "@textlint/module-interop": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@textlint/module-interop/-/module-interop-1.0.2.tgz", - "integrity": "sha512-qQ6dqlg4SYywCywimIbkveQZu1MG6ugf6fcJuWDi3D51FbdkSRsMrPusJ1YoW6Y3XBp0ww9fJjXWtlUStGeQsw==", - "dev": true - }, - "@textlint/text-to-ast": { - "version": "3.1.7", - "resolved": "https://registry.npmjs.org/@textlint/text-to-ast/-/text-to-ast-3.1.7.tgz", - "integrity": "sha512-CBAEQmiEa2G/wonlLr1HgUtXfTSas6OGGvYGRIRMJweNh5Ilhbz2nM2/9XQMfLQbdn5pGYrAAAQRB2+/9fZ31A==", - "dev": true, - "requires": { - "@textlint/ast-node-types": "^4.2.5" - } - }, - "@textlint/textlint-plugin-markdown": { - "version": "5.1.12", - "resolved": "https://registry.npmjs.org/@textlint/textlint-plugin-markdown/-/textlint-plugin-markdown-5.1.12.tgz", - "integrity": "sha512-CJWWTaomR22hQD3ogrZujMH1pNN7DqZadmx9CJXxgKwpI/cuD5d2kClwXO3MeLFckJr5HRso7SFN5ebqKu1ycw==", - "dev": true, - "requires": { - "@textlint/markdown-to-ast": "^6.1.7" - } - }, - "@textlint/textlint-plugin-text": { - "version": "4.1.13", - "resolved": "https://registry.npmjs.org/@textlint/textlint-plugin-text/-/textlint-plugin-text-4.1.13.tgz", - "integrity": "sha512-KQfSYNDt8HSX8ZL/r86N8OrAuQ9LEuevAtGomtfkw0h7Ed/pUfmuYXjht8wYRdysYBa4JyjrXcmqzRAUdkWrag==", - "dev": true, - "requires": { - "@textlint/text-to-ast": "^3.1.7" - } - }, - "@textlint/types": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@textlint/types/-/types-1.3.1.tgz", - "integrity": "sha512-9MJ6PRPYWiFs2lfvp/Qhq72WrkZLL5ncBUXAVoj1Ug17ug8d7psmr/KJstMMocW3EWHSOuIDj7unh413c3jPqQ==", - "dev": true, - "requires": { - "@textlint/ast-node-types": "^4.2.5" - } - }, - "@textlint/utils": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@textlint/utils/-/utils-1.0.3.tgz", - "integrity": "sha512-6oGaBKXYpg5Ooph5p32OFdp1dXDUC1z5mpHg2gmQbx6QZjmP4QX+ygBQdNoCq15d1w88+We6koJl0n0WXjItYw==", - "dev": true - }, - "@types/bluebird": { - "version": "3.5.29", - "resolved": "https://registry.npmjs.org/@types/bluebird/-/bluebird-3.5.29.tgz", - "integrity": "sha512-kmVtnxTuUuhCET669irqQmPAez4KFnFVKvpleVRyfC3g+SHD1hIkFZcWLim9BVcwUBLO59o8VZE4yGCmTif8Yw==", - "dev": true - }, - "@types/node": { - "version": "13.7.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-13.7.0.tgz", - "integrity": "sha512-GnZbirvmqZUzMgkFn70c74OQpTTUcCzlhQliTzYjQMqg+hVKcDnxdL19Ne3UdYzdMA/+W3eb646FWn/ZaT1NfQ==", - "dev": true - }, - "@types/unist": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.3.tgz", - "integrity": "sha512-FvUupuM3rlRsRtCN+fDudtmytGO6iHJuuRKS1Ss0pG5z8oX0diNEw94UEL7hgDbpN94rgaK5R7sWm6RrSkZuAQ==", - "dev": true - }, - "@types/vfile": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@types/vfile/-/vfile-3.0.2.tgz", - "integrity": "sha512-b3nLFGaGkJ9rzOcuXRfHkZMdjsawuDD0ENL9fzTophtBg8FJHSGbH7daXkEpcwy3v7Xol3pAvsmlYyFhR4pqJw==", - "dev": true, - "requires": { - "@types/node": "*", - "@types/unist": "*", - "@types/vfile-message": "*" - } - }, - "@types/vfile-message": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@types/vfile-message/-/vfile-message-2.0.0.tgz", - "integrity": "sha512-GpTIuDpb9u4zIO165fUy9+fXcULdD8HFRNli04GehoMVbeNq7D6OBnqSmg3lxZnC+UvgUhEWKxdKiwYUkGltIw==", - "dev": true, - "requires": { - "vfile-message": "*" - } - }, - "JSONSelect": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/JSONSelect/-/JSONSelect-0.4.0.tgz", - "integrity": "sha1-oI7cxn6z/L6Z7WMIVTRKDPKCu40=" - }, - "JSV": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/JSV/-/JSV-4.0.2.tgz", - "integrity": "sha1-0Hf2glVx+CEy+d/67Vh7QCn+/1c=" - }, - "abbrev": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz", - "integrity": "sha1-kbR5JYinc4wl813W9jdSovh3YTU=", - "dev": true - }, - "accepts": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz", - "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=", - "requires": { - "mime-types": "~2.1.18", - "negotiator": "0.6.1" - } - }, - "acorn": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.1.tgz", - "integrity": "sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA==", - "dev": true - }, - "acorn-jsx": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.2.0.tgz", - "integrity": "sha512-HiUX/+K2YpkpJ+SzBffkM/AQ2YE03S0U1kjTLVpoJdhZMOWy8qvXVN9JdLqv2QsaQ6MPYQIuNmwD8zOiYUofLQ==", - "dev": true - }, - "adverb-where": { - "version": "0.0.9", - "resolved": "https://registry.npmjs.org/adverb-where/-/adverb-where-0.0.9.tgz", - "integrity": "sha1-CcXN3Y1QO5/l924LjcXHCo8ZPjQ=", - "dev": true - }, - "ajv": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.7.0.tgz", - "integrity": "sha512-RZXPviBTtfmtka9n9sy1N5M5b82CbxWIR6HIis4s3WQTXDJamc/0gpCWNGz6EWdWp4DOfjzJfhz/AS9zVPjjWg==", - "requires": { - "fast-deep-equal": "^2.0.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "ajv-keywords": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-1.5.1.tgz", - "integrity": "sha1-MU3QpLM2j609/NxU7eYXG4htrzw=", - "dev": true - }, - "amdefine": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", - "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", - "optional": true - }, - "ansi-colors": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.3.tgz", - "integrity": "sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw==", - "dev": true - }, - "ansi-escapes": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", - "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", - "dev": true - }, - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "any-observable": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/any-observable/-/any-observable-0.3.0.tgz", - "integrity": "sha512-/FQM1EDkTsf63Ub2C6O7GuYFDsSXUwsaZDurV0np41ocwq0jthUAYCmhBX9f+KwlaCgIuWyr/4WlUQUBfKfZog==", - "dev": true - }, - "anymatch": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", - "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", - "dev": true, - "requires": { - "micromatch": "^3.1.4", - "normalize-path": "^2.1.1" - }, - "dependencies": { - "normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "dev": true, - "requires": { - "remove-trailing-separator": "^1.0.1" - } - } - } - }, - "argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "requires": { - "sprintf-js": "~1.0.2" - } - }, - "arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", - "dev": true - }, - "arr-flatten": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", - "dev": true - }, - "arr-union": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", - "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", - "dev": true - }, - "array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" - }, - "array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", - "dev": true - }, - "asn1": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", - "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", - "requires": { - "safer-buffer": "~2.1.0" - } - }, - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" - }, - "assertion-error": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", - "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", - "dev": true - }, - "assign-symbols": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", - "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", - "dev": true - }, - "astral-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", - "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", - "dev": true - }, - "async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.2.tgz", - "integrity": "sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg==", - "requires": { - "lodash": "^4.17.11" - } - }, - "async-each": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz", - "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==", - "dev": true - }, - "asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" - }, - "atob": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", - "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", - "dev": true - }, - "aws-sign2": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" - }, - "aws4": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", - "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==" - }, - "bail": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/bail/-/bail-1.0.5.tgz", - "integrity": "sha512-xFbRxM1tahm08yHBP16MMjVUAvDaBMD38zsM9EMAUN61omwLmKlOpB/Zku5QkjZ8TZ4vn53pj+t518cH0S03RQ==", - "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 - }, - "base": { - "version": "0.11.2", - "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", - "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", - "dev": true, - "requires": { - "cache-base": "^1.0.1", - "class-utils": "^0.3.5", - "component-emitter": "^1.2.1", - "define-property": "^1.0.0", - "isobject": "^3.0.1", - "mixin-deep": "^1.2.0", - "pascalcase": "^0.1.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } - } - }, - "bcrypt-pbkdf": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", - "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", - "requires": { - "tweetnacl": "^0.14.3" - } - }, - "binary-extensions": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", - "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", - "dev": true - }, - "bindings": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", - "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", - "dev": true, - "optional": true, - "requires": { - "file-uri-to-path": "1.0.0" - } - }, - "bluebird": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz", - "integrity": "sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA==" - }, - "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" - }, - "dependencies": { - "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" - } - }, - "mime-db": { - "version": "1.40.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz", - "integrity": "sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA==" - }, - "mime-types": { - "version": "2.1.24", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz", - "integrity": "sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==", - "requires": { - "mime-db": "1.40.0" - } - }, - "qs": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", - "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==" - }, - "setprototypeof": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", - "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" - }, - "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" - } - } - } - }, - "boundary": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/boundary/-/boundary-1.0.1.tgz", - "integrity": "sha1-TWfcJgLAzBbdm85+v4fpSCkPWBI=", - "dev": true - }, - "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": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "dev": true, - "requires": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "browser-stdout": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", - "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", - "dev": true - }, - "bson": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/bson/-/bson-1.1.1.tgz", - "integrity": "sha512-jCGVYLoYMHDkOsbwJZBCqwMHyH4c+wzgI9hG7Z6SZJRXWr+x58pdIbm2i9a/jFGCkRJqRUr8eoI7lDWa0hTkxg==" - }, - "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==" - }, - "cache-base": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", - "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", - "dev": true, - "requires": { - "collection-visit": "^1.0.0", - "component-emitter": "^1.2.1", - "get-value": "^2.0.6", - "has-value": "^1.0.0", - "isobject": "^3.0.1", - "set-value": "^2.0.0", - "to-object-path": "^0.3.0", - "union-value": "^1.0.0", - "unset-value": "^1.0.0" - } - }, - "caller-callsite": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/caller-callsite/-/caller-callsite-2.0.0.tgz", - "integrity": "sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ=", - "dev": true, - "requires": { - "callsites": "^2.0.0" - }, - "dependencies": { - "callsites": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz", - "integrity": "sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA=", - "dev": true - } - } - }, - "caller-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-2.0.0.tgz", - "integrity": "sha1-Ro+DBE42mrIBD6xfBs7uFbsssfQ=", - "dev": true, - "requires": { - "caller-callsite": "^2.0.0" - } - }, - "callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "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 - }, - "caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" - }, - "ccount": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/ccount/-/ccount-1.0.5.tgz", - "integrity": "sha512-MOli1W+nfbPLlKEhInaxhRdp7KVLFxLN5ykwzHgLsLI3H3gs5jjFAK4Eoj3OzzcxCtumDaI8onoVDeQyWaNTkw==", - "dev": true - }, - "chai": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/chai/-/chai-4.2.0.tgz", - "integrity": "sha512-XQU3bhBukrOsQCuwZndwGcCVQHyZi53fQ6Ys1Fym7E4olpIqqZZhhoFJoaKVvV17lWQoXYwgWN2nF5crA8J2jw==", - "dev": true, - "requires": { - "assertion-error": "^1.1.0", - "check-error": "^1.0.2", - "deep-eql": "^3.0.1", - "get-func-name": "^2.0.0", - "pathval": "^1.1.0", - "type-detect": "^4.0.5" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "dependencies": { - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "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" - } - } - } - }, - "character-entities": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-1.2.4.tgz", - "integrity": "sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw==", - "dev": true - }, - "character-entities-html4": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-1.1.4.tgz", - "integrity": "sha512-HRcDxZuZqMx3/a+qrzxdBKBPUpxWEq9xw2OPZ3a/174ihfrQKVsFhqtthBInFy1zZ9GgZyFXOatNujm8M+El3g==", - "dev": true - }, - "character-entities-legacy": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-1.1.4.tgz", - "integrity": "sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA==", - "dev": true - }, - "character-reference-invalid": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-1.1.4.tgz", - "integrity": "sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg==", - "dev": true - }, - "chardet": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", - "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", - "dev": true - }, - "charenc": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz", - "integrity": "sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc=", - "dev": true - }, - "check-error": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", - "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", - "dev": true - }, - "chokidar": { - "version": "2.1.8", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", - "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", - "dev": true, - "requires": { - "anymatch": "^2.0.0", - "async-each": "^1.0.1", - "braces": "^2.3.2", - "fsevents": "^1.2.7", - "glob-parent": "^3.1.0", - "inherits": "^2.0.3", - "is-binary-path": "^1.0.0", - "is-glob": "^4.0.0", - "normalize-path": "^3.0.0", - "path-is-absolute": "^1.0.0", - "readdirp": "^2.2.1", - "upath": "^1.1.1" - } - }, - "ci-info": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-1.6.0.tgz", - "integrity": "sha512-vsGdkwSCDpWmP80ncATX7iea5DWQemg1UgCW5J8tqjU3lYw4FBYuj89J0CTVomA7BEfvSZd84GmHko+MxFQU2A==", - "dev": true - }, - "cjson": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/cjson/-/cjson-0.3.0.tgz", - "integrity": "sha1-5kObkHA9MS/24iJAl76pLOPQKhQ=", - "requires": { - "jsonlint": "1.6.0" - } - }, - "class-utils": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", - "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", - "dev": true, - "requires": { - "arr-union": "^3.1.0", - "define-property": "^0.2.5", - "isobject": "^3.0.0", - "static-extend": "^0.1.1" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - } - } - }, - "cli-cursor": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", - "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", - "dev": true, - "requires": { - "restore-cursor": "^2.0.0" - } - }, - "cli-truncate": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-0.2.1.tgz", - "integrity": "sha1-nxXPuwcFAFNpIWxiasfQWrkN1XQ=", - "dev": true, - "requires": { - "slice-ansi": "0.0.4", - "string-width": "^1.0.1" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - } - } - }, - "cli-width": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.1.tgz", - "integrity": "sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw==", - "dev": true - }, - "cliui": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", - "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", - "dev": true, - "requires": { - "string-width": "^2.1.1", - "strip-ansi": "^4.0.0", - "wrap-ansi": "^2.0.0" - } - }, - "co": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/co/-/co-3.1.0.tgz", - "integrity": "sha1-TqVOpaCJOBUxheFSEMaNkJK8G3g=", - "dev": true - }, - "code-point-at": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", - "dev": true - }, - "collapse-white-space": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-1.0.6.tgz", - "integrity": "sha512-jEovNnrhMuqyCcjfEJA56v0Xq8SkIoPKDyaHahwo3POf4qcSXqMYuwNcOTzp74vTsR9Tn08z4MxWqAhcekogkQ==", - "dev": true - }, - "collection-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", - "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", - "dev": true, - "requires": { - "map-visit": "^1.0.0", - "object-visit": "^1.0.0" - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, - "colors": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/colors/-/colors-0.5.1.tgz", - "integrity": "sha1-fQAj6usVTo7p/Oddy5I9DtFmd3Q=" - }, - "combined-stream": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz", - "integrity": "sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w==", - "requires": { - "delayed-stream": "~1.0.0" - } - }, - "command-shell-lib": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/command-shell-lib/-/command-shell-lib-1.0.0.tgz", - "integrity": "sha1-KWC3MJvpBwojAYYjcvvjjtL3+RA=", - "requires": { - "async": "*" - } - }, - "commander": { - "version": "2.20.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.0.tgz", - "integrity": "sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==", - "dev": true - }, - "component-emitter": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", - "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", - "dev": true - }, - "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 - }, - "concat-stream": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", - "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", - "dev": true, - "requires": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^2.2.2", - "typedarray": "^0.0.6" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "content-disposition": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", - "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ=" - }, - "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.3.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", - "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=" - }, - "cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" - }, - "copy-descriptor": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", - "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", - "dev": true - }, - "core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" - }, - "cosmiconfig": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.1.tgz", - "integrity": "sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==", - "dev": true, - "requires": { - "import-fresh": "^2.0.0", - "is-directory": "^0.3.1", - "js-yaml": "^3.13.1", - "parse-json": "^4.0.0" - }, - "dependencies": { - "import-fresh": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz", - "integrity": "sha1-2BNVwVYS04bGH53dOSLUMEgipUY=", - "dev": true, - "requires": { - "caller-path": "^2.0.0", - "resolve-from": "^3.0.0" - } - }, - "resolve-from": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", - "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", - "dev": true - } - } - }, - "coveralls": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/coveralls/-/coveralls-3.0.3.tgz", - "integrity": "sha512-viNfeGlda2zJr8Gj1zqXpDMRjw9uM54p7wzZdvLRyOgnAfCe974Dq4veZkjJdxQXbmdppu6flEajFYseHYaUhg==", - "dev": true, - "requires": { - "growl": "~> 1.10.0", - "js-yaml": "^3.11.0", - "lcov-parse": "^0.0.10", - "log-driver": "^1.2.7", - "minimist": "^1.2.0", - "request": "^2.86.0" - } - }, - "cross-spawn": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", - "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", - "dev": true, - "requires": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - } - }, - "crypt": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz", - "integrity": "sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs=", - "dev": true - }, - "dashdash": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", - "requires": { - "assert-plus": "^1.0.0" - } - }, - "date-fns": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-1.30.1.tgz", - "integrity": "sha512-hBSVCvSmWC+QypYObzwGOd9wqdDpOt+0wl0KbU+R+uuZBS1jN8VsD1ss3irQDknRj5NvxiTF6oj/nDRnN/UQNw==", - "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" - } - }, - "decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", - "dev": true - }, - "decode-uri-component": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", - "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=" - }, - "dedent": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", - "integrity": "sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw=", - "dev": true - }, - "deep-eql": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", - "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", - "dev": true, - "requires": { - "type-detect": "^4.0.0" - } - }, - "deep-equal": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz", - "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=", - "dev": true - }, - "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 - }, - "deep-is": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", - "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", - "dev": true - }, - "define-properties": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", - "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", - "dev": true, - "requires": { - "object-keys": "^1.0.12" - } - }, - "define-property": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", - "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", - "dev": true, - "requires": { - "is-descriptor": "^1.0.2", - "isobject": "^3.0.1" - }, - "dependencies": { - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } - } - }, - "delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" - }, - "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": "3.5.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", - "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", - "dev": true - }, - "doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "requires": { - "esutils": "^2.0.2" - }, - "dependencies": { - "esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true - } - } - }, - "e-prime": { - "version": "0.10.3", - "resolved": "https://registry.npmjs.org/e-prime/-/e-prime-0.10.3.tgz", - "integrity": "sha512-QGKWEWRVUfjUXSoio9AW43RzzMQzI23No8uyKQD9yZJm4Hbc+8ZRZhyEtWdnpAkY7dXFmTxtcFR4cM0T0U1jGw==", - "dev": true - }, - "ebnf-parser": { - "version": "0.1.10", - "resolved": "https://registry.npmjs.org/ebnf-parser/-/ebnf-parser-0.1.10.tgz", - "integrity": "sha1-zR9rpHfFY4xAyX7ZtXLbW6tdgzE=" - }, - "ecc-jsbn": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", - "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", - "requires": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" - } - }, - "ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" - }, - "elegant-spinner": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/elegant-spinner/-/elegant-spinner-1.0.1.tgz", - "integrity": "sha1-2wQ1IcldfjA/2PNFvtwzSc+wcp4=", - "dev": true - }, - "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.1", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", - "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", - "dev": true, - "requires": { - "once": "^1.4.0" - } - }, - "error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, - "requires": { - "is-arrayish": "^0.2.1" - } - }, - "es-abstract": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.13.0.tgz", - "integrity": "sha512-vDZfg/ykNxQVwup/8E1BZhVzFfBxs9NqMzGcvIJrqg5k2/5Za2bWo40dK2J1pgLngZ7c+Shh8lwYtLGyrwPutg==", - "dev": true, - "requires": { - "es-to-primitive": "^1.2.0", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "is-callable": "^1.1.4", - "is-regex": "^1.0.4", - "object-keys": "^1.0.12" - } - }, - "es-to-primitive": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz", - "integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==", - "dev": true, - "requires": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - } - }, - "escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true - }, - "escodegen": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.3.3.tgz", - "integrity": "sha1-8CQBb1qI4Eb9EgBQVek5gC5sXyM=", - "requires": { - "esprima": "~1.1.1", - "estraverse": "~1.5.0", - "esutils": "~1.0.0", - "source-map": "~0.1.33" - } - }, - "eslint": { - "version": "5.16.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-5.16.0.tgz", - "integrity": "sha512-S3Rz11i7c8AA5JPv7xAH+dOyq/Cu/VXHiHXBPOU1k/JAM5dXqQPt3qcrhpHSorXmrpu2g0gkIBVXAqCpzfoZIg==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.0.0", - "ajv": "^6.9.1", - "chalk": "^2.1.0", - "cross-spawn": "^6.0.5", - "debug": "^4.0.1", - "doctrine": "^3.0.0", - "eslint-scope": "^4.0.3", - "eslint-utils": "^1.3.1", - "eslint-visitor-keys": "^1.0.0", - "espree": "^5.0.1", - "esquery": "^1.0.1", - "esutils": "^2.0.2", - "file-entry-cache": "^5.0.1", - "functional-red-black-tree": "^1.0.1", - "glob": "^7.1.2", - "globals": "^11.7.0", - "ignore": "^4.0.6", - "import-fresh": "^3.0.0", - "imurmurhash": "^0.1.4", - "inquirer": "^6.2.2", - "js-yaml": "^3.13.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.3.0", - "lodash": "^4.17.11", - "minimatch": "^3.0.4", - "mkdirp": "^0.5.1", - "natural-compare": "^1.4.0", - "optionator": "^0.8.2", - "path-is-inside": "^1.0.2", - "progress": "^2.0.0", - "regexpp": "^2.0.1", - "semver": "^5.5.1", - "strip-ansi": "^4.0.0", - "strip-json-comments": "^2.0.1", - "table": "^5.2.3", - "text-table": "^0.2.0" - }, - "dependencies": { - "ajv": { - "version": "6.12.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.2.tgz", - "integrity": "sha512-k+V+hzjm5q/Mr8ef/1Y9goCmlsK4I6Sm74teeyGvFk1XrOsbsKLjEdrvny42CZ+a8sXbk8KWpY/bDwS+FLL2UQ==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "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 - }, - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true - }, - "fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true - }, - "glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "ignore": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", - "dev": true - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "slice-ansi": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz", - "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.0", - "astral-regex": "^1.0.0", - "is-fullwidth-code-point": "^2.0.0" - } - }, - "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" - }, - "dependencies": { - "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 - }, - "table": { - "version": "5.4.6", - "resolved": "https://registry.npmjs.org/table/-/table-5.4.6.tgz", - "integrity": "sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug==", - "dev": true, - "requires": { - "ajv": "^6.10.2", - "lodash": "^4.17.14", - "slice-ansi": "^2.1.0", - "string-width": "^3.0.0" - }, - "dependencies": { - "lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", - "dev": true - } - } - } - } - }, - "eslint-config-tamia": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/eslint-config-tamia/-/eslint-config-tamia-6.2.1.tgz", - "integrity": "sha512-DZgK/08P1OshIwEWBzpGzRFYTL8wDQcuyBKPy16xR6dT1gg4Dapf7/5vWj88djwpW5XrzTvXv2G1yrIfH1ygkQ==", - "dev": true - }, - "eslint-plugin-prettier": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-3.1.4.tgz", - "integrity": "sha512-jZDa8z76klRqo+TdGDTFJSavwbnWK2ZpqGKNZ+VvweMW516pDUMmQ2koXvxEE4JhzNvTv+radye/bWGBmA6jmg==", - "dev": true, - "requires": { - "prettier-linter-helpers": "^1.0.0" - } - }, - "eslint-scope": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", - "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==", - "dev": true, - "requires": { - "esrecurse": "^4.1.0", - "estraverse": "^4.1.1" - }, - "dependencies": { - "estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true - } - } - }, - "eslint-utils": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.3.tgz", - "integrity": "sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q==", - "dev": true, - "requires": { - "eslint-visitor-keys": "^1.1.0" - } - }, - "eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", - "dev": true - }, - "espree": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-5.0.1.tgz", - "integrity": "sha512-qWAZcWh4XE/RwzLJejfcofscgMc9CamR6Tn1+XRXNzrvUSSbiAjGOI/fggztjIi7y9VLPqnICMIPiGyr8JaZ0A==", - "dev": true, - "requires": { - "acorn": "^6.0.7", - "acorn-jsx": "^5.0.0", - "eslint-visitor-keys": "^1.0.0" - } - }, - "esprima": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-1.1.1.tgz", - "integrity": "sha1-W28VR/TRAuZw4UDFCb5ncdautUk=" - }, - "esquery": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.3.1.tgz", - "integrity": "sha512-olpvt9QG0vniUBZspVRN6lwB7hOZoTRtT+jzR+tS4ffYx2mzbw+z0XCOk44aaLYKApNX5nMm+E+P6o25ip/DHQ==", - "dev": true, - "requires": { - "estraverse": "^5.1.0" - }, - "dependencies": { - "estraverse": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.1.0.tgz", - "integrity": "sha512-FyohXK+R0vE+y1nHLoBM7ZTyqRpqAlhdZHCWIWEviFLiGB8b04H6bQs8G+XTthacvT8VuwvteiP7RJSxMs8UEw==", - "dev": true - } - } - }, - "esrecurse": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", - "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", - "dev": true, - "requires": { - "estraverse": "^4.1.0" - }, - "dependencies": { - "estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true - } - } - }, - "estraverse": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.5.1.tgz", - "integrity": "sha1-hno+jlip+EYYr7bC3bzZFrfLr3E=" - }, - "esutils": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-1.0.0.tgz", - "integrity": "sha1-gVHTWOIMisx/t0XnRywAJf5JZXA=" - }, - "etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" - }, - "eventemitter3": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.0.tgz", - "integrity": "sha512-qerSRB0p+UDEssxTtm6EDKcE7W4OaoisfIMl4CngyEhjpYglocpNg6UEqCvemdGhosAsg4sO2dXJOdyBifPGCg==", - "dev": true - }, - "exec-sh": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/exec-sh/-/exec-sh-0.2.2.tgz", - "integrity": "sha512-FIUCJz1RbuS0FKTdaAafAByGS0CPvU3R0MeHxgtl+djzCc//F8HakL8GzmVNZanasTbTAY/3DRFA0KpVqj/eAw==", - "dev": true, - "requires": { - "merge": "^1.2.0" - } - }, - "execa": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", - "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", - "dev": true, - "requires": { - "cross-spawn": "^6.0.0", - "get-stream": "^4.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" - } - }, - "expand-brackets": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", - "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", - "dev": true, - "requires": { - "debug": "^2.3.3", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "posix-character-classes": "^0.1.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "express": { - "version": "4.16.4", - "resolved": "https://registry.npmjs.org/express/-/express-4.16.4.tgz", - "integrity": "sha512-j12Uuyb4FMrd/qQAm6uCHAkPtO8FDTRJZBDd5D2KOL2eLaz1yUNdUB/NOIyq0iU4q4cFarsUCrnFDPBcnksuOg==", - "requires": { - "accepts": "~1.3.5", - "array-flatten": "1.1.1", - "body-parser": "1.18.3", - "content-disposition": "0.5.2", - "content-type": "~1.0.4", - "cookie": "0.3.1", - "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.1", - "fresh": "0.5.2", - "merge-descriptors": "1.0.1", - "methods": "~1.1.2", - "on-finished": "~2.3.0", - "parseurl": "~1.3.2", - "path-to-regexp": "0.1.7", - "proxy-addr": "~2.0.4", - "qs": "6.5.2", - "range-parser": "~1.2.0", - "safe-buffer": "5.1.2", - "send": "0.16.2", - "serve-static": "1.13.2", - "setprototypeof": "1.1.0", - "statuses": "~1.4.0", - "type-is": "~1.6.16", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - }, - "dependencies": { - "body-parser": { - "version": "1.18.3", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.3.tgz", - "integrity": "sha1-WykhmP/dVTs6DyDe0FkrlWlVyLQ=", - "requires": { - "bytes": "3.0.0", - "content-type": "~1.0.4", - "debug": "2.6.9", - "depd": "~1.1.2", - "http-errors": "~1.6.3", - "iconv-lite": "0.4.23", - "on-finished": "~2.3.0", - "qs": "6.5.2", - "raw-body": "2.3.3", - "type-is": "~1.6.16" - } - }, - "bytes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", - "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=" - }, - "iconv-lite": { - "version": "0.4.23", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", - "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "raw-body": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.3.tgz", - "integrity": "sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw==", - "requires": { - "bytes": "3.0.0", - "http-errors": "1.6.3", - "iconv-lite": "0.4.23", - "unpipe": "1.0.0" - } - }, - "statuses": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", - "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==" - } - } - }, - "extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" - }, - "extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "dev": true, - "requires": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - }, - "dependencies": { - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4" - } - } - } - }, - "external-editor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", - "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", - "dev": true, - "requires": { - "chardet": "^0.7.0", - "iconv-lite": "^0.4.24", - "tmp": "^0.0.33" - } - }, - "extglob": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", - "dev": true, - "requires": { - "array-unique": "^0.3.2", - "define-property": "^1.0.0", - "expand-brackets": "^2.1.4", - "extend-shallow": "^2.0.1", - "fragment-cache": "^0.2.1", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } - } - }, - "extsprintf": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" - }, - "fast-deep-equal": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", - "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=" - }, - "fast-diff": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz", - "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==", - "dev": true - }, - "fast-json-stable-stringify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", - "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" - }, - "fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", - "dev": true - }, - "fault": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/fault/-/fault-1.0.4.tgz", - "integrity": "sha512-CJ0HCB5tL5fYTEA7ToAq5+kTwd++Borf1/bifxd9iT70QcXr4MRrO3Llf8Ifs70q+SJcGHFtnIE/Nw6giCtECA==", - "dev": true, - "requires": { - "format": "^0.2.0" - } - }, - "figures": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", - "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", - "dev": true, - "requires": { - "escape-string-regexp": "^1.0.5" - } - }, - "file-entry-cache": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz", - "integrity": "sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==", - "dev": true, - "requires": { - "flat-cache": "^2.0.1" - } - }, - "file-uri-to-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", - "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", - "dev": true, - "optional": true - }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "finalhandler": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz", - "integrity": "sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg==", - "requires": { - "debug": "2.6.9", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "on-finished": "~2.3.0", - "parseurl": "~1.3.2", - "statuses": "~1.4.0", - "unpipe": "~1.0.0" - }, - "dependencies": { - "statuses": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", - "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==" - } - } - }, - "find-parent-dir": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/find-parent-dir/-/find-parent-dir-0.3.0.tgz", - "integrity": "sha1-M8RLQpqysvBkYpnF+fcY83b/jVQ=", - "dev": true - }, - "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "requires": { - "locate-path": "^3.0.0" - } - }, - "flat": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/flat/-/flat-4.1.0.tgz", - "integrity": "sha512-Px/TiLIznH7gEDlPXcUD4KnBusa6kR6ayRUVcnEAbreRIuhkqow/mun59BuRXwoYk7ZQOLW1ZM05ilIvK38hFw==", - "dev": true, - "requires": { - "is-buffer": "~2.0.3" - } - }, - "flat-cache": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz", - "integrity": "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==", - "dev": true, - "requires": { - "flatted": "^2.0.0", - "rimraf": "2.6.3", - "write": "1.0.3" - } - }, - "flatted": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.1.tgz", - "integrity": "sha512-a1hQMktqW9Nmqr5aktAux3JMNqaucxGcjtjWnZLHX7yyPCmlSV3M54nGYbqT8K+0GhF3NBgmJCc3ma+WOgX8Jg==", - "dev": true - }, - "fn-name": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/fn-name/-/fn-name-2.0.1.tgz", - "integrity": "sha1-UhTXU3pNBqSjAcDMJi/rhBiAAuc=", - "dev": true - }, - "for-in": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", - "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", - "dev": true - }, - "forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" - }, - "form-data": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", - "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - } - }, - "format": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/format/-/format-0.2.2.tgz", - "integrity": "sha1-1hcBB+nv3E7TDJ3DkBbflCtctYs=", - "dev": true - }, - "forwarded": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", - "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=" - }, - "fragment-cache": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", - "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", - "dev": true, - "requires": { - "map-cache": "^0.2.2" - } - }, - "fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" - }, - "fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", - "dev": true, - "requires": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - } - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true - }, - "fsevents": { - "version": "1.2.12", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.12.tgz", - "integrity": "sha512-Ggd/Ktt7E7I8pxZRbGIs7vwqAPscSESMrCSkx2FtWeqmheJgCo2R74fTsZFCifr0VTPwqRpPv17+6b8Zp7th0Q==", - "dev": true, - "optional": true, - "requires": { - "bindings": "^1.5.0", - "nan": "^2.12.1", - "node-pre-gyp": "*" - }, - "dependencies": { - "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, - "optional": true - }, - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true, - "optional": true - }, - "aproba": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", - "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", - "dev": true, - "optional": true - }, - "are-we-there-yet": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz", - "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", - "dev": true, - "optional": true, - "requires": { - "delegates": "^1.0.0", - "readable-stream": "^2.0.6" - } - }, - "balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", - "dev": true, - "optional": true - }, - "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, - "optional": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "chownr": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", - "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", - "dev": true, - "optional": true - }, - "code-point-at": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", - "dev": true, - "optional": true - }, - "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, - "optional": true - }, - "console-control-strings": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", - "dev": true, - "optional": true - }, - "core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", - "dev": true, - "optional": true - }, - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true, - "optional": true, - "requires": { - "ms": "^2.1.1" - } - }, - "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, - "optional": true - }, - "delegates": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", - "dev": true, - "optional": true - }, - "detect-libc": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", - "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=", - "dev": true, - "optional": true - }, - "fs-minipass": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz", - "integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==", - "dev": true, - "optional": true, - "requires": { - "minipass": "^2.6.0" - } - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true, - "optional": true - }, - "gauge": { - "version": "2.7.4", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", - "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", - "dev": true, - "optional": true, - "requires": { - "aproba": "^1.0.3", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.0", - "object-assign": "^4.1.0", - "signal-exit": "^3.0.0", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wide-align": "^1.1.0" - } - }, - "glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", - "dev": true, - "optional": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "has-unicode": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", - "dev": true, - "optional": true - }, - "iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, - "optional": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "ignore-walk": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.3.tgz", - "integrity": "sha512-m7o6xuOaT1aqheYHKf8W6J5pYH85ZI9w077erOzLje3JsB1gkafkAhHHY19dqjulgIZHFm32Cp5uNZgcQqdJKw==", - "dev": true, - "optional": true, - "requires": { - "minimatch": "^3.0.4" - } - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, - "optional": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true, - "optional": true - }, - "ini": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", - "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", - "dev": true, - "optional": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "optional": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true, - "optional": true - }, - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, - "optional": 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, - "optional": true - }, - "minipass": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz", - "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", - "dev": true, - "optional": true, - "requires": { - "safe-buffer": "^5.1.2", - "yallist": "^3.0.0" - } - }, - "minizlib": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz", - "integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==", - "dev": true, - "optional": true, - "requires": { - "minipass": "^2.9.0" - } - }, - "mkdirp": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.3.tgz", - "integrity": "sha512-P+2gwrFqx8lhew375MQHHeTlY8AuOJSrGf0R5ddkEndUkmwpgUob/vQuBD1V22/Cw1/lJr4x+EjllSezBThzBg==", - "dev": true, - "optional": true, - "requires": { - "minimist": "^1.2.5" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true, - "optional": true - }, - "needle": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/needle/-/needle-2.3.3.tgz", - "integrity": "sha512-EkY0GeSq87rWp1hoq/sH/wnTWgFVhYlnIkbJ0YJFfRgEFlz2RraCjBpFQ+vrEgEdp0ThfyHADmkChEhcb7PKyw==", - "dev": true, - "optional": true, - "requires": { - "debug": "^3.2.6", - "iconv-lite": "^0.4.4", - "sax": "^1.2.4" - } - }, - "node-pre-gyp": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.14.0.tgz", - "integrity": "sha512-+CvDC7ZttU/sSt9rFjix/P05iS43qHCOOGzcr3Ry99bXG7VX953+vFyEuph/tfqoYu8dttBkE86JSKBO2OzcxA==", - "dev": true, - "optional": true, - "requires": { - "detect-libc": "^1.0.2", - "mkdirp": "^0.5.1", - "needle": "^2.2.1", - "nopt": "^4.0.1", - "npm-packlist": "^1.1.6", - "npmlog": "^4.0.2", - "rc": "^1.2.7", - "rimraf": "^2.6.1", - "semver": "^5.3.0", - "tar": "^4.4.2" - } - }, - "nopt": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.3.tgz", - "integrity": "sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg==", - "dev": true, - "optional": true, - "requires": { - "abbrev": "1", - "osenv": "^0.1.4" - } - }, - "npm-bundled": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.1.1.tgz", - "integrity": "sha512-gqkfgGePhTpAEgUsGEgcq1rqPXA+tv/aVBlgEzfXwA1yiUJF7xtEt3CtVwOjNYQOVknDk0F20w58Fnm3EtG0fA==", - "dev": true, - "optional": true, - "requires": { - "npm-normalize-package-bin": "^1.0.1" - } - }, - "npm-normalize-package-bin": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz", - "integrity": "sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==", - "dev": true, - "optional": true - }, - "npm-packlist": { - "version": "1.4.8", - "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.4.8.tgz", - "integrity": "sha512-5+AZgwru5IevF5ZdnFglB5wNlHG1AOOuw28WhUq8/8emhBmLv6jX5by4WJCh7lW0uSYZYS6DXqIsyZVIXRZU9A==", - "dev": true, - "optional": true, - "requires": { - "ignore-walk": "^3.0.1", - "npm-bundled": "^1.0.1", - "npm-normalize-package-bin": "^1.0.1" - } - }, - "npmlog": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", - "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", - "dev": true, - "optional": true, - "requires": { - "are-we-there-yet": "~1.1.2", - "console-control-strings": "~1.1.0", - "gauge": "~2.7.3", - "set-blocking": "~2.0.0" - } - }, - "number-is-nan": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", - "dev": true, - "optional": true - }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "dev": true, - "optional": true - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, - "optional": true, - "requires": { - "wrappy": "1" - } - }, - "os-homedir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", - "dev": true, - "optional": true - }, - "os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", - "dev": true, - "optional": true - }, - "osenv": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", - "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", - "dev": true, - "optional": true, - "requires": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.0" - } - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true, - "optional": true - }, - "process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true, - "optional": true - }, - "rc": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", - "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", - "dev": true, - "optional": true, - "requires": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - } - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "optional": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "dev": true, - "optional": true, - "requires": { - "glob": "^7.1.3" - } - }, - "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==", - "dev": true, - "optional": true - }, - "safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true, - "optional": true - }, - "sax": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", - "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", - "dev": true, - "optional": true - }, - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "optional": true - }, - "set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", - "dev": true, - "optional": true - }, - "signal-exit": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", - "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", - "dev": true, - "optional": true - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, - "optional": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "optional": true, - "requires": { - "safe-buffer": "~5.1.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "optional": true, - "requires": { - "ansi-regex": "^2.0.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, - "optional": true - }, - "tar": { - "version": "4.4.13", - "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.13.tgz", - "integrity": "sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA==", - "dev": true, - "optional": true, - "requires": { - "chownr": "^1.1.1", - "fs-minipass": "^1.2.5", - "minipass": "^2.8.6", - "minizlib": "^1.2.1", - "mkdirp": "^0.5.0", - "safe-buffer": "^5.1.2", - "yallist": "^3.0.3" - } - }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true, - "optional": true - }, - "wide-align": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", - "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", - "dev": true, - "optional": true, - "requires": { - "string-width": "^1.0.2 || 2" - } - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true, - "optional": true - }, - "yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true, - "optional": true - } - } - }, - "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true - }, - "functional-red-black-tree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", - "dev": true - }, - "get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true - }, - "get-func-name": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", - "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", - "dev": true - }, - "get-own-enumerable-property-symbols": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz", - "integrity": "sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g==", - "dev": true - }, - "get-stdin": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-6.0.0.tgz", - "integrity": "sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g==", - "dev": 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" - } - }, - "get-url-origin": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/get-url-origin/-/get-url-origin-1.0.1.tgz", - "integrity": "sha512-MMSKo16gB2+6CjWy55jNdIAqUEaKgw3LzZCb8wVVtFrhoQ78EXyuYXxDdn3COI3A4Xr4ZfM3fZa9RTjO6DOTxw==", - "dev": true - }, - "get-value": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", - "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", - "dev": true - }, - "getpass": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", - "requires": { - "assert-plus": "^1.0.0" - } - }, - "glob": { - "version": "5.0.15", - "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", - "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", - "dev": true, - "requires": { - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "2 || 3", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "glob-parent": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", - "dev": true, - "requires": { - "is-glob": "^3.1.0", - "path-dirname": "^1.0.0" - }, - "dependencies": { - "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true, - "requires": { - "is-extglob": "^2.1.0" - } - } - } - }, - "globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true - }, - "graceful-fs": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz", - "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==", - "dev": true - }, - "growl": { - "version": "1.10.5", - "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", - "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", - "dev": true - }, - "handlebars": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.1.2.tgz", - "integrity": "sha512-nvfrjqvt9xQ8Z/w0ijewdD/vvWDTOweBUm96NTr66Wfvo1mJenBLwcYmPs3TIBP5ruzYGD7Hx/DaM9RmhroGPw==", - "dev": true, - "requires": { - "neo-async": "^2.6.0", - "optimist": "^0.6.1", - "source-map": "^0.6.1", - "uglify-js": "^3.1.4" - }, - "dependencies": { - "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 - } - } - }, - "har-schema": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" - }, - "har-validator": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", - "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", - "requires": { - "ajv": "^6.5.5", - "har-schema": "^2.0.0" - } - }, - "has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "requires": { - "function-bind": "^1.1.1" - } - }, - "has-ansi": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", - "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - } - } - }, - "has-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", - "dev": true - }, - "has-symbols": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz", - "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=", - "dev": true - }, - "has-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", - "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", - "dev": true, - "requires": { - "get-value": "^2.0.6", - "has-values": "^1.0.0", - "isobject": "^3.0.0" - } - }, - "has-values": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", - "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", - "dev": true, - "requires": { - "is-number": "^3.0.0", - "kind-of": "^4.0.0" - }, - "dependencies": { - "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "kind-of": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", - "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", - "dev": true - }, - "hosted-git-info": { - "version": "2.8.4", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.4.tgz", - "integrity": "sha512-pzXIvANXEFrc5oFFXRMkbLPQ2rXRoDERwDLyrcUxGhaZhgP54BBSl9Oheh7Vv0T090cszWBxPjkQQ5Sq1PbBRQ==", - "dev": true - }, - "http-errors": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", - "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", - "requires": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.0", - "statuses": ">= 1.4.0 < 2" - } - }, - "http-signature": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", - "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", - "requires": { - "assert-plus": "^1.0.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" - } - }, - "husky": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/husky/-/husky-1.1.4.tgz", - "integrity": "sha512-cZjGpS7qsaBSo3fOMUuR7erQloX3l5XzL1v/RkIqU6zrQImDdU70z5Re9fGDp7+kbYlM2EtS4aYMlahBeiCUGw==", - "dev": true, - "requires": { - "cosmiconfig": "^5.0.6", - "execa": "^1.0.0", - "find-up": "^3.0.0", - "get-stdin": "^6.0.0", - "is-ci": "^1.2.1", - "pkg-dir": "^3.0.0", - "please-upgrade-node": "^3.1.1", - "read-pkg": "^4.0.1", - "run-node": "^1.0.0", - "slash": "^2.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": { - "version": "3.3.10", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz", - "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==", - "dev": true - }, - "import-fresh": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.1.tgz", - "integrity": "sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ==", - "dev": true, - "requires": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "dependencies": { - "resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true - } - } - }, - "imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", - "dev": true - }, - "indent-string": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-3.2.0.tgz", - "integrity": "sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok=", - "dev": true - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" - }, - "ini": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", - "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", - "dev": true - }, - "inquirer": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.5.2.tgz", - "integrity": "sha512-cntlB5ghuB0iuO65Ovoi8ogLHiWGs/5yNrtUcKjFhSSiVeAIVpD7koaSU9RM8mpXw5YDi9RdYXGQMaOURB7ycQ==", - "dev": true, - "requires": { - "ansi-escapes": "^3.2.0", - "chalk": "^2.4.2", - "cli-cursor": "^2.1.0", - "cli-width": "^2.0.0", - "external-editor": "^3.0.3", - "figures": "^2.0.0", - "lodash": "^4.17.12", - "mute-stream": "0.0.7", - "run-async": "^2.2.0", - "rxjs": "^6.4.0", - "string-width": "^2.1.0", - "strip-ansi": "^5.1.0", - "through": "^2.3.6" - }, - "dependencies": { - "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 - }, - "lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", - "dev": true - }, - "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" - } - } - } - }, - "invert-kv": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz", - "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==", - "dev": true - }, - "ipaddr.js": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.8.0.tgz", - "integrity": "sha1-6qM9bd16zo9/b+DJygRA5wZzix4=" - }, - "irregular-plurals": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/irregular-plurals/-/irregular-plurals-2.0.0.tgz", - "integrity": "sha512-Y75zBYLkh0lJ9qxeHlMjQ7bSbyiSqNW/UOPWDmzC7cXskL1hekSITh1Oc6JV0XCWWZ9DE8VYSB71xocLk3gmGw==", - "dev": true - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-alphabetical": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-1.0.4.tgz", - "integrity": "sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg==", - "dev": true - }, - "is-alphanumeric": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-alphanumeric/-/is-alphanumeric-1.0.0.tgz", - "integrity": "sha1-Spzvcdr0wAHB2B1j0UDPU/1oifQ=", - "dev": true - }, - "is-alphanumerical": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-1.0.4.tgz", - "integrity": "sha512-UzoZUr+XfVz3t3v4KyGEniVL9BDRoQtY7tOyrRybkVNjDFWyo1yhXNGrrBTQxp3ib9BLAWs7k2YKBQsFRkZG9A==", - "dev": true, - "requires": { - "is-alphabetical": "^1.0.0", - "is-decimal": "^1.0.0" - } - }, - "is-arguments": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.0.4.tgz", - "integrity": "sha512-xPh0Rmt8NE65sNzvyUmWgI1tz3mKq74lGA0mL8LYZcoIzKOzDh6HmrYm3d18k60nHerC8A9Km8kYu87zfSFnLA==", - "dev": true - }, - "is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", - "dev": true - }, - "is-binary-path": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", - "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", - "dev": true, - "requires": { - "binary-extensions": "^1.0.0" - } - }, - "is-buffer": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.3.tgz", - "integrity": "sha512-U15Q7MXTuZlrbymiz95PJpZxu8IlipAp4dtS3wOdgPXx3mqBnslrWU14kxfHB+Py/+2PVKSr37dMAgM2A4uArw==", - "dev": true - }, - "is-callable": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz", - "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==", - "dev": true - }, - "is-ci": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-1.2.1.tgz", - "integrity": "sha512-s6tfsaQaQi3JNciBH6shVqEDvhGut0SUXr31ag8Pd8BBbVVlcGfWhpPmEOoM6RJ5TFhbypvf5yyRw/VXW1IiWg==", - "dev": true, - "requires": { - "ci-info": "^1.5.0" - } - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-date-object": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", - "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=", - "dev": true - }, - "is-decimal": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-1.0.4.tgz", - "integrity": "sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw==", - "dev": true - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - }, - "dependencies": { - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true - } - } - }, - "is-directory": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz", - "integrity": "sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE=", - "dev": true - }, - "is-empty": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/is-empty/-/is-empty-1.2.0.tgz", - "integrity": "sha1-3pu1snhzigWgsJpX4ftNSjQan2s=", - "dev": true - }, - "is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true - }, - "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-file": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-file/-/is-file-1.0.0.tgz", - "integrity": "sha1-KKRM+9nT2xkwRfIrZfzo7fliBZY=", - "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-hexadecimal": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-1.0.4.tgz", - "integrity": "sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw==", - "dev": true - }, - "is-hidden": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/is-hidden/-/is-hidden-1.1.3.tgz", - "integrity": "sha512-FFzhGKA9h59OFxeaJl0W5ILTYetI8WsdqdofKr69uLKZdV6hbDKxj8vkpG3L9uS/6Q/XYh1tkXm6xwRGFweETA==", - "dev": true - }, - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", - "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=", - "dev": true - }, - "is-object": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.1.tgz", - "integrity": "sha1-iVJojF7C/9awPsyF52ngKQMINHA=", - "dev": true - }, - "is-observable": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-observable/-/is-observable-1.1.0.tgz", - "integrity": "sha512-NqCa4Sa2d+u7BWc6CukaObG3Fh+CU9bvixbpcXYhy2VvYS7vVGIdAgnIS5Ks3A/cqk4rebLJ9s8zBstT2aKnIA==", - "dev": true, - "requires": { - "symbol-observable": "^1.1.0" - } - }, - "is-plain-obj": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", - "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=", - "dev": true - }, - "is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "requires": { - "isobject": "^3.0.1" - } - }, - "is-promise": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", - "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==", - "dev": true - }, - "is-regex": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", - "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", - "dev": true, - "requires": { - "has": "^1.0.1" - } - }, - "is-regexp": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz", - "integrity": "sha1-/S2INUXEa6xaYz57mgnof6LLUGk=", - "dev": true - }, - "is-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", - "dev": true - }, - "is-symbol": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz", - "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==", - "dev": true, - "requires": { - "has-symbols": "^1.0.0" - } - }, - "is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" - }, - "is-utf8": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", - "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", - "dev": true - }, - "is-whitespace-character": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-whitespace-character/-/is-whitespace-character-1.0.4.tgz", - "integrity": "sha512-SDweEzfIZM0SJV0EUga669UTKlmL0Pq8Lno0QDQsPnvECB3IM2aP0gdx5TrU0A01MAPfViaZiI2V1QMZLaKK5w==", - "dev": true - }, - "is-windows": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", - "dev": true - }, - "is-word-character": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-word-character/-/is-word-character-1.0.4.tgz", - "integrity": "sha512-5SMO8RVennx3nZrqtKwCGyyetPE9VDba5ugvKLaD4KopPG5kR4mQ7tNt/r7feL5yt5h3lpuBbIUmCOG2eSzXHA==", - "dev": true - }, - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - }, - "isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" - }, - "istanbul": { - "version": "0.4.5", - "resolved": "https://registry.npmjs.org/istanbul/-/istanbul-0.4.5.tgz", - "integrity": "sha1-ZcfXPUxNqE1POsMQuRj7C4Azczs=", - "dev": true, - "requires": { - "abbrev": "1.0.x", - "async": "1.x", - "escodegen": "1.8.x", - "esprima": "2.7.x", - "glob": "^5.0.15", - "handlebars": "^4.0.1", - "js-yaml": "3.x", - "mkdirp": "0.5.x", - "nopt": "3.x", - "once": "1.x", - "resolve": "1.1.x", - "supports-color": "^3.1.0", - "which": "^1.1.1", - "wordwrap": "^1.0.0" - }, - "dependencies": { - "async": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", - "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", - "dev": true - }, - "escodegen": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.8.1.tgz", - "integrity": "sha1-WltTr0aTEQvrsIZ6o0MN07cKEBg=", - "dev": true, - "requires": { - "esprima": "^2.7.1", - "estraverse": "^1.9.1", - "esutils": "^2.0.2", - "optionator": "^0.8.1", - "source-map": "~0.2.0" - } - }, - "esprima": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", - "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", - "dev": true - }, - "estraverse": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.3.tgz", - "integrity": "sha1-r2fy3JIlgkFZUJJgkaQAXSnJu0Q=", - "dev": true - }, - "esutils": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", - "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", - "dev": true - }, - "source-map": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz", - "integrity": "sha1-2rc/vPwrqBm03gO9b26qSBZLP50=", - "dev": true, - "optional": true, - "requires": { - "amdefine": ">=0.0.4" - } - } - } - }, - "jest-get-type": { - "version": "22.4.3", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-22.4.3.tgz", - "integrity": "sha512-/jsz0Y+V29w1chdXVygEKSz2nBoHoYqNShPe+QgxSNjAuP1i8+k4LbQNrfoliKej0P45sivkSCh7yiD6ubHS3w==", - "dev": true - }, - "jest-validate": { - "version": "23.6.0", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-23.6.0.tgz", - "integrity": "sha512-OFKapYxe72yz7agrDAWi8v2WL8GIfVqcbKRCLbRG9PAxtzF9b1SEDdTpytNDN12z2fJynoBwpMpvj2R39plI2A==", - "dev": true, - "requires": { - "chalk": "^2.0.1", - "jest-get-type": "^22.1.0", - "leven": "^2.1.0", - "pretty-format": "^23.6.0" - } - }, - "jexl": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/jexl/-/jexl-2.1.1.tgz", - "integrity": "sha512-a+dZiuYIKl0nPYdAe7sJ8D/bCAbemwLjLypcT2brXtft/Mi3titp1QRCpTkaHrp+qeno8DKFxVpVKYNvw1AV3A==" - }, - "jison": { - "version": "0.4.18", - "resolved": "https://registry.npmjs.org/jison/-/jison-0.4.18.tgz", - "integrity": "sha512-FKkCiJvozgC7VTHhMJ00a0/IApSxhlGsFIshLW6trWJ8ONX2TQJBBz6DlcO1Gffy4w9LT+uL+PA+CVnUSJMF7w==", - "requires": { - "JSONSelect": "0.4.0", - "cjson": "0.3.0", - "ebnf-parser": "0.1.10", - "escodegen": "1.3.x", - "esprima": "1.1.x", - "jison-lex": "0.3.x", - "lex-parser": "~0.1.3", - "nomnom": "1.5.2" - } - }, - "jison-lex": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/jison-lex/-/jison-lex-0.3.4.tgz", - "integrity": "sha1-gcoo2E+ESZ36jFlNzePYo/Jux6U=", - "requires": { - "lex-parser": "0.1.x", - "nomnom": "1.5.2" - } - }, - "js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, - "js-yaml": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", - "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", - "dev": true, - "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "dependencies": { - "esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true - } - } - }, - "jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" - }, - "json-parse-better-errors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", - "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", - "dev": true - }, - "json-schema": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", - "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" - }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" - }, - "json-stable-stringify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", - "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", - "dev": true, - "requires": { - "jsonify": "~0.0.0" - } - }, - "json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", - "dev": true - }, - "json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" - }, - "json5": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", - "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", - "dev": true, - "requires": { - "minimist": "^1.2.0" - } - }, - "jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.6" - } - }, - "jsonify": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", - "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", - "dev": true - }, - "jsonlint": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/jsonlint/-/jsonlint-1.6.0.tgz", - "integrity": "sha1-iKpGvCiaesk7tGyuLVihh6m7SUo=", - "requires": { - "JSV": ">= 4.0.x", - "nomnom": ">= 1.5.x" - } - }, - "jsprim": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", - "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", - "requires": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.2.3", - "verror": "1.10.0" - } - }, - "just-extend": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.1.0.tgz", - "integrity": "sha512-ApcjaOdVTJ7y4r08xI5wIqpvwS48Q0PBG4DJROcEkH1f8MdAiNFyFxz3xoL0LWAVwjrwPYZdVHHxhRHcx/uGLA==", - "dev": true - }, - "kareem": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/kareem/-/kareem-2.3.1.tgz", - "integrity": "sha512-l3hLhffs9zqoDe8zjmb/mAN4B8VT3L56EUvKNqLFVs9YlFA+zx7ke1DO8STAdDyYNkeSo1nKmjuvQeI12So8Xw==" - }, - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", - "dev": true - }, - "lcid": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz", - "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==", - "dev": true, - "requires": { - "invert-kv": "^2.0.0" - } - }, - "lcov-parse": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/lcov-parse/-/lcov-parse-0.0.10.tgz", - "integrity": "sha1-GwuP+ayceIklBYK3C3ExXZ2m2aM=", - "dev": true - }, - "leven": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz", - "integrity": "sha1-wuep93IJTe6dNCAq6KzORoeHVYA=", - "dev": true - }, - "levn": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", - "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", - "dev": true, - "requires": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" - } - }, - "lex-parser": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/lex-parser/-/lex-parser-0.1.4.tgz", - "integrity": "sha1-ZMTwJfF/1Tv7RXY/rrFvAVp0dVA=" - }, - "lint-staged": { - "version": "7.3.0", - "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-7.3.0.tgz", - "integrity": "sha512-AXk40M9DAiPi7f4tdJggwuKIViUplYtVj1os1MVEteW7qOkU50EOehayCfO9TsoGK24o/EsWb41yrEgfJDDjCw==", - "dev": true, - "requires": { - "chalk": "^2.3.1", - "commander": "^2.14.1", - "cosmiconfig": "^5.0.2", - "debug": "^3.1.0", - "dedent": "^0.7.0", - "execa": "^0.9.0", - "find-parent-dir": "^0.3.0", - "is-glob": "^4.0.0", - "is-windows": "^1.0.2", - "jest-validate": "^23.5.0", - "listr": "^0.14.1", - "lodash": "^4.17.5", - "log-symbols": "^2.2.0", - "micromatch": "^3.1.8", - "npm-which": "^3.0.1", - "p-map": "^1.1.1", - "path-is-inside": "^1.0.2", - "pify": "^3.0.0", - "please-upgrade-node": "^3.0.2", - "staged-git-files": "1.1.1", - "string-argv": "^0.0.2", - "stringify-object": "^3.2.2" - }, - "dependencies": { - "cross-spawn": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", - "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", - "dev": true, - "requires": { - "lru-cache": "^4.0.1", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - } - }, - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "execa": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-0.9.0.tgz", - "integrity": "sha512-BbUMBiX4hqiHZUA5+JujIjNb6TyAlp2D5KLheMjMluwOuzcnylDL4AxZYLLn1n2AGB49eSWwyKvvEQoRpnAtmA==", - "dev": true, - "requires": { - "cross-spawn": "^5.0.1", - "get-stream": "^3.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" - } - }, - "get-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", - "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", - "dev": true - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - } - } - }, - "listr": { - "version": "0.14.3", - "resolved": "https://registry.npmjs.org/listr/-/listr-0.14.3.tgz", - "integrity": "sha512-RmAl7su35BFd/xoMamRjpIE4j3v+L28o8CT5YhAXQJm1fD+1l9ngXY8JAQRJ+tFK2i5njvi0iRUKV09vPwA0iA==", - "dev": true, - "requires": { - "@samverschueren/stream-to-observable": "^0.3.0", - "is-observable": "^1.1.0", - "is-promise": "^2.1.0", - "is-stream": "^1.1.0", - "listr-silent-renderer": "^1.1.1", - "listr-update-renderer": "^0.5.0", - "listr-verbose-renderer": "^0.5.0", - "p-map": "^2.0.0", - "rxjs": "^6.3.3" - }, - "dependencies": { - "p-map": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", - "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", - "dev": true - } - } - }, - "listr-silent-renderer": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/listr-silent-renderer/-/listr-silent-renderer-1.1.1.tgz", - "integrity": "sha1-kktaN1cVN3C/Go4/v3S4u/P5JC4=", - "dev": true - }, - "listr-update-renderer": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/listr-update-renderer/-/listr-update-renderer-0.5.0.tgz", - "integrity": "sha512-tKRsZpKz8GSGqoI/+caPmfrypiaq+OQCbd+CovEC24uk1h952lVj5sC7SqyFUm+OaJ5HN/a1YLt5cit2FMNsFA==", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "cli-truncate": "^0.2.1", - "elegant-spinner": "^1.0.1", - "figures": "^1.7.0", - "indent-string": "^3.0.0", - "log-symbols": "^1.0.2", - "log-update": "^2.3.0", - "strip-ansi": "^3.0.1" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - }, - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - } - }, - "figures": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", - "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", - "dev": true, - "requires": { - "escape-string-regexp": "^1.0.5", - "object-assign": "^4.1.0" - } - }, - "log-symbols": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-1.0.2.tgz", - "integrity": "sha1-N2/3tY6jCGoPCfrMdGF+ylAeGhg=", - "dev": true, - "requires": { - "chalk": "^1.0.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - } - } - }, - "listr-verbose-renderer": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/listr-verbose-renderer/-/listr-verbose-renderer-0.5.0.tgz", - "integrity": "sha512-04PDPqSlsqIOaaaGZ+41vq5FejI9auqTInicFRndCBgE3bXG8D6W1I+mWhk+1nqbHmyhla/6BUrd5OSiHwKRXw==", - "dev": true, - "requires": { - "chalk": "^2.4.1", - "cli-cursor": "^2.1.0", - "date-fns": "^1.27.2", - "figures": "^2.0.0" - } - }, - "load-json-file": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", - "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0", - "strip-bom": "^2.0.0" - }, - "dependencies": { - "parse-json": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", - "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "dev": true, - "requires": { - "error-ex": "^1.2.0" - } - }, - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - } - } - }, - "load-plugin": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/load-plugin/-/load-plugin-2.3.1.tgz", - "integrity": "sha512-dYB1lbwqHgPTrruy9glukCu8Ya9vzj6TMfouCtj2H/GuJ+8syioisgKTBPxnCi6m8K8jINKfTOxOHngFkUYqHw==", - "dev": true, - "requires": { - "npm-prefix": "^1.2.0", - "resolve-from": "^5.0.0" - }, - "dependencies": { - "resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true - } - } - }, - "locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, - "requires": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - } - }, - "lodash": { - "version": "4.17.11", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", - "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==" - }, - "lodash.get": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", - "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=", - "dev": true - }, - "log-driver": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/log-driver/-/log-driver-1.2.7.tgz", - "integrity": "sha512-U7KCmLdqsGHBLeWqYlFA0V0Sl6P08EE1ZrmA9cxjUE0WVqT9qnyVDPz1kzpFEP0jdJuFnasWIfSd7fsaNXkpbg==", - "dev": true - }, - "log-symbols": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", - "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", - "dev": true, - "requires": { - "chalk": "^2.0.1" - } - }, - "log-update": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/log-update/-/log-update-2.3.0.tgz", - "integrity": "sha1-iDKP19HOeTiykoN0bwsbwSayRwg=", - "dev": true, - "requires": { - "ansi-escapes": "^3.0.0", - "cli-cursor": "^2.0.0", - "wrap-ansi": "^3.0.1" - }, - "dependencies": { - "wrap-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-3.0.1.tgz", - "integrity": "sha1-KIoE2H7aXChuBg3+jxNc6NAH+Lo=", - "dev": true, - "requires": { - "string-width": "^2.1.1", - "strip-ansi": "^4.0.0" - } - } - } - }, - "logops": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/logops/-/logops-2.1.0.tgz", - "integrity": "sha1-mHIkVNeHG9KqR2j7QWZvFCuVNc8=", - "requires": { - "colors": "^1.1.2", - "lodash": "^4.1.0", - "safe-json-stringify": "^1.0.4", - "serr": "^1.0.0" - }, - "dependencies": { - "colors": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.3.3.tgz", - "integrity": "sha512-mmGt/1pZqYRjMxB1axhTo16/snVZ5krrKkcmMeVKxzECMMXoCgnvTPp10QgHfcbQZw8Dq2jMNG6je4JlWU0gWg==" - } - } - }, - "longest-streak": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-2.0.4.tgz", - "integrity": "sha512-vM6rUVCVUJJt33bnmHiZEvr7wPT78ztX7rojL+LW51bHtLh6HTjx84LA5W4+oa6aKEJA7jJu5LR6vQRBpA5DVg==", - "dev": true - }, - "lru-cache": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", - "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", - "dev": true, - "requires": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" - } - }, - "map-age-cleaner": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz", - "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==", - "dev": true, - "requires": { - "p-defer": "^1.0.0" - } - }, - "map-cache": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", - "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", - "dev": true - }, - "map-like": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/map-like/-/map-like-2.0.0.tgz", - "integrity": "sha1-lEltSa0zPA3DI0snrbvR6FNZU7Q=", - "dev": true - }, - "map-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", - "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", - "dev": true, - "requires": { - "object-visit": "^1.0.0" - } - }, - "markdown-escapes": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/markdown-escapes/-/markdown-escapes-1.0.4.tgz", - "integrity": "sha512-8z4efJYk43E0upd0NbVXwgSTQs6cT3T06etieCMEg7dRbzCbxUCK/GHlX8mhHRDcp+OLlHkPKsvqQTCvsRl2cg==", - "dev": true - }, - "markdown-extensions": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/markdown-extensions/-/markdown-extensions-1.1.1.tgz", - "integrity": "sha512-WWC0ZuMzCyDHYCasEGs4IPvLyTGftYwh6wIEOULOF0HXcqZlhwRzrK0w2VUlxWA98xnvb/jszw4ZSkJ6ADpM6Q==", - "dev": true - }, - "markdown-table": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-1.1.3.tgz", - "integrity": "sha512-1RUZVgQlpJSPWYbFSpmudq5nHY1doEIv89gBtF0s4gW1GF2XorxcA/70M5vq7rLv0a6mhOUccRsqkwhwLCIQ2Q==", - "dev": true - }, - "md5": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/md5/-/md5-2.2.1.tgz", - "integrity": "sha1-U6s41f48iJG6RlMp6iP6wFQBJvk=", - "dev": true, - "requires": { - "charenc": "~0.0.1", - "crypt": "~0.0.1", - "is-buffer": "~1.1.1" - }, - "dependencies": { - "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - } - } - }, - "mdast-comment-marker": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/mdast-comment-marker/-/mdast-comment-marker-1.1.1.tgz", - "integrity": "sha512-TWZDaUtPLwKX1pzDIY48MkSUQRDwX/HqbTB4m3iYdL/zosi/Z6Xqfdv0C0hNVKvzrPjZENrpWDt4p4odeVO0Iw==", - "dev": true - }, - "mdast-util-compact": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mdast-util-compact/-/mdast-util-compact-1.0.4.tgz", - "integrity": "sha512-3YDMQHI5vRiS2uygEFYaqckibpJtKq5Sj2c8JioeOQBU6INpKbdWzfyLqFFnDwEcEnRFIdMsguzs5pC1Jp4Isg==", - "dev": true, - "requires": { - "unist-util-visit": "^1.1.0" - } - }, - "mdast-util-heading-style": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/mdast-util-heading-style/-/mdast-util-heading-style-1.0.5.tgz", - "integrity": "sha512-8zQkb3IUwiwOdUw6jIhnwM6DPyib+mgzQuHAe7j2Hy1rIarU4VUxe472bp9oktqULW3xqZE+Kz6OD4Gi7IA3vw==", - "dev": true - }, - "mdast-util-to-string": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-1.0.7.tgz", - "integrity": "sha512-P+gdtssCoHOX+eJUrrC30Sixqao86ZPlVjR5NEAoy0U79Pfxb1Y0Gntei0+GrnQD4T04X9xA8tcugp90cSmNow==", - "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=" - }, - "mem": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/mem/-/mem-4.3.0.tgz", - "integrity": "sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==", - "dev": true, - "requires": { - "map-age-cleaner": "^0.1.1", - "mimic-fn": "^2.0.0", - "p-is-promise": "^2.0.0" - } - }, - "memory-pager": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz", - "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==", - "optional": true - }, - "merge": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/merge/-/merge-1.2.1.tgz", - "integrity": "sha512-VjFo4P5Whtj4vsLzsYBu5ayHhoHJ0UqNm7ibvShmbmoz7tGi0vXaoJbGdB+GmDMLUdg8DpQXEIeVDAe8MaABvQ==", - "dev": true - }, - "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=" - }, - "micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dev": true, - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - } - }, - "mime": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz", - "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==" - }, - "mime-db": { - "version": "1.37.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.37.0.tgz", - "integrity": "sha512-R3C4db6bgQhlIhPU48fUtdVmKnflq+hRdad7IyKhtFj06VPNVdk2RhiYL3UjQIlso8L+YxAtFkobT0VK+S/ybg==" - }, - "mime-types": { - "version": "2.1.21", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.21.tgz", - "integrity": "sha512-3iL6DbwpyLzjR3xHSFNFeb9Nz/M8WDkX33t1GFQnFOllWk8pOrh/LSrB5OXlnlW5P9LH73X6loW/eogc+F5lJg==", - "requires": { - "mime-db": "~1.37.0" - } - }, - "mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "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.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - }, - "misspellings": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/misspellings/-/misspellings-1.1.0.tgz", - "integrity": "sha1-U9UAJmy9Cc2p2UxM85LmBYm1syQ=", - "dev": true - }, - "mixin-deep": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", - "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", - "dev": true, - "requires": { - "for-in": "^1.0.2", - "is-extendable": "^1.0.1" - }, - "dependencies": { - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4" - } - } - } - }, - "mkdirp": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", - "dev": true, - "requires": { - "minimist": "0.0.8" - }, - "dependencies": { - "minimist": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", - "dev": true - } - } - }, - "mocha": { - "version": "6.1.4", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-6.1.4.tgz", - "integrity": "sha512-PN8CIy4RXsIoxoFJzS4QNnCH4psUCPWc4/rPrst/ecSJJbLBkubMiyGCP2Kj/9YnWbotFqAoeXyXMucj7gwCFg==", - "dev": true, - "requires": { - "ansi-colors": "3.2.3", - "browser-stdout": "1.3.1", - "debug": "3.2.6", - "diff": "3.5.0", - "escape-string-regexp": "1.0.5", - "find-up": "3.0.0", - "glob": "7.1.3", - "growl": "1.10.5", - "he": "1.2.0", - "js-yaml": "3.13.1", - "log-symbols": "2.2.0", - "minimatch": "3.0.4", - "mkdirp": "0.5.1", - "ms": "2.1.1", - "node-environment-flags": "1.0.5", - "object.assign": "4.1.0", - "strip-json-comments": "2.0.1", - "supports-color": "6.0.0", - "which": "1.3.1", - "wide-align": "1.1.3", - "yargs": "13.2.2", - "yargs-parser": "13.0.0", - "yargs-unparser": "1.5.0" - }, - "dependencies": { - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "glob": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", - "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "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==", - "dev": true - }, - "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": "6.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.0.0.tgz", - "integrity": "sha512-on9Kwidc1IUQo+bQdhi8+Tijpo0e1SS6RoGo2guUwn5vdaxw8RXOF9Vb2ws+ihWOmh4JnCJOvaziZWP1VABaLg==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "moment": { - "version": "2.24.0", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.24.0.tgz", - "integrity": "sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg==" - }, - "moment-timezone": { - "version": "0.5.25", - "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.25.tgz", - "integrity": "sha512-DgEaTyN/z0HFaVcVbSyVCUU6HeFdnNC3vE4c9cgu2dgMTvjBUBdBzWfasTBmAW45u5OIMeCJtU8yNjM22DHucw==", - "requires": { - "moment": ">= 2.9.0" - } - }, - "mongodb": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.2.3.tgz", - "integrity": "sha512-jw8UyPsq4QleZ9z+t/pIVy3L++51vKdaJ2Q/XXeYxk/3cnKioAH8H6f5tkkDivrQL4PUgUOHe9uZzkpRFH1XtQ==", - "requires": { - "mongodb-core": "^3.2.3", - "safe-buffer": "^5.1.2" - } - }, - "mongodb-core": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/mongodb-core/-/mongodb-core-3.2.3.tgz", - "integrity": "sha512-UyI0rmvPPkjOJV8XGWa9VCTq7R4hBVipimhnAXeSXnuAPjuTqbyfA5Ec9RcYJ1Hhu+ISnc8bJ1KfGZd4ZkYARQ==", - "requires": { - "bson": "^1.1.1", - "require_optional": "^1.0.1", - "safe-buffer": "^5.1.2", - "saslprep": "^1.0.0" - } - }, - "mongoose": { - "version": "5.7.5", - "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-5.7.5.tgz", - "integrity": "sha512-BZ4FxtnbTurc/wcm/hLltLdI4IDxo4nsE0D9q58YymTdZwreNzwO62CcjVtaHhmr8HmJtOInp2W/T12FZaMf8g==", - "requires": { - "bson": "~1.1.1", - "kareem": "2.3.1", - "mongodb": "3.3.2", - "mongoose-legacy-pluralize": "1.0.2", - "mpath": "0.6.0", - "mquery": "3.2.2", - "ms": "2.1.2", - "regexp-clone": "1.0.0", - "safe-buffer": "5.1.2", - "sift": "7.0.1", - "sliced": "1.0.1" - }, - "dependencies": { - "mongodb": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.3.2.tgz", - "integrity": "sha512-fqJt3iywelk4yKu/lfwQg163Bjpo5zDKhXiohycvon4iQHbrfflSAz9AIlRE6496Pm/dQKQK5bMigdVo2s6gBg==", - "requires": { - "bson": "^1.1.1", - "require_optional": "^1.0.1", - "safe-buffer": "^5.1.2" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - } - } - }, - "mongoose-legacy-pluralize": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/mongoose-legacy-pluralize/-/mongoose-legacy-pluralize-1.0.2.tgz", - "integrity": "sha512-Yo/7qQU4/EyIS8YDFSeenIvXxZN+ld7YdV9LqFVQJzTLye8unujAWPZ4NWKfFA+RNjh+wvTWKY9Z3E5XM6ZZiQ==" - }, - "mpath": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.6.0.tgz", - "integrity": "sha512-i75qh79MJ5Xo/sbhxrDrPSEG0H/mr1kcZXJ8dH6URU5jD/knFxCVqVC/gVSW7GIXL/9hHWlT9haLbCXWOll3qw==" - }, - "mquery": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/mquery/-/mquery-3.2.2.tgz", - "integrity": "sha512-XB52992COp0KP230I3qloVUbkLUxJIu328HBP2t2EsxSFtf4W1HPSOBWOXf1bqxK4Xbb66lfMJ+Bpfd9/yZE1Q==", - "requires": { - "bluebird": "3.5.1", - "debug": "3.1.0", - "regexp-clone": "^1.0.0", - "safe-buffer": "5.1.2", - "sliced": "1.0.1" - }, - "dependencies": { - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "requires": { - "ms": "2.0.0" - } - } - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - }, - "mu2": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/mu2/-/mu2-0.5.21.tgz", - "integrity": "sha1-iIqPD9kOsc/anbgUdvbhmcyeWNM=" - }, - "mute-stream": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", - "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", - "dev": true - }, - "nan": { - "version": "2.14.1", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.1.tgz", - "integrity": "sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw==", - "dev": true, - "optional": true - }, - "nanomatch": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", - "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", - "dev": true, - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "fragment-cache": "^0.2.1", - "is-windows": "^1.0.2", - "kind-of": "^6.0.2", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - } - }, - "natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", - "dev": true - }, - "negotiator": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", - "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=" - }, - "neo-async": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.0.tgz", - "integrity": "sha512-MFh0d/Wa7vkKO3Y3LlacqAEeHK0mckVqzDieUKTT+KGxi+zIpeVsFxymkIiRpbpDziHc290Xr9A1O4Om7otoRA==", - "dev": true - }, - "nice-try": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", - "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", - "dev": true - }, - "nise": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/nise/-/nise-4.0.3.tgz", - "integrity": "sha512-EGlhjm7/4KvmmE6B/UFsKh7eHykRl9VH+au8dduHLCyWUO/hr7+N+WtTvDUwc9zHuM1IaIJs/0lQ6Ag1jDkQSg==", - "dev": true, - "requires": { - "@sinonjs/commons": "^1.7.0", - "@sinonjs/fake-timers": "^6.0.0", - "@sinonjs/text-encoding": "^0.7.1", - "just-extend": "^4.0.2", - "path-to-regexp": "^1.7.0" - }, - "dependencies": { - "path-to-regexp": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", - "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", - "dev": true, - "requires": { - "isarray": "0.0.1" - } - } - } - }, - "no-cliches": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/no-cliches/-/no-cliches-0.1.1.tgz", - "integrity": "sha512-mYihjs47X5+N71CN3P+QBrEIBuclIfMMpgWEpkmLqFPvrOXdzokvDlhbLfjdBNZOqYgniaeZC6J1ZCgxFdyvXw==", - "dev": true - }, - "nock": { - "version": "10.0.6", - "resolved": "https://registry.npmjs.org/nock/-/nock-10.0.6.tgz", - "integrity": "sha512-b47OWj1qf/LqSQYnmokNWM8D88KvUl2y7jT0567NB3ZBAZFz2bWp2PC81Xn7u8F2/vJxzkzNZybnemeFa7AZ2w==", - "dev": true, - "requires": { - "chai": "^4.1.2", - "debug": "^4.1.0", - "deep-equal": "^1.0.0", - "json-stringify-safe": "^5.0.1", - "lodash": "^4.17.5", - "mkdirp": "^0.5.0", - "propagate": "^1.0.0", - "qs": "^6.5.1", - "semver": "^5.5.0" - }, - "dependencies": { - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - } - } - }, - "node-environment-flags": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/node-environment-flags/-/node-environment-flags-1.0.5.tgz", - "integrity": "sha512-VNYPRfGfmZLx0Ye20jWzHUjyTW/c+6Wq+iLhDzUI4XmhrDd9l/FozXV3F2xOaXjvp0co0+v1YSR3CMP6g+VvLQ==", - "dev": true, - "requires": { - "object.getownpropertydescriptors": "^2.0.3", - "semver": "^5.7.0" - } - }, - "node-fetch": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.0.tgz", - "integrity": "sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA==", - "dev": true - }, - "nomnom": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/nomnom/-/nomnom-1.5.2.tgz", - "integrity": "sha1-9DRUSKhTz71cDSYyDyR3qwUm/i8=", - "requires": { - "colors": "0.5.x", - "underscore": "1.1.x" - }, - "dependencies": { - "underscore": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.1.7.tgz", - "integrity": "sha1-QLq4S60Z0jAJbo1u9ii/8FXYPbA=" - } - } - }, - "nopt": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", - "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", - "dev": true, - "requires": { - "abbrev": "1" - } - }, - "normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "dev": true, - "requires": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - }, - "dependencies": { - "resolve": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.12.0.tgz", - "integrity": "sha512-B/dOmuoAik5bKcD6s6nXDCjzUKnaDvdkRyAk6rsmsKLipWj4797iothd7jmmUhWTfinVMU+wc56rYKsit2Qy4w==", - "dev": true, - "requires": { - "path-parse": "^1.0.6" - } - } - } - }, - "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 - }, - "npm-path": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/npm-path/-/npm-path-2.0.4.tgz", - "integrity": "sha512-IFsj0R9C7ZdR5cP+ET342q77uSRdtWOlWpih5eC+lu29tIDbNEgDbzgVJ5UFvYHWhxDZ5TFkJafFioO0pPQjCw==", - "dev": true, - "requires": { - "which": "^1.2.10" - } - }, - "npm-prefix": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/npm-prefix/-/npm-prefix-1.2.0.tgz", - "integrity": "sha1-5hlFX3B0ulTMZtbQ033Z8b5ry8A=", - "dev": true, - "requires": { - "rc": "^1.1.0", - "shellsubstitute": "^1.1.0", - "untildify": "^2.1.0" - } - }, - "npm-run-path": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", - "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", - "dev": true, - "requires": { - "path-key": "^2.0.0" - } - }, - "npm-which": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/npm-which/-/npm-which-3.0.1.tgz", - "integrity": "sha1-kiXybsOihcIJyuZ8OxGmtKtxQKo=", - "dev": true, - "requires": { - "commander": "^2.9.0", - "npm-path": "^2.0.2", - "which": "^1.2.10" - } - }, - "number-is-nan": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", - "dev": true - }, - "oauth-sign": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", - "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" - }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "dev": true - }, - "object-copy": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", - "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", - "dev": true, - "requires": { - "copy-descriptor": "^0.1.0", - "define-property": "^0.2.5", - "kind-of": "^3.0.3" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "object-inspect": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.7.0.tgz", - "integrity": "sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw==", - "dev": true - }, - "object-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.0.2.tgz", - "integrity": "sha512-Epah+btZd5wrrfjkJZq1AOB9O6OxUQto45hzFd7lXGrpHPGE0W1k+426yrZV+k6NJOzLNNW/nVsmZdIWsAqoOQ==", - "dev": true - }, - "object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true - }, - "object-visit": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", - "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", - "dev": true, - "requires": { - "isobject": "^3.0.0" - } - }, - "object.assign": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", - "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", - "dev": true, - "requires": { - "define-properties": "^1.1.2", - "function-bind": "^1.1.1", - "has-symbols": "^1.0.0", - "object-keys": "^1.0.11" - } - }, - "object.getownpropertydescriptors": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz", - "integrity": "sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY=", - "dev": true, - "requires": { - "define-properties": "^1.1.2", - "es-abstract": "^1.5.1" - } - }, - "object.pick": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", - "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", - "dev": true, - "requires": { - "isobject": "^3.0.1" - } - }, - "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" - } - }, - "onetime": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", - "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", - "dev": true, - "requires": { - "mimic-fn": "^1.0.0" - }, - "dependencies": { - "mimic-fn": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", - "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", - "dev": true - } - } - }, - "optimist": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", - "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", - "dev": true, - "requires": { - "minimist": "~0.0.1", - "wordwrap": "~0.0.2" - }, - "dependencies": { - "minimist": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", - "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=", - "dev": true - }, - "wordwrap": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", - "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", - "dev": true - } - } - }, - "optionator": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", - "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", - "dev": true, - "requires": { - "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.4", - "levn": "~0.3.0", - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2", - "wordwrap": "~1.0.0" - } - }, - "os-homedir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", - "dev": true - }, - "os-locale": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz", - "integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==", - "dev": true, - "requires": { - "execa": "^1.0.0", - "lcid": "^2.0.0", - "mem": "^4.0.0" - } - }, - "os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", - "dev": true - }, - "p-defer": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz", - "integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=", - "dev": true - }, - "p-finally": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", - "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", - "dev": true - }, - "p-is-promise": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-2.1.0.tgz", - "integrity": "sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg==", - "dev": true - }, - "p-limit": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.0.tgz", - "integrity": "sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==", - "dev": true, - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, - "requires": { - "p-limit": "^2.0.0" - } - }, - "p-map": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-1.2.0.tgz", - "integrity": "sha512-r6zKACMNhjPJMTl8KcFH4li//gkrXWfbD6feV8l6doRHlzljFWGJ2AP6iKaCJXyZmAUMOPtvbW7EXkbWO/pLEA==", - "dev": true - }, - "p-memoize": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-memoize/-/p-memoize-3.1.0.tgz", - "integrity": "sha512-e5tIvrsr7ydUUnxb534iQWtXxWgk/86IsH+H+nV4FHouIggBt4coXboKBt26o4lTu7JbEnGSeXdEsYR8BhAHFA==", - "dev": true, - "requires": { - "mem": "^4.3.0", - "mimic-fn": "^2.1.0" - } - }, - "p-queue": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-6.2.1.tgz", - "integrity": "sha512-wV8yC/rkuWpgu9LGKJIb48OynYSrE6lVl2Bx6r8WjbyVKrFAzzQ/QevAvwnDjlD+mLt8xy0LTDOU1freOvMTCg==", - "dev": true, - "requires": { - "eventemitter3": "^4.0.0", - "p-timeout": "^3.1.0" - } - }, - "p-timeout": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-3.2.0.tgz", - "integrity": "sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==", - "dev": true, - "requires": { - "p-finally": "^1.0.0" - } - }, - "p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true - }, - "parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "requires": { - "callsites": "^3.0.0" - } - }, - "parse-entities": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-1.2.2.tgz", - "integrity": "sha512-NzfpbxW/NPrzZ/yYSoQxyqUZMZXIdCfE0OIN4ESsnptHJECoUk3FZktxNuzQf4tjt5UEopnxpYJbvYuxIFDdsg==", - "dev": true, - "requires": { - "character-entities": "^1.0.0", - "character-entities-legacy": "^1.0.0", - "character-reference-invalid": "^1.0.0", - "is-alphanumerical": "^1.0.0", - "is-decimal": "^1.0.0", - "is-hexadecimal": "^1.0.0" - } - }, - "parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", - "dev": true, - "requires": { - "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1" - } - }, - "parseurl": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", - "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=" - }, - "pascalcase": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", - "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", - "dev": true - }, - "passive-voice": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/passive-voice/-/passive-voice-0.1.0.tgz", - "integrity": "sha1-Fv+RrkC6DpLEPmcXY/3IQqcCcLE=", - "dev": true - }, - "path-dirname": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", - "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", - "dev": true - }, - "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", - "dev": true - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true - }, - "path-is-inside": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", - "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", - "dev": true - }, - "path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", - "dev": true - }, - "path-parse": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", - "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", - "dev": true - }, - "path-to-glob-pattern": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-to-glob-pattern/-/path-to-glob-pattern-1.0.2.tgz", - "integrity": "sha1-Rz5qOikqnRP7rj7czuctO6uoxhk=", - "dev": true - }, - "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=" - }, - "path-type": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", - "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" - }, - "dependencies": { - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - } - } - }, - "pathval": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.0.tgz", - "integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA=", - "dev": true - }, - "performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" - }, - "pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", - "dev": true - }, - "pinkie": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", - "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", - "dev": true - }, - "pinkie-promise": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", - "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", - "dev": true, - "requires": { - "pinkie": "^2.0.0" - } - }, - "pkg-dir": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", - "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", - "dev": true, - "requires": { - "find-up": "^3.0.0" - } - }, - "please-upgrade-node": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/please-upgrade-node/-/please-upgrade-node-3.2.0.tgz", - "integrity": "sha512-gQR3WpIgNIKwBMVLkpMUeR3e1/E1y42bqDQZfql+kDeXd8COYfM8PQA4X6y7a8u9Ua9FHmsrrmirW2vHs45hWg==", - "dev": true, - "requires": { - "semver-compare": "^1.0.0" - } - }, - "plur": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/plur/-/plur-3.1.1.tgz", - "integrity": "sha512-t1Ax8KUvV3FFII8ltczPn2tJdjqbd1sIzu6t4JL7nQ3EyeL/lTrj5PWKb06ic5/6XYDr65rQ4uzQEGN70/6X5w==", - "dev": true, - "requires": { - "irregular-plurals": "^2.0.0" - } - }, - "pluralize": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-2.0.0.tgz", - "integrity": "sha1-crcmqm+sHt7uQiVsfY3CVrM1Z38=", - "dev": true - }, - "posix-character-classes": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", - "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", - "dev": true - }, - "prelude-ls": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", - "dev": true - }, - "prettier": { - "version": "1.18.2", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.18.2.tgz", - "integrity": "sha512-OeHeMc0JhFE9idD4ZdtNibzY0+TPHSpSSb9h8FqtP+YnoZZ1sl8Vc9b1sasjfymH3SonAF4QcA2+mzHPhMvIiw==", - "dev": true - }, - "prettier-linter-helpers": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", - "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", - "dev": true, - "requires": { - "fast-diff": "^1.1.2" - } - }, - "pretty-format": { - "version": "23.6.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-23.6.0.tgz", - "integrity": "sha512-zf9NV1NSlDLDjycnwm6hpFATCGl/K1lt0R/GdkAK2O5LN/rwJoB+Mh93gGJjut4YbmecbfgLWVGSTCr0Ewvvbw==", - "dev": true, - "requires": { - "ansi-regex": "^3.0.0", - "ansi-styles": "^3.2.0" - } - }, - "process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true - }, - "progress": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", - "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", - "dev": true - }, - "propagate": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/propagate/-/propagate-1.0.0.tgz", - "integrity": "sha1-AMLa7t2iDofjeCs0Stuhzd1q1wk=", - "dev": true - }, - "proxy-addr": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.4.tgz", - "integrity": "sha512-5erio2h9jp5CHGwcybmxmVqHmnCBZeewlfJ0pex+UW7Qny7OOZXTtH56TGNyBizkgiOwhJtMKrVzDTeKcySZwA==", - "requires": { - "forwarded": "~0.1.2", - "ipaddr.js": "1.8.0" - } - }, - "pseudomap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", - "dev": true - }, - "psl": { - "version": "1.1.31", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.31.tgz", - "integrity": "sha512-/6pt4+C+T+wZUieKR620OpzN/LlnNKuWjy1iFLQ/UG35JqHlR/89MP1d96dUfkf6Dne3TuLQzOYEYshJ+Hx8mw==" - }, - "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" - } - }, - "punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" - }, - "qs": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", - "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" - }, - "query-string": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/query-string/-/query-string-6.5.0.tgz", - "integrity": "sha512-TYC4hDjZSvVxLMEucDMySkuAS9UIzSbAiYGyA9GWCjLKB8fQpviFbjd20fD7uejCDxZS+ftSdBKE6DS+xucJFg==", - "requires": { - "decode-uri-component": "^0.2.0", - "split-on-first": "^1.0.0", - "strict-uri-encode": "^2.0.0" - } - }, - "range-parser": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", - "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=" - }, - "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" - }, - "dependencies": { - "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" - } - }, - "setprototypeof": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", - "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" - } - } - }, - "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" - }, - "dependencies": { - "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 - } - } - }, - "rc-config-loader": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/rc-config-loader/-/rc-config-loader-2.0.5.tgz", - "integrity": "sha512-T464K2MQlnNWOblUDIglpFhyN+zYJq7jSlL++/N0hUkcmIXeNFumwXFVdtf8qhUGohn4RYQ0wdi74R575I44PQ==", - "dev": true, - "requires": { - "debug": "^4.1.1", - "js-yaml": "^3.12.0", - "json5": "^2.1.0", - "object-assign": "^4.1.0", - "object-keys": "^1.0.12", - "path-exists": "^3.0.0", - "require-from-string": "^2.0.2" - }, - "dependencies": { - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "json5": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.1.tgz", - "integrity": "sha512-l+3HXD0GEI3huGq1njuqtzYK8OYJyXMkOLtQ53pjWh89tvWS2h6l+1zMkYWqlb57+SiQodKZyvMEFb2X+KrFhQ==", - "dev": true, - "requires": { - "minimist": "^1.2.0" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - } - } - }, - "read-pkg": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-4.0.1.tgz", - "integrity": "sha1-ljYlN48+HE1IyFhytabsfV0JMjc=", - "dev": true, - "requires": { - "normalize-package-data": "^2.3.2", - "parse-json": "^4.0.0", - "pify": "^3.0.0" - } - }, - "read-pkg-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-3.0.0.tgz", - "integrity": "sha1-PtSWaF26D4/hGNBpHcUfSh/5bwc=", - "dev": true, - "requires": { - "find-up": "^2.0.0", - "read-pkg": "^3.0.0" - }, - "dependencies": { - "find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true, - "requires": { - "locate-path": "^2.0.0" - } - }, - "load-json-file": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", - "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^4.0.0", - "pify": "^3.0.0", - "strip-bom": "^3.0.0" - } - }, - "locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", - "dev": true, - "requires": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" - } - }, - "p-limit": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", - "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", - "dev": true, - "requires": { - "p-try": "^1.0.0" - } - }, - "p-locate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", - "dev": true, - "requires": { - "p-limit": "^1.1.0" - } - }, - "p-try": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", - "dev": true - }, - "path-type": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", - "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", - "dev": true, - "requires": { - "pify": "^3.0.0" - } - }, - "read-pkg": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", - "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", - "dev": true, - "requires": { - "load-json-file": "^4.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^3.0.0" - } - }, - "strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", - "dev": true - } - } - }, - "readdirp": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", - "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.11", - "micromatch": "^3.1.10", - "readable-stream": "^2.0.2" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "regex-not": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", - "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", - "dev": true, - "requires": { - "extend-shallow": "^3.0.2", - "safe-regex": "^1.1.0" - } - }, - "regexp-clone": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/regexp-clone/-/regexp-clone-1.0.0.tgz", - "integrity": "sha512-TuAasHQNamyyJ2hb97IuBEif4qBHGjPHBS64sZwytpLEqtBQ1gPJTnOaQ6qmpET16cK14kkjbazl6+p0RRv0yw==" - }, - "regexp.prototype.flags": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.3.0.tgz", - "integrity": "sha512-2+Q0C5g951OlYlJz6yu5/M33IcsESLlLfsyIaLJaG4FA2r4yP8MvVMJUUP/fVBkSpbbbZlS5gynbEWLipiiXiQ==", - "dev": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.0-next.1" - }, - "dependencies": { - "es-abstract": { - "version": "1.17.4", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.4.tgz", - "integrity": "sha512-Ae3um/gb8F0mui/jPL+QiqmglkUsaQf7FwBEHYIFkztkneosu9imhqHpBzQ3h1vit8t5iQ74t6PEVvphBZiuiQ==", - "dev": true, - "requires": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.1.5", - "is-regex": "^1.0.5", - "object-inspect": "^1.7.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.0", - "string.prototype.trimleft": "^2.1.1", - "string.prototype.trimright": "^2.1.1" - } - }, - "es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "dev": true, - "requires": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - } - }, - "has-symbols": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", - "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", - "dev": true - }, - "is-callable": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.5.tgz", - "integrity": "sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q==", - "dev": true - }, - "is-regex": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.5.tgz", - "integrity": "sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ==", - "dev": true, - "requires": { - "has": "^1.0.3" - } - } - } - }, - "regexpp": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz", - "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==", - "dev": true - }, - "remark": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/remark/-/remark-10.0.1.tgz", - "integrity": "sha512-E6lMuoLIy2TyiokHprMjcWNJ5UxfGQjaMSMhV+f4idM625UjjK4j798+gPs5mfjzDE6vL0oFKVeZM6gZVSVrzQ==", - "dev": true, - "requires": { - "remark-parse": "^6.0.0", - "remark-stringify": "^6.0.0", - "unified": "^7.0.0" - } - }, - "remark-cli": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/remark-cli/-/remark-cli-6.0.1.tgz", - "integrity": "sha512-h7Hwnfdcm5J03t2mxhl9BAav+Goqauqfz3LhpE7TP+RIiPnK6njU7qRDD7qlUd/hLyMSB+WBjYc7gVDQT3pv0A==", - "dev": true, - "requires": { - "markdown-extensions": "^1.1.0", - "remark": "^10.0.0", - "unified-args": "^6.0.0" - } - }, - "remark-frontmatter": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/remark-frontmatter/-/remark-frontmatter-1.3.2.tgz", - "integrity": "sha512-2eayxITZ8rezsXdgcXnYB3iLivohm2V/ZT4Ne8uhua6A4pk6GdLE2ZzJnbnINtD1HRLaTdB7RwF9sgUbMptJZA==", - "dev": true, - "requires": { - "fault": "^1.0.1", - "xtend": "^4.0.1" - } - }, - "remark-lint": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/remark-lint/-/remark-lint-6.0.5.tgz", - "integrity": "sha512-o1I3ddm+KNsTxk60wWGI+p2yU1jB1gcm8jo2Sy6VhJ4ab2TrQIp1oQbp5xeLoFXYSh/NAqCpKjHkCM/BYpkFdQ==", - "dev": true, - "requires": { - "remark-message-control": "^4.0.0" - } - }, - "remark-lint-final-newline": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/remark-lint-final-newline/-/remark-lint-final-newline-1.0.3.tgz", - "integrity": "sha512-ETAadktv75EwUS3XDhyZUVstXKxfPAEn7SmfN9kZ4+Jb4qo4hHE9gtTOzhE6HxLUxxl9BBhpC5mMO3JcL8UZ5A==", - "dev": true, - "requires": { - "unified-lint-rule": "^1.0.0" - } - }, - "remark-lint-hard-break-spaces": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/remark-lint-hard-break-spaces/-/remark-lint-hard-break-spaces-1.0.4.tgz", - "integrity": "sha512-YM82UpgliZCZhGNmFxEe7ArfhqR5CplFf2bc0k0+8w3rKWKx7EJcGMar2NK410tIi40gGeWtH/pIEypPJFCCiA==", - "dev": true, - "requires": { - "unified-lint-rule": "^1.0.0", - "unist-util-generated": "^1.1.0", - "unist-util-position": "^3.0.0", - "unist-util-visit": "^1.1.1" - } - }, - "remark-lint-list-item-bullet-indent": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/remark-lint-list-item-bullet-indent/-/remark-lint-list-item-bullet-indent-1.0.3.tgz", - "integrity": "sha512-iVxQbrgzLpMHG3C6o6wRta/+Bc96etOiBYJnh2zm/aWz6DJ7cGLDykngblP/C4he7LYSeWOD/8Y57HbXZwM2Og==", - "dev": true, - "requires": { - "plur": "^3.0.0", - "unified-lint-rule": "^1.0.0", - "unist-util-generated": "^1.1.0", - "unist-util-position": "^3.0.0", - "unist-util-visit": "^1.1.1" - } - }, - "remark-lint-list-item-indent": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/remark-lint-list-item-indent/-/remark-lint-list-item-indent-1.0.4.tgz", - "integrity": "sha512-Sv0gVH6qP1/nFpbJuyyguB9sAD2o42StD2WbEZeUcEexXwRO4u/YaX0Pm5pMtCiEHyN+qyL6ShKBQMtgol9BeA==", - "dev": true, - "requires": { - "plur": "^3.0.0", - "unified-lint-rule": "^1.0.0", - "unist-util-generated": "^1.1.0", - "unist-util-position": "^3.0.0", - "unist-util-visit": "^1.1.1" - } - }, - "remark-lint-no-auto-link-without-protocol": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/remark-lint-no-auto-link-without-protocol/-/remark-lint-no-auto-link-without-protocol-1.0.3.tgz", - "integrity": "sha512-k+hg2mXnO4Q9WV+UShPLen5oThvFxcRVWkx2hviVd/nu3eiszBKH3o38csBwjeJoMG3l2ZhdUW8dlOBhq8670Q==", - "dev": true, - "requires": { - "mdast-util-to-string": "^1.0.2", - "unified-lint-rule": "^1.0.0", - "unist-util-generated": "^1.1.0", - "unist-util-position": "^3.0.0", - "unist-util-visit": "^1.1.1" - } - }, - "remark-lint-no-blockquote-without-marker": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/remark-lint-no-blockquote-without-marker/-/remark-lint-no-blockquote-without-marker-2.0.3.tgz", - "integrity": "sha512-faDzKrA6aKidsRXG6gcIlCO8TexLxIxe+n9B3mdnl8mhZGgE0FfWTkIWVMj0IYps/xVsVMf45KxhXgc1wU9kwg==", - "dev": true, - "requires": { - "unified-lint-rule": "^1.0.0", - "unist-util-generated": "^1.1.0", - "unist-util-position": "^3.0.0", - "unist-util-visit": "^1.1.1", - "vfile-location": "^2.0.1" - } - }, - "remark-lint-no-duplicate-definitions": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/remark-lint-no-duplicate-definitions/-/remark-lint-no-duplicate-definitions-1.0.5.tgz", - "integrity": "sha512-zKXmfNUODXhJsGQdqfguMG9Nl9v1sLaDsQgMjUtmOSoQRnNud9ThQAZl62eX5jBn5HKcpOifG80tgkyBvU5eEw==", - "dev": true, - "requires": { - "unified-lint-rule": "^1.0.0", - "unist-util-generated": "^1.1.0", - "unist-util-position": "^3.0.0", - "unist-util-stringify-position": "^2.0.0", - "unist-util-visit": "^1.4.0" - } - }, - "remark-lint-no-heading-content-indent": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/remark-lint-no-heading-content-indent/-/remark-lint-no-heading-content-indent-1.0.3.tgz", - "integrity": "sha512-7xM6X5E/dt8OXOHdejH+sfYb139a3kMr8ZSSkcp90Ab1y+ZQBNaWsR3mYh8FRKkYPTN5eyd+KjhNpLWyqqCbgg==", - "dev": true, - "requires": { - "mdast-util-heading-style": "^1.0.2", - "plur": "^3.0.0", - "unified-lint-rule": "^1.0.0", - "unist-util-generated": "^1.1.0", - "unist-util-position": "^3.0.0", - "unist-util-visit": "^1.1.1" - } - }, - "remark-lint-no-inline-padding": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/remark-lint-no-inline-padding/-/remark-lint-no-inline-padding-1.0.4.tgz", - "integrity": "sha512-u5rgbDkcfVv645YxxOwoGBBJbsHEwWm/XqnO8EhfKTxkfKOF4ZItG7Ajhj89EDaeXMkvCcB/avBl4bj50eJH3g==", - "dev": true, - "requires": { - "mdast-util-to-string": "^1.0.2", - "unified-lint-rule": "^1.0.0", - "unist-util-generated": "^1.1.0", - "unist-util-visit": "^1.4.0" - } - }, - "remark-lint-no-literal-urls": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/remark-lint-no-literal-urls/-/remark-lint-no-literal-urls-1.0.3.tgz", - "integrity": "sha512-H5quyMzl2kaewK+jYD1FI0G1SIinIsIp4DEyOUwIR+vYUoKwo0B4vvW0cmPpD1dgqqxHYx0B2B0JQQKFVWzGiw==", - "dev": true, - "requires": { - "mdast-util-to-string": "^1.0.2", - "unified-lint-rule": "^1.0.0", - "unist-util-generated": "^1.1.0", - "unist-util-position": "^3.0.0", - "unist-util-visit": "^1.1.1" - } - }, - "remark-lint-no-shortcut-reference-image": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/remark-lint-no-shortcut-reference-image/-/remark-lint-no-shortcut-reference-image-1.0.3.tgz", - "integrity": "sha512-CGm27X54kXp/5ehXejDTsZjqzK4uIhLGcrFzN3k/KjdwunQouEY92AARGrLSEuJ1hQx0bJsmnvr/hvQyWAfNJg==", - "dev": true, - "requires": { - "unified-lint-rule": "^1.0.0", - "unist-util-generated": "^1.1.0", - "unist-util-visit": "^1.1.1" - } - }, - "remark-lint-no-shortcut-reference-link": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/remark-lint-no-shortcut-reference-link/-/remark-lint-no-shortcut-reference-link-1.0.4.tgz", - "integrity": "sha512-FXdMJYqspZBhPlxYqfVgVluVXjxStg0RHJzqrk8G9wS8fCS62AE3reoaoiCahwoH1tfKcA+poktbKqDAmZo7Jg==", - "dev": true, - "requires": { - "unified-lint-rule": "^1.0.0", - "unist-util-generated": "^1.1.0", - "unist-util-visit": "^1.1.1" - } - }, - "remark-lint-no-undefined-references": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/remark-lint-no-undefined-references/-/remark-lint-no-undefined-references-1.1.1.tgz", - "integrity": "sha512-b1eIjWFaCu6m16Ax2uG33o1v+eRYqDTQRUqU6UeQ76JXmDmVtVO75ZuyRpqqE7VTZRW8YLVurXfJPDXfIa5Wng==", - "dev": true, - "requires": { - "collapse-white-space": "^1.0.4", - "unified-lint-rule": "^1.0.0", - "unist-util-generated": "^1.1.0", - "unist-util-visit": "^1.4.0" - } - }, - "remark-lint-no-unused-definitions": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/remark-lint-no-unused-definitions/-/remark-lint-no-unused-definitions-1.0.5.tgz", - "integrity": "sha512-Bo22e0RNzc1QMW317KTuStGFDG7uTDUQhm/TrW6Qzud0WXnNnqUyvts+e7wTYoj8VnwhhjyjyoA9lKA3uXMdAQ==", - "dev": true, - "requires": { - "unified-lint-rule": "^1.0.0", - "unist-util-generated": "^1.1.0", - "unist-util-visit": "^1.4.0" - } - }, - "remark-lint-ordered-list-marker-style": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/remark-lint-ordered-list-marker-style/-/remark-lint-ordered-list-marker-style-1.0.3.tgz", - "integrity": "sha512-24TmW1eUa/2JlwprZg9jJ8LKLxNGKnlKiI5YOhN4taUp2yv8daqlV9vR54yfn/ZZQh6EQvbIX0jeVY9NYgQUtw==", - "dev": true, - "requires": { - "unified-lint-rule": "^1.0.0", - "unist-util-generated": "^1.1.0", - "unist-util-position": "^3.0.0", - "unist-util-visit": "^1.1.1" - } - }, - "remark-message-control": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/remark-message-control/-/remark-message-control-4.2.0.tgz", - "integrity": "sha512-WXH2t5ljTyhsXlK1zPBLF3iPHbXl58R94phPMreS1xcHWBZJt6Oiu8RtNjy1poZFb3PqKnbYLJeR/CWcZ1bTFw==", - "dev": true, - "requires": { - "mdast-comment-marker": "^1.0.0", - "unified-message-control": "^1.0.0", - "xtend": "^4.0.1" - } - }, - "remark-parse": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-6.0.3.tgz", - "integrity": "sha512-QbDXWN4HfKTUC0hHa4teU463KclLAnwpn/FBn87j9cKYJWWawbiLgMfP2Q4XwhxxuuuOxHlw+pSN0OKuJwyVvg==", - "dev": true, - "requires": { - "collapse-white-space": "^1.0.2", - "is-alphabetical": "^1.0.0", - "is-decimal": "^1.0.0", - "is-whitespace-character": "^1.0.0", - "is-word-character": "^1.0.0", - "markdown-escapes": "^1.0.0", - "parse-entities": "^1.1.0", - "repeat-string": "^1.5.4", - "state-toggle": "^1.0.0", - "trim": "0.0.1", - "trim-trailing-lines": "^1.0.0", - "unherit": "^1.0.4", - "unist-util-remove-position": "^1.0.0", - "vfile-location": "^2.0.0", - "xtend": "^4.0.1" - } - }, - "remark-preset-lint-recommended": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/remark-preset-lint-recommended/-/remark-preset-lint-recommended-3.0.3.tgz", - "integrity": "sha512-5sQ34j1Irlsj6Tt4WWRylZ7UU+1jD5es/LfDZBZp/LXDwC4ldGqKpMmCCR6Z00x1jYM1phmS4M+eGqTdah0qkQ==", - "dev": true, - "requires": { - "remark-lint": "^6.0.0", - "remark-lint-final-newline": "^1.0.0", - "remark-lint-hard-break-spaces": "^1.0.0", - "remark-lint-list-item-bullet-indent": "^1.0.0", - "remark-lint-list-item-indent": "^1.0.0", - "remark-lint-no-auto-link-without-protocol": "^1.0.0", - "remark-lint-no-blockquote-without-marker": "^2.0.0", - "remark-lint-no-duplicate-definitions": "^1.0.0", - "remark-lint-no-heading-content-indent": "^1.0.0", - "remark-lint-no-inline-padding": "^1.0.0", - "remark-lint-no-literal-urls": "^1.0.0", - "remark-lint-no-shortcut-reference-image": "^1.0.0", - "remark-lint-no-shortcut-reference-link": "^1.0.0", - "remark-lint-no-undefined-references": "^1.0.0", - "remark-lint-no-unused-definitions": "^1.0.0", - "remark-lint-ordered-list-marker-style": "^1.0.0" - } - }, - "remark-stringify": { - "version": "6.0.4", - "resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-6.0.4.tgz", - "integrity": "sha512-eRWGdEPMVudijE/psbIDNcnJLRVx3xhfuEsTDGgH4GsFF91dVhw5nhmnBppafJ7+NWINW6C7ZwWbi30ImJzqWg==", - "dev": true, - "requires": { - "ccount": "^1.0.0", - "is-alphanumeric": "^1.0.0", - "is-decimal": "^1.0.0", - "is-whitespace-character": "^1.0.0", - "longest-streak": "^2.0.1", - "markdown-escapes": "^1.0.0", - "markdown-table": "^1.1.0", - "mdast-util-compact": "^1.0.0", - "parse-entities": "^1.0.2", - "repeat-string": "^1.5.4", - "state-toggle": "^1.0.0", - "stringify-entities": "^1.0.1", - "unherit": "^1.0.4", - "xtend": "^4.0.1" - } - }, - "remove-trailing-separator": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", - "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", - "dev": true - }, - "repeat-element": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", - "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==", - "dev": true - }, - "repeat-string": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", - "dev": true - }, - "replace-ext": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz", - "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=", - "dev": true - }, - "request": { - "version": "2.88.0", - "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", - "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", - "requires": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "har-validator": "~5.1.0", - "http-signature": "~1.2.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "oauth-sign": "~0.9.0", - "performance-now": "^2.1.0", - "qs": "~6.5.2", - "safe-buffer": "^5.1.2", - "tough-cookie": "~2.4.3", - "tunnel-agent": "^0.6.0", - "uuid": "^3.3.2" - }, - "dependencies": { - "uuid": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", - "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==" - } - } - }, - "require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", - "dev": true - }, - "require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "dev": true - }, - "require-main-filename": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", - "dev": true - }, - "require_optional": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/require_optional/-/require_optional-1.0.1.tgz", - "integrity": "sha512-qhM/y57enGWHAe3v/NcwML6a3/vfESLe/sGM2dII+gEO0BpKRUkWZow/tyloNqJyN6kXSl3RyyM8Ll5D/sJP8g==", - "requires": { - "resolve-from": "^2.0.0", - "semver": "^5.1.0" - } - }, - "resolve": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", - "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", - "dev": true - }, - "resolve-from": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-2.0.0.tgz", - "integrity": "sha1-lICrIOlP+h2egKgEx+oUdhGWa1c=" - }, - "resolve-url": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", - "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", - "dev": true - }, - "restore-cursor": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", - "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", - "dev": true, - "requires": { - "onetime": "^2.0.0", - "signal-exit": "^3.0.2" - } - }, - "ret": { - "version": "0.1.15", - "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", - "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", - "dev": true - }, - "revalidator": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/revalidator/-/revalidator-0.3.1.tgz", - "integrity": "sha1-/yzEz3zHxjhaxxAXgnbm280Ddi8=" - }, - "rimraf": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", - "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - }, - "dependencies": { - "glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - } - } - }, - "run-async": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", - "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", - "dev": true - }, - "run-node": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/run-node/-/run-node-1.0.0.tgz", - "integrity": "sha512-kc120TBlQ3mih1LSzdAJXo4xn/GWS2ec0l3S+syHDXP9uRr0JAT8Qd3mdMuyjqCzeZktgP3try92cEgf9Nks8A==", - "dev": true - }, - "rxjs": { - "version": "6.5.5", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.5.tgz", - "integrity": "sha512-WfQI+1gohdf0Dai/Bbmk5L5ItH5tYqm3ki2c5GdWhKjalzjg93N3avFjVStyZZz+A2Em+ZxKH5bNghw9UeylGQ==", - "dev": true, - "requires": { - "tslib": "^1.9.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==" - }, - "safe-json-stringify": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/safe-json-stringify/-/safe-json-stringify-1.2.0.tgz", - "integrity": "sha512-gH8eh2nZudPQO6TytOvbxnuhYBOvDBBLW52tz5q6X58lJcd/tkmqFR+5Z9adS8aJtURSXWThWy/xJtJwixErvg==" - }, - "safe-regex": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", - "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", - "dev": true, - "requires": { - "ret": "~0.1.10" - } - }, - "safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" - }, - "saslprep": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/saslprep/-/saslprep-1.0.2.tgz", - "integrity": "sha512-4cDsYuAjXssUSjxHKRe4DTZC0agDwsCqcMqtJAQPzC74nJ7LfAJflAtC1Zed5hMzEQKj82d3tuzqdGNRsLJ4Gw==", - "optional": true, - "requires": { - "sparse-bitfield": "^3.0.3" - } - }, - "semver": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz", - "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==" - }, - "semver-compare": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", - "integrity": "sha1-De4hahyUGrN+nvsXiPavxf9VN/w=", - "dev": true - }, - "send": { - "version": "0.16.2", - "resolved": "https://registry.npmjs.org/send/-/send-0.16.2.tgz", - "integrity": "sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw==", - "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.6.2", - "mime": "1.4.1", - "ms": "2.0.0", - "on-finished": "~2.3.0", - "range-parser": "~1.2.0", - "statuses": "~1.4.0" - }, - "dependencies": { - "statuses": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", - "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==" - } - } - }, - "serr": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/serr/-/serr-1.0.1.tgz", - "integrity": "sha1-dKW55/rdW1X4qF5+crwApBm25II=", - "requires": { - "lodash": "^4.0.0" - } - }, - "serve-static": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.2.tgz", - "integrity": "sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw==", - "requires": { - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "parseurl": "~1.3.2", - "send": "0.16.2" - } - }, - "set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", - "dev": true - }, - "set-value": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", - "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-extendable": "^0.1.1", - "is-plain-object": "^2.0.3", - "split-string": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "setprototypeof": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", - "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" - }, - "shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", - "dev": true, - "requires": { - "shebang-regex": "^1.0.0" - } - }, - "shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", - "dev": true - }, - "shellsubstitute": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shellsubstitute/-/shellsubstitute-1.2.0.tgz", - "integrity": "sha1-5PcCpQxRiw9v6YRRiQ1wWvKba3A=", - "dev": true - }, - "should": { - "version": "13.2.3", - "resolved": "https://registry.npmjs.org/should/-/should-13.2.3.tgz", - "integrity": "sha512-ggLesLtu2xp+ZxI+ysJTmNjh2U0TsC+rQ/pfED9bUZZ4DKefP27D+7YJVVTvKsmjLpIi9jAa7itwDGkDDmt1GQ==", - "dev": true, - "requires": { - "should-equal": "^2.0.0", - "should-format": "^3.0.3", - "should-type": "^1.4.0", - "should-type-adaptors": "^1.0.1", - "should-util": "^1.0.0" - } - }, - "should-equal": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/should-equal/-/should-equal-2.0.0.tgz", - "integrity": "sha512-ZP36TMrK9euEuWQYBig9W55WPC7uo37qzAEmbjHz4gfyuXrEUgF8cUvQVO+w+d3OMfPvSRQJ22lSm8MQJ43LTA==", - "dev": true, - "requires": { - "should-type": "^1.4.0" - } - }, - "should-format": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/should-format/-/should-format-3.0.3.tgz", - "integrity": "sha1-m/yPdPo5IFxT04w01xcwPidxJPE=", - "dev": true, - "requires": { - "should-type": "^1.3.0", - "should-type-adaptors": "^1.0.1" - } - }, - "should-type": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/should-type/-/should-type-1.4.0.tgz", - "integrity": "sha1-B1bYzoRt/QmEOmlHcZ36DUz/XPM=", - "dev": true - }, - "should-type-adaptors": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/should-type-adaptors/-/should-type-adaptors-1.1.0.tgz", - "integrity": "sha512-JA4hdoLnN+kebEp2Vs8eBe9g7uy0zbRo+RMcU0EsNy+R+k049Ki+N5tT5Jagst2g7EAja+euFuoXFCa8vIklfA==", - "dev": true, - "requires": { - "should-type": "^1.3.0", - "should-util": "^1.0.0" - } - }, - "should-util": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/should-util/-/should-util-1.0.0.tgz", - "integrity": "sha1-yYzaN0qmsZDfi6h8mInCtNtiAGM=", - "dev": true - }, - "sift": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/sift/-/sift-7.0.1.tgz", - "integrity": "sha512-oqD7PMJ+uO6jV9EQCl0LrRw1OwsiPsiFQR5AR30heR+4Dl7jBBbDLnNvWiak20tzZlSE1H7RB30SX/1j/YYT7g==" - }, - "signal-exit": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", - "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", - "dev": true - }, - "sinon": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-9.0.2.tgz", - "integrity": "sha512-0uF8Q/QHkizNUmbK3LRFqx5cpTttEVXudywY9Uwzy8bTfZUhljZ7ARzSxnRHWYWtVTeh4Cw+tTb3iU21FQVO9A==", - "dev": true, - "requires": { - "@sinonjs/commons": "^1.7.2", - "@sinonjs/fake-timers": "^6.0.1", - "@sinonjs/formatio": "^5.0.1", - "@sinonjs/samsam": "^5.0.3", - "diff": "^4.0.2", - "nise": "^4.0.1", - "supports-color": "^7.1.0" - }, - "dependencies": { - "diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "dev": true - }, - "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.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", - "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "slash": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", - "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", - "dev": true - }, - "slice-ansi": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz", - "integrity": "sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU=", - "dev": true - }, - "sliced": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/sliced/-/sliced-1.0.1.tgz", - "integrity": "sha1-CzpmK10Ewxd7GSa+qCsD+Dei70E=" - }, - "snapdragon": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", - "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", - "dev": true, - "requires": { - "base": "^0.11.1", - "debug": "^2.2.0", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "map-cache": "^0.2.2", - "source-map": "^0.5.6", - "source-map-resolve": "^0.5.0", - "use": "^3.1.0" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - } - } - }, - "snapdragon-node": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", - "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", - "dev": true, - "requires": { - "define-property": "^1.0.0", - "isobject": "^3.0.0", - "snapdragon-util": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } - } - }, - "snapdragon-util": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", - "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", - "dev": true, - "requires": { - "kind-of": "^3.2.0" - }, - "dependencies": { - "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "source-map": { - "version": "0.1.43", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", - "integrity": "sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y=", - "optional": true, - "requires": { - "amdefine": ">=0.0.4" - } - }, - "source-map-resolve": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz", - "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==", - "dev": true, - "requires": { - "atob": "^2.1.1", - "decode-uri-component": "^0.2.0", - "resolve-url": "^0.2.1", - "source-map-url": "^0.4.0", - "urix": "^0.1.0" - } - }, - "source-map-url": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", - "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", - "dev": true - }, - "sparse-bitfield": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", - "integrity": "sha1-/0rm5oZWBWuks+eSqzM004JzyhE=", - "optional": true, - "requires": { - "memory-pager": "^1.0.2" - } - }, - "spdx-correct": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz", - "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==", - "dev": true, - "requires": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-exceptions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", - "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==", - "dev": true - }, - "spdx-expression-parse": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", - "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", - "dev": true, - "requires": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-license-ids": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz", - "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==", - "dev": true - }, - "split-on-first": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/split-on-first/-/split-on-first-1.1.0.tgz", - "integrity": "sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw==" - }, - "split-string": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", - "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", - "dev": true, - "requires": { - "extend-shallow": "^3.0.0" - } - }, - "sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", - "dev": true - }, - "sshpk": { - "version": "1.16.1", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", - "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", - "requires": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "safer-buffer": "^2.0.2", - "tweetnacl": "~0.14.0" - } - }, - "staged-git-files": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/staged-git-files/-/staged-git-files-1.1.1.tgz", - "integrity": "sha512-H89UNKr1rQJvI1c/PIR3kiAMBV23yvR7LItZiV74HWZwzt7f3YHuujJ9nJZlt58WlFox7XQsOahexwk7nTe69A==", - "dev": true - }, - "state-toggle": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/state-toggle/-/state-toggle-1.0.3.tgz", - "integrity": "sha512-d/5Z4/2iiCnHw6Xzghyhb+GcmF89bxwgXG60wjIiZaxnymbyOmI8Hk4VqHXiVVp6u2ysaskFfXg3ekCj4WNftQ==", - "dev": true - }, - "static-extend": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", - "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", - "dev": true, - "requires": { - "define-property": "^0.2.5", - "object-copy": "^0.1.0" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - } - } - }, - "statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" - }, - "strict-uri-encode": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz", - "integrity": "sha1-ucczDHBChi9rFC3CdLvMWGbONUY=" - }, - "string-argv": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.0.2.tgz", - "integrity": "sha1-2sMECGkMIfPDYwo/86BYd73L1zY=", - "dev": true - }, - "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true, - "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - } - }, - "string.prototype.padstart": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string.prototype.padstart/-/string.prototype.padstart-3.1.0.tgz", - "integrity": "sha512-envqZvUp2JItI+OeQ5UAh1ihbAV5G/2bixTojvlIa090GGqF+NQRxbWb2nv9fTGrZABv6+pE6jXoAZhhS2k4Hw==", - "dev": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.0-next.1" - }, - "dependencies": { - "es-abstract": { - "version": "1.17.4", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.4.tgz", - "integrity": "sha512-Ae3um/gb8F0mui/jPL+QiqmglkUsaQf7FwBEHYIFkztkneosu9imhqHpBzQ3h1vit8t5iQ74t6PEVvphBZiuiQ==", - "dev": true, - "requires": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.1.5", - "is-regex": "^1.0.5", - "object-inspect": "^1.7.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.0", - "string.prototype.trimleft": "^2.1.1", - "string.prototype.trimright": "^2.1.1" - } - }, - "es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "dev": true, - "requires": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - } - }, - "has-symbols": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", - "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", - "dev": true - }, - "is-callable": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.5.tgz", - "integrity": "sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q==", - "dev": true - }, - "is-regex": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.5.tgz", - "integrity": "sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ==", - "dev": true, - "requires": { - "has": "^1.0.3" - } - } - } - }, - "string.prototype.trimleft": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.1.tgz", - "integrity": "sha512-iu2AGd3PuP5Rp7x2kEZCrB2Nf41ehzh+goo8TV7z8/XDBbsvc6HQIlUl9RjkZ4oyrW1XM5UwlGl1oVEaDjg6Ag==", - "dev": true, - "requires": { - "define-properties": "^1.1.3", - "function-bind": "^1.1.1" - } - }, - "string.prototype.trimright": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.1.tgz", - "integrity": "sha512-qFvWL3/+QIgZXVmJBfpHmxLB7xsUXz6HsUmP8+5dRaC3Q7oKUv9Vo6aMCRZC1smrtyECFsIT30PqBJ1gTjAs+g==", - "dev": true, - "requires": { - "define-properties": "^1.1.3", - "function-bind": "^1.1.1" - } - }, - "stringify-entities": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-1.3.2.tgz", - "integrity": "sha512-nrBAQClJAPN2p+uGCVJRPIPakKeKWZ9GtBCmormE7pWOSlHat7+x5A8gx85M7HM5Dt0BP3pP5RhVW77WdbJJ3A==", - "dev": true, - "requires": { - "character-entities-html4": "^1.0.0", - "character-entities-legacy": "^1.0.0", - "is-alphanumerical": "^1.0.0", - "is-hexadecimal": "^1.0.0" - } - }, - "stringify-object": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/stringify-object/-/stringify-object-3.3.0.tgz", - "integrity": "sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw==", - "dev": true, - "requires": { - "get-own-enumerable-property-symbols": "^3.0.0", - "is-obj": "^1.0.1", - "is-regexp": "^1.0.0" - } - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "^3.0.0" - } - }, - "strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "dev": true, - "requires": { - "is-utf8": "^0.2.0" - } - }, - "strip-eof": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", - "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", - "dev": true - }, - "structured-source": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/structured-source/-/structured-source-3.0.2.tgz", - "integrity": "sha1-3YAkJeD1PcSm56yjdSkBoczaevU=", - "dev": true, - "requires": { - "boundary": "^1.0.1" - } - }, - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true, - "requires": { - "has-flag": "^1.0.0" - } - }, - "symbol-observable": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz", - "integrity": "sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==", - "dev": true - }, - "table": { - "version": "3.8.3", - "resolved": "https://registry.npmjs.org/table/-/table-3.8.3.tgz", - "integrity": "sha1-K7xULw/amGGnVdOUf+/Ys/UThV8=", - "dev": true, - "requires": { - "ajv": "^4.7.0", - "ajv-keywords": "^1.0.0", - "chalk": "^1.1.1", - "lodash": "^4.0.0", - "slice-ansi": "0.0.4", - "string-width": "^2.0.0" - }, - "dependencies": { - "ajv": { - "version": "4.11.8", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", - "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=", - "dev": true, - "requires": { - "co": "^4.6.0", - "json-stable-stringify": "^1.0.1" - } - }, - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - }, - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - } - }, - "co": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", - "dev": true - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - } - } - }, - "text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", - "dev": true - }, - "textlint": { - "version": "11.3.1", - "resolved": "https://registry.npmjs.org/textlint/-/textlint-11.3.1.tgz", - "integrity": "sha512-svbO/fhj7dLTJcdKgrW5fJtNRHoFFVL+sutsKBmNUcSJgvgWteLOUZAKT/dp/4S0QfkwkpNOts7Bzn9T+0h0Cw==", - "dev": true, - "requires": { - "@textlint/ast-node-types": "^4.2.4", - "@textlint/ast-traverse": "^2.1.5", - "@textlint/feature-flag": "^3.1.3", - "@textlint/fixer-formatter": "^3.1.8", - "@textlint/kernel": "^3.1.8", - "@textlint/linter-formatter": "^3.1.7", - "@textlint/module-interop": "^1.0.1", - "@textlint/textlint-plugin-markdown": "^5.1.8", - "@textlint/textlint-plugin-text": "^4.1.8", - "@textlint/types": "^1.2.1", - "@textlint/utils": "^1.0.2", - "@types/bluebird": "^3.5.18", - "bluebird": "^3.0.5", - "debug": "^4.1.1", - "deep-equal": "^1.0.1", - "file-entry-cache": "^5.0.1", - "get-stdin": "^5.0.1", - "glob": "^7.1.3", - "is-file": "^1.0.0", - "log-symbols": "^1.0.2", - "map-like": "^2.0.0", - "md5": "^2.2.1", - "mkdirp": "^0.5.0", - "optionator": "^0.8.0", - "path-to-glob-pattern": "^1.0.2", - "rc-config-loader": "^2.0.4", - "read-pkg": "^1.1.0", - "read-pkg-up": "^3.0.0", - "structured-source": "^3.0.2", - "try-resolve": "^1.0.1", - "unique-concat": "^0.2.2" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - }, - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - } - }, - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "get-stdin": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-5.0.1.tgz", - "integrity": "sha1-Ei4WFZHiH/TFJTAwVpPyDmOTo5g=", - "dev": true - }, - "glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "log-symbols": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-1.0.2.tgz", - "integrity": "sha1-N2/3tY6jCGoPCfrMdGF+ylAeGhg=", - "dev": true, - "requires": { - "chalk": "^1.0.0" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "read-pkg": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", - "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", - "dev": true, - "requires": { - "load-json-file": "^1.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^1.0.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - } - } - }, - "textlint-filter-rule-comments": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/textlint-filter-rule-comments/-/textlint-filter-rule-comments-1.2.2.tgz", - "integrity": "sha1-OnLElJlOBo4OSqrQ8k6nz+M4UDo=", - "dev": true - }, - "textlint-rule-common-misspellings": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/textlint-rule-common-misspellings/-/textlint-rule-common-misspellings-1.0.1.tgz", - "integrity": "sha1-jEEzzzu1mqFZGZ0sm87RJBM2V3Q=", - "dev": true, - "requires": { - "misspellings": "^1.0.1", - "textlint-rule-helper": "^1.1.5" - } - }, - "textlint-rule-helper": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/textlint-rule-helper/-/textlint-rule-helper-1.2.0.tgz", - "integrity": "sha1-vmjUelFGsW3RFieMmut701YxzNo=", - "dev": true, - "requires": { - "unist-util-visit": "^1.1.0" - } - }, - "textlint-rule-no-dead-link": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/textlint-rule-no-dead-link/-/textlint-rule-no-dead-link-4.6.2.tgz", - "integrity": "sha512-f11iwmihzQhWwO8KCa4sYMhiZhnfRYwXQbuFILZVoNhBRfcxYF3A19N/poYgAcCJRre9GkCv7/B2RiraxKUUjA==", - "dev": true, - "requires": { - "fs-extra": "^8.1.0", - "get-url-origin": "^1.0.1", - "minimatch": "^3.0.4", - "node-fetch": "^2.6.0", - "p-memoize": "^3.1.0", - "p-queue": "^6.2.0", - "textlint-rule-helper": "^2.1.1" - }, - "dependencies": { - "textlint-rule-helper": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/textlint-rule-helper/-/textlint-rule-helper-2.1.1.tgz", - "integrity": "sha512-6fxgHzoJVkjl3LaC1b2Egi+5wbhG4i0pU0knJmQujVhxIJ3D3AcQQZPs457xKAi5xKz1WayYeTeJ5jrD/hnO7g==", - "dev": true, - "requires": { - "@textlint/ast-node-types": "^4.2.1", - "@textlint/types": "^1.1.2", - "structured-source": "^3.0.2", - "unist-util-visit": "^1.1.0" - } - } - } - }, - "textlint-rule-terminology": { - "version": "1.1.30", - "resolved": "https://registry.npmjs.org/textlint-rule-terminology/-/textlint-rule-terminology-1.1.30.tgz", - "integrity": "sha512-PsLiridAdaLyho236adWnTEAbAcxxUsxVqaXWaJce+aRsjCOeyYPBLNRisFGz90KZ0S1NDYT/v5CvzBrgsiuzQ==", - "dev": true, - "requires": { - "lodash": "^4.17.4", - "strip-json-comments": "^2.0.1", - "textlint-rule-helper": "^2.0.0" - }, - "dependencies": { - "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 - }, - "textlint-rule-helper": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/textlint-rule-helper/-/textlint-rule-helper-2.1.1.tgz", - "integrity": "sha512-6fxgHzoJVkjl3LaC1b2Egi+5wbhG4i0pU0knJmQujVhxIJ3D3AcQQZPs457xKAi5xKz1WayYeTeJ5jrD/hnO7g==", - "dev": true, - "requires": { - "@textlint/ast-node-types": "^4.2.1", - "@textlint/types": "^1.1.2", - "structured-source": "^3.0.2", - "unist-util-visit": "^1.1.0" - } - } - } - }, - "textlint-rule-write-good": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/textlint-rule-write-good/-/textlint-rule-write-good-1.6.2.tgz", - "integrity": "sha1-PHmwQJExnU6L5ftELFlr9QDoST4=", - "dev": true, - "requires": { - "textlint-rule-helper": "^2.0.0", - "write-good": "^0.11.0" - }, - "dependencies": { - "textlint-rule-helper": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/textlint-rule-helper/-/textlint-rule-helper-2.1.1.tgz", - "integrity": "sha512-6fxgHzoJVkjl3LaC1b2Egi+5wbhG4i0pU0knJmQujVhxIJ3D3AcQQZPs457xKAi5xKz1WayYeTeJ5jrD/hnO7g==", - "dev": true, - "requires": { - "@textlint/ast-node-types": "^4.2.1", - "@textlint/types": "^1.1.2", - "structured-source": "^3.0.2", - "unist-util-visit": "^1.1.0" - } - } - } - }, - "through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", - "dev": true - }, - "timekeeper": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/timekeeper/-/timekeeper-2.2.0.tgz", - "integrity": "sha512-W3AmPTJWZkRwu+iSNxPIsLZ2ByADsOLbbLxe46UJyWj3mlYLlwucKiq+/dPm0l9wTzqoF3/2PH0AGFCebjq23A==", - "dev": true - }, - "tmp": { - "version": "0.0.33", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", - "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", - "dev": true, - "requires": { - "os-tmpdir": "~1.0.2" - } - }, - "to-object-path": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", - "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "to-regex": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", - "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", - "dev": true, - "requires": { - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "regex-not": "^1.0.2", - "safe-regex": "^1.1.0" - } - }, - "to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", - "dev": true, - "requires": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" - } - }, - "to-vfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/to-vfile/-/to-vfile-4.0.0.tgz", - "integrity": "sha512-Y7EDM+uoU8TZxF5ej2mUR0dLO4qbuuNRnJKxEht2QJWEq2421pyG1D1x8YxPKmyTc6nHh7Td/jLGFxYo+9vkLA==", - "dev": true, - "requires": { - "is-buffer": "^2.0.0", - "vfile": "^3.0.0" - } - }, - "toidentifier": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", - "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==" - }, - "too-wordy": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/too-wordy/-/too-wordy-0.1.6.tgz", - "integrity": "sha512-MV5F74YF9+UYsvwXGXTh+5YP3EqH/ivwWfyFE2/YHWQQxm9jDPmkIC23nkN133Ye4nO3HTXmiMcfGqJ5xRPfOA==", - "dev": true - }, - "tough-cookie": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", - "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", - "requires": { - "psl": "^1.1.24", - "punycode": "^1.4.1" - }, - "dependencies": { - "punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" - } - } - }, - "traverse": { - "version": "0.6.6", - "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.6.6.tgz", - "integrity": "sha1-y99WD9e5r2MlAv7UD5GMFX6pcTc=", - "dev": true - }, - "trim": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/trim/-/trim-0.0.1.tgz", - "integrity": "sha1-WFhUf2spB1fulczMZm+1AITEYN0=", - "dev": true - }, - "trim-trailing-lines": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/trim-trailing-lines/-/trim-trailing-lines-1.1.3.tgz", - "integrity": "sha512-4ku0mmjXifQcTVfYDfR5lpgV7zVqPg6zV9rdZmwOPqq0+Zq19xDqEgagqVbc4pOOShbncuAOIs59R3+3gcF3ZA==", - "dev": true - }, - "trough": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/trough/-/trough-1.0.5.tgz", - "integrity": "sha512-rvuRbTarPXmMb79SmzEp8aqXNKcK+y0XaB298IXueQ8I2PsrATcPBCSPyK/dDNa2iWOhKlfNnOjdAOTBU/nkFA==", - "dev": true - }, - "try-resolve": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/try-resolve/-/try-resolve-1.0.1.tgz", - "integrity": "sha1-z95vq9ctY+V5fPqrhzq76OcA6RI=", - "dev": true - }, - "tslib": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz", - "integrity": "sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q==", - "dev": true - }, - "tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", - "requires": { - "safe-buffer": "^5.0.1" - } - }, - "tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" - }, - "type-check": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", - "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", - "dev": true, - "requires": { - "prelude-ls": "~1.1.2" - } - }, - "type-detect": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", - "dev": true - }, - "type-is": { - "version": "1.6.16", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz", - "integrity": "sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q==", - "requires": { - "media-typer": "0.3.0", - "mime-types": "~2.1.18" - } - }, - "typedarray": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", - "dev": true - }, - "uglify-js": { - "version": "3.5.9", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.5.9.tgz", - "integrity": "sha512-WpT0RqsDtAWPNJK955DEnb6xjymR8Fn0OlK4TT4pS0ASYsVPqr5ELhgwOwLCP5J5vHeJ4xmMmz3DEgdqC10JeQ==", - "dev": true, - "optional": true, - "requires": { - "commander": "~2.20.0", - "source-map": "~0.6.1" - }, - "dependencies": { - "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, - "optional": true - } - } - }, - "underscore": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.9.1.tgz", - "integrity": "sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg==" - }, - "unherit": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/unherit/-/unherit-1.1.3.tgz", - "integrity": "sha512-Ft16BJcnapDKp0+J/rqFC3Rrk6Y/Ng4nzsC028k2jdDII/rdZ7Wd3pPT/6+vIIxRagwRc9K0IUX0Ra4fKvw+WQ==", - "dev": true, - "requires": { - "inherits": "^2.0.0", - "xtend": "^4.0.0" - } - }, - "unified": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/unified/-/unified-7.1.0.tgz", - "integrity": "sha512-lbk82UOIGuCEsZhPj8rNAkXSDXd6p0QLzIuSsCdxrqnqU56St4eyOB+AlXsVgVeRmetPTYydIuvFfpDIed8mqw==", - "dev": true, - "requires": { - "@types/unist": "^2.0.0", - "@types/vfile": "^3.0.0", - "bail": "^1.0.0", - "extend": "^3.0.0", - "is-plain-obj": "^1.1.0", - "trough": "^1.0.0", - "vfile": "^3.0.0", - "x-is-string": "^0.1.0" - } - }, - "unified-args": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/unified-args/-/unified-args-6.0.0.tgz", - "integrity": "sha512-1m2pGiTClgcCtCvgtABkJLze8JJiZpzsqujRhzBjZsRwaIIU1Yj36YHY6t2RvidO8d6fucZdk3KX+8eS4+uv9g==", - "dev": true, - "requires": { - "camelcase": "^5.0.0", - "chalk": "^2.0.0", - "chokidar": "^2.0.0", - "fault": "^1.0.2", - "json5": "^1.0.0", - "minimist": "^1.2.0", - "text-table": "^0.2.0", - "unified-engine": "^6.0.0" - } - }, - "unified-engine": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/unified-engine/-/unified-engine-6.0.1.tgz", - "integrity": "sha512-iDJYH82TgcezQA4IZzhCNJQx7vBsGk4h9s4Q7Fscrb3qcPsxBqVrVNYez2W3sBVTxuU1bFAhyRpA6ba/R4j93A==", - "dev": true, - "requires": { - "concat-stream": "^1.5.1", - "debug": "^3.1.0", - "fault": "^1.0.0", - "fn-name": "^2.0.1", - "glob": "^7.0.3", - "ignore": "^3.2.0", - "is-empty": "^1.0.0", - "is-hidden": "^1.0.1", - "is-object": "^1.0.1", - "js-yaml": "^3.6.1", - "load-plugin": "^2.0.0", - "parse-json": "^4.0.0", - "to-vfile": "^4.0.0", - "trough": "^1.0.0", - "unist-util-inspect": "^4.1.2", - "vfile-reporter": "^5.0.0", - "vfile-statistics": "^1.1.0", - "x-is-string": "^0.1.0", - "xtend": "^4.0.1" - }, - "dependencies": { - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - } - } - }, - "unified-lint-rule": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/unified-lint-rule/-/unified-lint-rule-1.0.4.tgz", - "integrity": "sha512-q9wY6S+d38xRAuWQVOMjBQYi7zGyKkY23ciNafB8JFVmDroyKjtytXHCg94JnhBCXrNqpfojo3+8D+gmF4zxJQ==", - "dev": true, - "requires": { - "wrapped": "^1.0.1" - } - }, - "unified-message-control": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/unified-message-control/-/unified-message-control-1.0.4.tgz", - "integrity": "sha512-e1dEtN4Z/TvLn/qHm+xeZpzqhJTtfZusFErk336kkZVpqrJYiV9ptxq+SbRPFMlN0OkjDYHmVJ929KYjsMTo3g==", - "dev": true, - "requires": { - "trim": "0.0.1", - "unist-util-visit": "^1.0.0", - "vfile-location": "^2.0.0" - } - }, - "union-value": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", - "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", - "dev": true, - "requires": { - "arr-union": "^3.1.0", - "get-value": "^2.0.6", - "is-extendable": "^0.1.1", - "set-value": "^2.0.1" - } - }, - "unique-concat": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/unique-concat/-/unique-concat-0.2.2.tgz", - "integrity": "sha1-khD5vcqsxeHjkpSQ18AZ35bxhxI=", - "dev": true - }, - "unist-util-generated": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/unist-util-generated/-/unist-util-generated-1.1.5.tgz", - "integrity": "sha512-1TC+NxQa4N9pNdayCYA1EGUOCAO0Le3fVp7Jzns6lnua/mYgwHo0tz5WUAfrdpNch1RZLHc61VZ1SDgrtNXLSw==", - "dev": true - }, - "unist-util-inspect": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/unist-util-inspect/-/unist-util-inspect-4.1.4.tgz", - "integrity": "sha512-7xxyvKiZ1SC9vL5qrMqKub1T31gRHfau4242F69CcaOrXt//5PmRVOmDZ36UAEgiT+tZWzmQmbNZn+mVtnR9HQ==", - "dev": true, - "requires": { - "is-empty": "^1.0.0" - } - }, - "unist-util-is": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-3.0.0.tgz", - "integrity": "sha512-sVZZX3+kspVNmLWBPAB6r+7D9ZgAFPNWm66f7YNb420RlQSbn+n8rG8dGZSkrER7ZIXGQYNm5pqC3v3HopH24A==", - "dev": true - }, - "unist-util-position": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-3.0.4.tgz", - "integrity": "sha512-tWvIbV8goayTjobxDIr4zVTyG+Q7ragMSMeKC3xnPl9xzIc0+she8mxXLM3JVNDDsfARPbCd3XdzkyLdo7fF3g==", - "dev": true - }, - "unist-util-remove-position": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-1.1.4.tgz", - "integrity": "sha512-tLqd653ArxJIPnKII6LMZwH+mb5q+n/GtXQZo6S6csPRs5zB0u79Yw8ouR3wTw8wxvdJFhpP6Y7jorWdCgLO0A==", - "dev": true, - "requires": { - "unist-util-visit": "^1.1.0" - } - }, - "unist-util-stringify-position": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-2.0.2.tgz", - "integrity": "sha512-nK5n8OGhZ7ZgUwoUbL8uiVRwAbZyzBsB/Ddrlbu6jwwubFza4oe15KlyEaLNMXQW1svOQq4xesUeqA85YrIUQA==", - "dev": true, - "requires": { - "@types/unist": "^2.0.2" - } - }, - "unist-util-visit": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-1.4.1.tgz", - "integrity": "sha512-AvGNk7Bb//EmJZyhtRUnNMEpId/AZ5Ph/KUpTI09WHQuDZHKovQ1oEv3mfmKpWKtoMzyMC4GLBm1Zy5k12fjIw==", - "dev": true, - "requires": { - "unist-util-visit-parents": "^2.0.0" - } - }, - "unist-util-visit-parents": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-2.1.2.tgz", - "integrity": "sha512-DyN5vD4NE3aSeB+PXYNKxzGsfocxp6asDc2XXE3b0ekO2BaRUpBicbbUygfSvYfUz1IkmjFR1YF7dPklraMZ2g==", - "dev": true, - "requires": { - "unist-util-is": "^3.0.0" - } - }, - "universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", - "dev": true - }, - "unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" - }, - "unset-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", - "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", - "dev": true, - "requires": { - "has-value": "^0.3.1", - "isobject": "^3.0.0" - }, - "dependencies": { - "has-value": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", - "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", - "dev": true, - "requires": { - "get-value": "^2.0.3", - "has-values": "^0.1.4", - "isobject": "^2.0.0" - }, - "dependencies": { - "isobject": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", - "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "dev": true, - "requires": { - "isarray": "1.0.0" - } - } - } - }, - "has-values": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", - "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", - "dev": true - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - } - } - }, - "untildify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/untildify/-/untildify-2.1.0.tgz", - "integrity": "sha1-F+soB5h/dpUunASF/DEdBqgmouA=", - "dev": true, - "requires": { - "os-homedir": "^1.0.0" - } - }, - "upath": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", - "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==", - "dev": true - }, - "uri-js": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", - "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", - "requires": { - "punycode": "^2.1.0" - } - }, - "urix": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", - "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", - "dev": true - }, - "use": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", - "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", - "dev": true - }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true - }, - "utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" - }, - "uuid": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", - "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==" - }, - "validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "dev": true, - "requires": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, - "vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" - }, - "verror": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", - "requires": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" - } - }, - "vfile": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/vfile/-/vfile-3.0.1.tgz", - "integrity": "sha512-y7Y3gH9BsUSdD4KzHsuMaCzRjglXN0W2EcMf0gpvu6+SbsGhMje7xDc8AEoeXy6mIwCKMI6BkjMsRjzQbhMEjQ==", - "dev": true, - "requires": { - "is-buffer": "^2.0.0", - "replace-ext": "1.0.0", - "unist-util-stringify-position": "^1.0.0", - "vfile-message": "^1.0.0" - }, - "dependencies": { - "unist-util-stringify-position": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-1.1.2.tgz", - "integrity": "sha512-pNCVrk64LZv1kElr0N1wPiHEUoXNVFERp+mlTg/s9R5Lwg87f9bM/3sQB99w+N9D/qnM9ar3+AKDBwo/gm/iQQ==", - "dev": true - }, - "vfile-message": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-1.1.1.tgz", - "integrity": "sha512-1WmsopSGhWt5laNir+633LszXvZ+Z/lxveBf6yhGsqnQIhlhzooZae7zV6YVM1Sdkw68dtAW3ow0pOdPANugvA==", - "dev": true, - "requires": { - "unist-util-stringify-position": "^1.1.1" - } - } - } - }, - "vfile-location": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-2.0.6.tgz", - "integrity": "sha512-sSFdyCP3G6Ka0CEmN83A2YCMKIieHx0EDaj5IDP4g1pa5ZJ4FJDvpO0WODLxo4LUX4oe52gmSCK7Jw4SBghqxA==", - "dev": true - }, - "vfile-message": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-2.0.2.tgz", - "integrity": "sha512-gNV2Y2fDvDOOqq8bEe7cF3DXU6QgV4uA9zMR2P8tix11l1r7zju3zry3wZ8sx+BEfuO6WQ7z2QzfWTvqHQiwsA==", - "dev": true, - "requires": { - "@types/unist": "^2.0.0", - "unist-util-stringify-position": "^2.0.0" - } - }, - "vfile-reporter": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/vfile-reporter/-/vfile-reporter-5.1.2.tgz", - "integrity": "sha512-b15sTuss1wOPWVlyWOvu+n6wGJ/eTYngz3uqMLimQvxZ+Q5oFQGYZZP1o3dR9sk58G5+wej0UPCZSwQBX/mzrQ==", - "dev": true, - "requires": { - "repeat-string": "^1.5.0", - "string-width": "^2.0.0", - "supports-color": "^5.0.0", - "unist-util-stringify-position": "^2.0.0", - "vfile-sort": "^2.1.2", - "vfile-statistics": "^1.1.0" - }, - "dependencies": { - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "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" - } - } - } - }, - "vfile-sort": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/vfile-sort/-/vfile-sort-2.2.1.tgz", - "integrity": "sha512-5dt7xEhC44h0uRQKhbM2JAe0z/naHphIZlMOygtMBM9Nn0pZdaX5fshhwWit9wvsuP8t/wp43nTDRRErO1WK8g==", - "dev": true - }, - "vfile-statistics": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/vfile-statistics/-/vfile-statistics-1.1.3.tgz", - "integrity": "sha512-CstaK/ebTz1W3Qp41Bt9Lj/2DmumFsCwC2sKahDNSPh0mPh7/UyMLCoU8ZBX34CRU0d61B4W41yIFsV0NKMZeA==", - "dev": true - }, - "watch": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/watch/-/watch-1.0.2.tgz", - "integrity": "sha1-NApxe952Vyb6CqB9ch4BR6VR3ww=", - "dev": true, - "requires": { - "exec-sh": "^0.2.0", - "minimist": "^1.2.0" - } - }, - "weasel-words": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/weasel-words/-/weasel-words-0.1.1.tgz", - "integrity": "sha1-cTeUZYXHP+RIggE4U70ADF1oek4=", - "dev": true - }, - "which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - }, - "which-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", - "dev": true - }, - "wide-align": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", - "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", - "dev": true, - "requires": { - "string-width": "^1.0.2 || 2" - } - }, - "wordwrap": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", - "dev": true - }, - "wrap-ansi": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", - "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", - "dev": true, - "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - } - } - }, - "wrapped": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/wrapped/-/wrapped-1.0.1.tgz", - "integrity": "sha1-x4PZ2Aeyc+mwHoUWgKk4yHyQckI=", - "dev": true, - "requires": { - "co": "3.1.0", - "sliced": "^1.0.1" - } - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true - }, - "write": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/write/-/write-1.0.3.tgz", - "integrity": "sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==", - "dev": true, - "requires": { - "mkdirp": "^0.5.1" - } - }, - "write-good": { - "version": "0.11.3", - "resolved": "https://registry.npmjs.org/write-good/-/write-good-0.11.3.tgz", - "integrity": "sha512-fDKIHO5wCzTLCOGNJl1rzzJrZlTIzfZl8msOoJQZzRhYo0X/tFTm4+2B1zTibFYK01Nnd1kLZBjj4xjcFLePNQ==", - "dev": true, - "requires": { - "adverb-where": "0.0.9", - "e-prime": "^0.10.2", - "no-cliches": "^0.1.0", - "object.assign": "^4.0.4", - "passive-voice": "^0.1.0", - "too-wordy": "^0.1.4", - "weasel-words": "^0.1.1" - } - }, - "x-is-string": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/x-is-string/-/x-is-string-0.1.0.tgz", - "integrity": "sha1-R0tQhlrzpJqcRlfwWs0UVFj3fYI=", - "dev": true - }, - "xml-escape": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/xml-escape/-/xml-escape-1.1.0.tgz", - "integrity": "sha1-OQTBQ/qOs6ADDsZG0pAqLxtwbEQ=", - "dev": true - }, - "xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "dev": true - }, - "y18n": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", - "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", - "dev": true - }, - "yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", - "dev": true - }, - "yargs": { - "version": "13.2.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.2.2.tgz", - "integrity": "sha512-WyEoxgyTD3w5XRpAQNYUB9ycVH/PQrToaTXdYXRdOXvEy1l19br+VJsc0vcO8PTGg5ro/l/GY7F/JMEBmI0BxA==", - "dev": true, - "requires": { - "cliui": "^4.0.0", - "find-up": "^3.0.0", - "get-caller-file": "^2.0.1", - "os-locale": "^3.1.0", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^3.0.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^13.0.0" - }, - "dependencies": { - "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 - }, - "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" - } - }, - "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" - } - } - } - }, - "yargs-parser": { - "version": "13.0.0", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.0.0.tgz", - "integrity": "sha512-w2LXjoL8oRdRQN+hOyppuXs+V/fVAYtpcrRxZuF7Kt/Oc+Jr2uAcVntaUTNT6w5ihoWfFDpNY8CPx1QskxZ/pw==", - "dev": true, - "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } - }, - "yargs-unparser": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-1.5.0.tgz", - "integrity": "sha512-HK25qidFTCVuj/D1VfNiEndpLIeJN78aqgR23nL3y4N0U/91cOAzqfHlF8n2BvoNDcZmJKin3ddNSvOxSr8flw==", - "dev": true, - "requires": { - "flat": "^4.1.0", - "lodash": "^4.17.11", - "yargs": "^12.0.5" - }, - "dependencies": { - "get-caller-file": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", - "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", - "dev": true - }, - "require-main-filename": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", - "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", - "dev": true - }, - "yargs": { - "version": "12.0.5", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.5.tgz", - "integrity": "sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw==", - "dev": true, - "requires": { - "cliui": "^4.0.0", - "decamelize": "^1.2.0", - "find-up": "^3.0.0", - "get-caller-file": "^1.0.1", - "os-locale": "^3.0.0", - "require-directory": "^2.1.1", - "require-main-filename": "^1.0.1", - "set-blocking": "^2.0.0", - "string-width": "^2.0.0", - "which-module": "^2.0.0", - "y18n": "^3.2.1 || ^4.0.0", - "yargs-parser": "^11.1.1" - } - }, - "yargs-parser": { - "version": "11.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-11.1.1.tgz", - "integrity": "sha512-C6kB/WJDiaxONLJQnF8ccx9SEeoTTLek8RVbaOIsrAUS8VrBEXfmeSnCZxygc+XC2sNMBIwOOnfcxiynjHsVSQ==", - "dev": true, - "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } - } - } - } - } -} From c35b0ba32ebc9a0d08631065a7efde7a3d637fc4 Mon Sep 17 00:00:00 2001 From: Jason Fox Date: Fri, 17 Jul 2020 18:11:29 +0200 Subject: [PATCH 13/27] Fix broken test from merge --- lib/plugins/multiEntity.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/plugins/multiEntity.js b/lib/plugins/multiEntity.js index 703d9a3d3..48640c0af 100644 --- a/lib/plugins/multiEntity.js +++ b/lib/plugins/multiEntity.js @@ -66,7 +66,7 @@ function filterOutMultientitiesNgsi1(originalAttrs, meAttributes) { */ function filterOutMultientitiesNgsi2(originalAttrs, meAttributes) { const result = {}; - for (const att in originalAttrs) { + for (let att in originalAttrs) { if (originalAttrs.hasOwnProperty(att)) { if (!_.contains(meAttributes, att)) { result[att] = originalAttrs[att]; @@ -225,8 +225,9 @@ function propagateTimestamp(entity, entities) { } entities.map(function(en) { + let att; // Set timestamp metadata in attributes (except TimeInstant attribute itself) - for (const att in en && att !== constants.TIMESTAMP_ATTRIBUTE) { + for (att in en && att !== constants.TIMESTAMP_ATTRIBUTE) { if (en.hasOwnProperty(att) && att !== 'id' && att !== 'type') { if (!en[att].metadata) { en[att].metadata = {}; From c0a6b9629964278ea06ad09ac24bc1c2fcccbef7 Mon Sep 17 00:00:00 2001 From: Jason Fox Date: Thu, 10 Sep 2020 19:34:34 +0200 Subject: [PATCH 14/27] Run prettier, fix docs. --- README.md | 6 +- doc/advanced-topics.md | 2 +- doc/architecture.md | 4 +- doc/getting-started.md | 20 +++--- doc/howto.md | 120 +++++++++++++++++----------------- doc/index.md | 2 +- doc/installationguide.md | 2 +- doc/northboundinteractions.md | 6 +- doc/usermanual.md | 32 ++++----- package.json | 2 +- 10 files changed, 98 insertions(+), 98 deletions(-) diff --git a/README.md b/README.md index 816d2c8ba..ebe3a29f3 100644 --- a/README.md +++ b/README.md @@ -71,7 +71,7 @@ IoT Agent In order to use the library within your own IoT Agent, you must first you require it before use: ```javascript -const iotagentLib = require('iotagent-node-lib'); +const iotagentLib = require("iotagent-node-lib"); ``` Information about how to configure the Library can be found at the corresponding section of the @@ -307,7 +307,7 @@ array that can be directly imported into other Command-Line tools, using the fol - Require the `iotagent-node-lib` command-line module in your command-line tool: ```javascript -var iotaCommands = require('iotagent-node-lib').commandLine; +var iotaCommands = require("iotagent-node-lib").commandLine; ``` - Initialize the command-line utils (the initialization function takes two arguments, that will be explained in detail @@ -326,7 +326,7 @@ commands = commands.concat(commands, iotaCommands.commands); - Execute the command-line interpreter as usual: ```javascript -clUtils.initialize(commandLine.commands, 'IoT Agent tester> '); +clUtils.initialize(commandLine.commands, "IoT Agent tester> "); ``` The command-line module makes use of two configuration objects. Both can be shown and edited in the command-line using diff --git a/doc/advanced-topics.md b/doc/advanced-topics.md index 4e98f3214..1d44bd120 100644 --- a/doc/advanced-topics.md +++ b/doc/advanced-topics.md @@ -138,7 +138,7 @@ The library provides some plugins out of the box, in the `dataPlugins` collectio use the `addQueryMiddleware` and `addUpdateMiddleware` functions with the selected plugin, as in the example: ```javascript -var iotaLib = require('iotagent-node-lib'); +var iotaLib = require("iotagent-node-lib"); iotaLib.addUpdateMiddleware(iotaLib.dataPlugins.compressTimestamp.update); iotaLib.addQueryMiddleware(iotaLib.dataPlugins.compressTimestamp.query); diff --git a/doc/architecture.md b/doc/architecture.md index db94266da..b975d153d 100644 --- a/doc/architecture.md +++ b/doc/architecture.md @@ -32,7 +32,7 @@ basis preprovisioning the devices). Device measures can have three different beh The following sequence diagram shows the different NGSI interactions an IoT Agent makes with the Context Broker, explained in the following subsections (using the example of a OMA Lightweight M2M device). -![General ](./img/ngsiInteractions.png 'NGSI Interactions') +![General ](./img/ngsiInteractions.png "NGSI Interactions") Be aware that the IoT Agents are only required to support NGSI10 operations `updateContext` and `queryContext` in their standard formats (currently in JSON format; XML deprecated) but will not answer to NGSI9 operations (or NGSI convenience @@ -207,7 +207,7 @@ the concrete IoT Agent implementations will be to map between the native device The following figure offers a graphical example of how a COAP IoT Agent work, ordered from the registration of the device to a command update to the device. -![General ](./img/iotAgentLib.png 'Architecture Overview') +![General ](./img/iotAgentLib.png "Architecture Overview") ### The `TimeInstant` element diff --git a/doc/getting-started.md b/doc/getting-started.md index c594d907f..236858216 100644 --- a/doc/getting-started.md +++ b/doc/getting-started.md @@ -10,23 +10,23 @@ custom settings may also be required dependent upon the actual IoT Agent used. ```javascript config = { - logLevel: 'DEBUG', + logLevel: "DEBUG", contextBroker: { - host: 'orion', - port: '1026' + host: "orion", + port: "1026", }, server: { port: 4041, - host: '0.0.0.0' + host: "0.0.0.0", }, deviceRegistry: { - type: 'memory' + type: "memory", }, - service: 'openiot', - subservice: '/', - providerUrl: 'http://iot-agent:4041', - deviceRegistrationDuration: 'P1M', - defaultType: 'Thing' + service: "openiot", + subservice: "/", + providerUrl: "http://iot-agent:4041", + deviceRegistrationDuration: "P1M", + defaultType: "Thing", }; ``` diff --git a/doc/howto.md b/doc/howto.md index ff7520146..28fdd82ec 100644 --- a/doc/howto.md +++ b/doc/howto.md @@ -75,12 +75,12 @@ folder of your project. Remember to change the Context Broker IP to your local C Now we can begin with the code of our IoT Agent. The very minimum code we need to start an IoT Agent is the following: ```javascript -var iotAgentLib = require('iotagent-node-lib'), - config = require('./config'); +var iotAgentLib = require("iotagent-node-lib"), + config = require("./config"); -iotAgentLib.activate(config, function(error) { +iotAgentLib.activate(config, function (error) { if (error) { - console.log('There was an error activating the IOTA'); + console.log("There was an error activating the IOTA"); process.exit(1); } }); @@ -112,10 +112,10 @@ In order to add the Express dependency to your project, add the following line t The require section would end up like this (the standard `http` module is also needed): ```javascript -var iotAgentLib = require('iotagent-node-lib'), - http = require('http'), - express = require('express'), - config = require('./config'); +var iotAgentLib = require("iotagent-node-lib"), + http = require("http"), + express = require("express"), + config = require("./config"); ``` And install the dependencies as usual with `npm install`. You will have to require both `express` and `http` in your @@ -129,16 +129,16 @@ function initSouthbound(callback) { southboundServer = { server: null, app: express(), - router: express.Router() + router: express.Router(), }; - southboundServer.app.set('port', 8080); - southboundServer.app.set('host', '0.0.0.0'); + southboundServer.app.set("port", 8080); + southboundServer.app.set("host", "0.0.0.0"); - southboundServer.router.get('/iot/d', manageULRequest); + southboundServer.router.get("/iot/d", manageULRequest); southboundServer.server = http.createServer(southboundServer.app); - southboundServer.app.use('/', southboundServer.router); - southboundServer.server.listen(southboundServer.app.get('port'), southboundServer.app.get('host'), callback); + southboundServer.app.use("/", southboundServer.router); + southboundServer.server.listen(southboundServer.app.get("port"), southboundServer.app.get("host"), callback); } ``` @@ -151,21 +151,21 @@ would be as follows: function manageULRequest(req, res, next) { var values; - iotAgentLib.retrieveDevice(req.query.i, req.query.k, function(error, device) { + iotAgentLib.retrieveDevice(req.query.i, req.query.k, function (error, device) { if (error) { res.status(404).send({ - message: "Couldn't find the device: " + JSON.stringify(error) + message: "Couldn't find the device: " + JSON.stringify(error), }); } else { values = parseUl(req.query.d, device); - iotAgentLib.update(device.name, device.type, '', values, device, function(error) { + iotAgentLib.update(device.name, device.type, "", values, device, function (error) { if (error) { res.status(500).send({ - message: 'Error updating the device' + message: "Error updating the device", }); } else { res.status(200).send({ - message: 'Device successfully updated' + message: "Device successfully updated", }); } }); @@ -190,17 +190,17 @@ function parseUl(data, device) { } function createAttribute(element) { - var pair = element.split('|'), + var pair = element.split("|"), attribute = { name: pair[0], value: pair[1], - type: findType(pair[0]) + type: findType(pair[0]), }; return attribute; } - return data.split(',').map(createAttribute); + return data.split(",").map(createAttribute); } ``` @@ -225,16 +225,16 @@ The last thing to do is to invoke the initialization function inside the IoT Age show the modifications in the `activate()` function: ```javascript -iotAgentLib.activate(config, function(error) { +iotAgentLib.activate(config, function (error) { if (error) { - console.log('There was an error activating the IOTA'); + console.log("There was an error activating the IOTA"); process.exit(1); } else { - initSouthbound(function(error) { + initSouthbound(function (error) { if (error) { - console.log('Could not initialize South bound API due to the following error: %s', error); + console.log("Could not initialize South bound API due to the following error: %s", error); } else { - console.log('Both APIs started successfully'); + console.log("Both APIs started successfully"); } }); } @@ -286,7 +286,7 @@ A HTTP request library will be needed in order to make those calls. To this exte used. In order to do so, add the following require statement to the initialization code: ```javascript -request = require('request'); +request = require("request"); ``` and add the `request` dependency to the `package.json` file: @@ -303,11 +303,11 @@ and add the `request` dependency to the `package.json` file: The require section should now look like this: ```javascript -var iotAgentLib = require('iotagent-node-lib'), - http = require('http'), - express = require('express'), - request = require('request'), - config = require('./config'); +var iotAgentLib = require("iotagent-node-lib"), + http = require("http"), + express = require("express"), + request = require("request"), + config = require("./config"); ``` ### Implementation @@ -321,14 +321,14 @@ for the context provisioning requests. At this point, we should provide two hand ```javascript function queryContextHandler(id, type, service, subservice, attributes, callback) { var options = { - url: 'http://127.0.0.1:9999/iot/d', - method: 'GET', + url: "http://127.0.0.1:9999/iot/d", + method: "GET", qs: { - q: attributes.join() - } + q: attributes.join(), + }, }; - request(options, function(error, response, body) { + request(options, function (error, response, body) { if (error) { callback(error); } else { @@ -350,21 +350,21 @@ attributes). Here is the code for the `createResponse()` function: ```javascript function createResponse(id, type, attributes, body) { - var values = body.split(','), + var values = body.split(","), responses = []; for (var i = 0; i < attributes.length; i++) { responses.push({ name: attributes[i], - type: 'string', - value: values[i] + type: "string", + value: values[i], }); } return { id: id, type: type, - attributes: responses + attributes: responses, }; } ``` @@ -374,21 +374,21 @@ function createResponse(id, type, attributes, body) { ```javascript function updateContextHandler(id, type, service, subservice, attributes, callback) { var options = { - url: 'http://127.0.0.1:9999/iot/d', - method: 'GET', + url: "http://127.0.0.1:9999/iot/d", + method: "GET", qs: { - d: createQueryFromAttributes(attributes) - } + d: createQueryFromAttributes(attributes), + }, }; - request(options, function(error, response, body) { + request(options, function (error, response, body) { if (error) { callback(error); } else { callback(null, { id: id, type: type, - attributes: attributes + attributes: attributes, }); } }); @@ -406,13 +406,13 @@ representation of the attributes to the UL type expected by the device: ```javascript function createQueryFromAttributes(attributes) { - var query = ''; + var query = ""; for (var i in attributes) { - query += attributes[i].name + '|' + attributes[i].value; + query += attributes[i].name + "|" + attributes[i].value; if (i != attributes.length - 1) { - query += ','; + query += ","; } } @@ -559,9 +559,9 @@ variable and afterward the value of the multiCore in the `config.js` file. The r (the standard `http` module is also needed): ```javascript -var iotAgent = require('../lib/iotagent-implementation'), - iotAgentLib = require('iotagent-node-lib'), - config = require('./config'); +var iotAgent = require("../lib/iotagent-implementation"), + iotAgentLib = require("iotagent-node-lib"), + config = require("./config"); ``` It is important to mention the purpose of the `iotAgent` variable. It is the proper implementation of the IoT Agent @@ -575,11 +575,11 @@ following code with a callback function to show details about any error during t about starting the IoTAgent: ```javascript -iotAgentLib.startServer(config, iotAgent, function(error) { +iotAgentLib.startServer(config, iotAgent, function (error) { if (error) { - console.log(context, 'Error starting IoT Agent: [%s] Exiting process', error); + console.log(context, "Error starting IoT Agent: [%s] Exiting process", error); } else { - console.log(context, 'IoT Agent started'); + console.log(context, "IoT Agent started"); } }); ``` @@ -606,7 +606,7 @@ handlers themselves. Here we can see the definition of the configuration handler ```javascript function configurationHandler(configuration, callback) { - console.log('\n\n* REGISTERING A NEW CONFIGURATION:\n%s\n\n', JSON.stringify(configuration, null, 4)); + console.log("\n\n* REGISTERING A NEW CONFIGURATION:\n%s\n\n", JSON.stringify(configuration, null, 4)); callback(null, configuration); } ``` @@ -623,8 +623,8 @@ feature, let's use the provisioning handler to change the value of the type of t ```javascript function provisioningHandler(device, callback) { - console.log('\n\n* REGISTERING A NEW DEVICE:\n%s\n\n', JSON.stringify(device, null, 4)); - device.type = 'CertifiedType'; + console.log("\n\n* REGISTERING A NEW DEVICE:\n%s\n\n", JSON.stringify(device, null, 4)); + device.type = "CertifiedType"; callback(null, device); } ``` diff --git a/doc/index.md b/doc/index.md index e9da09ac5..f32f7a6c1 100644 --- a/doc/index.md +++ b/doc/index.md @@ -51,5 +51,5 @@ IoT Agent In order to use the library within your own IoT Agent, you must first you require it before use: ```javascript -const iotagentLib = require('iotagent-node-lib'); +const iotagentLib = require("iotagent-node-lib"); ``` diff --git a/doc/installationguide.md b/doc/installationguide.md index 83e599df7..9e2314934 100644 --- a/doc/installationguide.md +++ b/doc/installationguide.md @@ -129,7 +129,7 @@ used for the same purpose. For instance: ```javascript { - type: 'mongodb'; + type: "mongodb"; } ``` diff --git a/doc/northboundinteractions.md b/doc/northboundinteractions.md index 0817bf525..f0d9d6e20 100644 --- a/doc/northboundinteractions.md +++ b/doc/northboundinteractions.md @@ -261,7 +261,7 @@ Context Element, but with the request as a whole. ### Scenario 1: active attributes -![General ](./img/scenario1.png 'Scenario 1: active attributes') +![General ](./img/scenario1.png "Scenario 1: active attributes") In this scenario, the interaction is started by the device, that is going to actively send a piece of data to the platform. When the IoTAgent receives the data, it sends it to the Context Broker through a P1 request. The Context @@ -275,7 +275,7 @@ updating process, and can occur at any time (they are to completely different pr ### Scenario 2: lazy attributes -![General ](./img/scenario2.png 'Scenario 2: lazy attributes') +![General ](./img/scenario2.png "Scenario 2: lazy attributes") This scenario requires that the attributes that are going to be requested are marked as provided by the IoT Agent, through a registration process (NGSIv9). Examples of this registration process will be provided in the practical section @@ -301,7 +301,7 @@ queries (and thus P2 and R2 payloads). ### Scenario 3: commands -![General ](./img/scenario3.png 'Scenario 3: commands') +![General ](./img/scenario3.png "Scenario 3: commands") This scenario requires that the attributes that are going to be requested are marked as provided by the IoT Agent, through a registration process (NGSIv9). Examples of this registration process will be provided in the practical section diff --git a/doc/usermanual.md b/doc/usermanual.md index 7381a58f1..2c59d6a54 100644 --- a/doc/usermanual.md +++ b/doc/usermanual.md @@ -25,7 +25,7 @@ More values will be added in the future to the library. The applications using t Registry just by using the following function: ```javascript -iotagentLib.statsRegistry.add('statName', statIncrementalValue, callback); +iotagentLib.statsRegistry.add("statName", statIncrementalValue, callback); ``` The first time this function is invoked, it will add the new stat to the registry. Subsequent calls will add the value @@ -80,7 +80,7 @@ In order to use the library, add the following dependency to your package.json f In order to use this library, first you must require it: ```javascript -var iotagentLib = require('iotagent-node-lib'); +var iotagentLib = require("iotagent-node-lib"); ``` The library supports four groups of features, one for each direction of the communication: client-to-server and @@ -265,16 +265,16 @@ Once all the updates have taken place, the callback must be invoked with the upd ```javascript callback(null, { - type: 'TheType', + type: "TheType", isPattern: false, - id: 'EntityID', + id: "EntityID", attributes: [ { - name: 'lumniscence', - type: 'Lumens', - value: '432' - } - ] + name: "lumniscence", + type: "Lumens", + value: "432", + }, + ], }); ``` @@ -303,16 +303,16 @@ The callback must be invoked with the updated Context Element, using the informa ```javascript callback(null, { - type: 'TheType', + type: "TheType", isPattern: false, - id: 'EntityID', + id: "EntityID", attributes: [ { - name: 'lumniscence', - type: 'Lumens', - value: '432' - } - ] + name: "lumniscence", + type: "Lumens", + value: "432", + }, + ], }); ``` diff --git a/package.json b/package.json index 4509153dd..40412d840 100644 --- a/package.json +++ b/package.json @@ -35,7 +35,7 @@ "lint:md": "remark -f '*.md' 'doc/*.md'", "lint:text": "textlint '*.md' 'doc/*.md'", "prettier": "prettier --config .prettierrc.json --write '**/**/**/**/*.js' '**/**/**/*.js' '**/**/*.js' '**/*.js' '*.js'", - "prettier:text": "prettier 'README.md' 'docs/*.md' 'docs/**/*.md' --no-config --tab-width 4 --print-width 120 --write --prose-wrap always", + "prettier:text": "prettier 'README.md' 'doc/*.md' 'doc/**/*.md' --no-config --tab-width 4 --print-width 120 --write --prose-wrap always", "test": "nyc --reporter=text mocha --recursive 'test/**/*.js' --reporter spec --timeout 3000 --ui bdd --exit", "test:coverage": "nyc --reporter=lcov mocha -- --recursive 'test/**/*.js' --reporter spec --exit", "test:coveralls": "npm run test:coverage && cat ./coverage/lcov.info | coveralls && rm -rf ./coverage", From 8de0be20e09ee06fbd12d2f6eafbd535ebf02704 Mon Sep 17 00:00:00 2001 From: Jason Fox Date: Wed, 7 Oct 2020 17:26:23 +0200 Subject: [PATCH 15/27] Increase timeout --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index fc1185700..ad0ecd6f3 100644 --- a/package.json +++ b/package.json @@ -36,8 +36,8 @@ "lint:text": "textlint '*.md' 'doc/*.md'", "prettier": "prettier --config .prettierrc.json --write '**/**/**/**/*.js' '**/**/**/*.js' '**/**/*.js' '**/*.js' '*.js'", "prettier:text": "prettier 'README.md' 'doc/*.md' 'doc/**/*.md' --no-config --tab-width 4 --print-width 120 --write --prose-wrap always", - "test": "nyc --reporter=text mocha --recursive 'test/**/*.js' --reporter spec --timeout 3000 --ui bdd --exit", - "test:coverage": "nyc --reporter=lcov mocha -- --recursive 'test/**/*.js' --reporter spec --exit", + "test": "nyc --reporter=text mocha --recursive 'test/**/*.js' --reporter spec --timeout 5000 --ui bdd --exit", + "test:coverage": "nyc --reporter=lcov mocha -- --recursive 'test/**/*.js' --reporter spec --timeout 5000 --exit", "test:coveralls": "npm run test:coverage && cat ./coverage/lcov.info | coveralls && rm -rf ./coverage", "test:watch": "npm run test -- -w ./lib", "watch": "watch 'npm test && npm run lint' ./lib ./test" From 605398e319a771008dbe4cd1841e018c2510586b Mon Sep 17 00:00:00 2001 From: Alvaro Vega Date: Thu, 12 Nov 2020 08:56:40 +0100 Subject: [PATCH 16/27] Update createDevice.json --- lib/templates/createDevice.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/templates/createDevice.json b/lib/templates/createDevice.json index bdb39da68..a89d33916 100644 --- a/lib/templates/createDevice.json +++ b/lib/templates/createDevice.json @@ -38,7 +38,7 @@ }, "expressionLanguage": { "description": "Expression language used to apply expressions for this device", - "type": "boolean" + "type": "string" }, "explicitAttrs": { "description": "Flag about only provisioned attributes will be processed to Context Broker", From d3c1cac59980faa2f9ff37072b30a8fc8e2a4d6b Mon Sep 17 00:00:00 2001 From: Alvaro Vega Date: Thu, 12 Nov 2020 08:58:00 +0100 Subject: [PATCH 17/27] Update CHANGES_NEXT_RELEASE --- CHANGES_NEXT_RELEASE | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES_NEXT_RELEASE b/CHANGES_NEXT_RELEASE index b9ed7d07e..dad1ff24c 100644 --- a/CHANGES_NEXT_RELEASE +++ b/CHANGES_NEXT_RELEASE @@ -1,3 +1,4 @@ +Fix: bad type in check expressionLanguage at device provision Add: enable use group commands in device and register it in iotagent-manager Add: extends commands definition to add mqtt options (qos, retain) Add: include findTypeSilently for groups to log some false errors as debug instead of alarm From 8e3c6727044cebbb8f706f076e4ac5868b53333f Mon Sep 17 00:00:00 2001 From: Alvaro Vega Date: Thu, 12 Nov 2020 12:23:44 +0100 Subject: [PATCH 18/27] add missed expressionLanguage --- lib/services/northBound/deviceProvisioningServer.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/lib/services/northBound/deviceProvisioningServer.js b/lib/services/northBound/deviceProvisioningServer.js index 443ac71b0..555f7cb88 100644 --- a/lib/services/northBound/deviceProvisioningServer.js +++ b/lib/services/northBound/deviceProvisioningServer.js @@ -62,7 +62,8 @@ var async = require('async'), internal_attributes: 'internalAttributes', static_attributes: 'staticAttributes', autoprovision: 'autoprovision', - explicitAttrs: 'explicitAttrs' + explicitAttrs: 'explicitAttrs', + expressionLanguage: 'expressionLanguage' }; /** @@ -139,7 +140,8 @@ function handleProvision(req, res, next) { transport: body['transport'], internalId: null, autoprovision: body['autoprovision'], - explicitAttrs: body['explicitAttrs'] + explicitAttrs: body['explicitAttrs'], + expressionLanguage: body['expressionLanguage'] }); } @@ -207,7 +209,8 @@ function toProvisioningAPIFormat(device) { internal_attributes: device.internalAttributes, protocol: device.protocol, autoprovision: device.autoprovision, - explicitAttrs: device.explicitAttrs + explicitAttrs: device.explicitAttrs, + expresionLanguage: device.expressionLanguage }; } From abdcff19b3f16cc5afe78fa0ae573f17f373f4bc Mon Sep 17 00:00:00 2001 From: Alvaro Vega Date: Thu, 12 Nov 2020 12:26:00 +0100 Subject: [PATCH 19/27] Update CHANGES_NEXT_RELEASE --- CHANGES_NEXT_RELEASE | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES_NEXT_RELEASE b/CHANGES_NEXT_RELEASE index dad1ff24c..311fc3fc5 100644 --- a/CHANGES_NEXT_RELEASE +++ b/CHANGES_NEXT_RELEASE @@ -1,3 +1,4 @@ +Fix: add missed expressionLanguage to deviceProvisioningServer Fix: bad type in check expressionLanguage at device provision Add: enable use group commands in device and register it in iotagent-manager Add: extends commands definition to add mqtt options (qos, retain) From 29d94f95019d0722969f194de1e648b34a899f52 Mon Sep 17 00:00:00 2001 From: Alvaro Vega Date: Thu, 12 Nov 2020 12:28:56 +0100 Subject: [PATCH 20/27] Update deviceProvisioningServer.js --- lib/services/northBound/deviceProvisioningServer.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/services/northBound/deviceProvisioningServer.js b/lib/services/northBound/deviceProvisioningServer.js index 555f7cb88..85f648f56 100644 --- a/lib/services/northBound/deviceProvisioningServer.js +++ b/lib/services/northBound/deviceProvisioningServer.js @@ -210,7 +210,7 @@ function toProvisioningAPIFormat(device) { protocol: device.protocol, autoprovision: device.autoprovision, explicitAttrs: device.explicitAttrs, - expresionLanguage: device.expressionLanguage + expressionLanguage: device.expressionLanguage }; } From ee29e6b28550af01ae1be08accad07828248a923 Mon Sep 17 00:00:00 2001 From: Alvaro Vega Date: Mon, 16 Nov 2020 09:47:09 +0100 Subject: [PATCH 21/27] Step: 2.13.0-next -> 2.14.0 --- CHANGES_NEXT_RELEASE | 12 ------------ package.json | 2 +- 2 files changed, 1 insertion(+), 13 deletions(-) diff --git a/CHANGES_NEXT_RELEASE b/CHANGES_NEXT_RELEASE index 311fc3fc5..e69de29bb 100644 --- a/CHANGES_NEXT_RELEASE +++ b/CHANGES_NEXT_RELEASE @@ -1,12 +0,0 @@ -Fix: add missed expressionLanguage to deviceProvisioningServer -Fix: bad type in check expressionLanguage at device provision -Add: enable use group commands in device and register it in iotagent-manager -Add: extends commands definition to add mqtt options (qos, retain) -Add: include findTypeSilently for groups to log some false errors as debug instead of alarm -Add: include `description` field in group schema -Add: include from in log context (#918) -Fix: Update internal attributes in Group update (#917) -Fix: Static attributes from service not applied if device has static attributes (#757) -Move Docker secret support inside the Node Application - remove Entrypoint (#885) -Fix: IOTA_EXPLICIT_ATTRS env var was not working -Add lax validation mode using IOTA_RELAX_TEMPLATE_VALIDATION (#920) diff --git a/package.json b/package.json index 97d92c5bd..de779123d 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "iotagent-node-lib", "description": "IoT Agent library to interface with NGSI Context Broker", - "version": "2.13.0-next", + "version": "2.14.0", "homepage": "https://github.com/telefonicaid/iotagent-node-lib", "keywords": [ "fiware", From 43c54ac1947949aca7bebc4be54164eb6ca529a4 Mon Sep 17 00:00:00 2001 From: Alvaro Vega Date: Mon, 16 Nov 2020 10:48:40 +0100 Subject: [PATCH 22/27] Step: 2.14.0 -> 2.14.0-next --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index de779123d..604c6f028 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "iotagent-node-lib", "description": "IoT Agent library to interface with NGSI Context Broker", - "version": "2.14.0", + "version": "2.14.0-next", "homepage": "https://github.com/telefonicaid/iotagent-node-lib", "keywords": [ "fiware", From 68cebf8a7811ad5df2ebc14a2b71a99dc74c07ed Mon Sep 17 00:00:00 2001 From: Jason Fox Date: Wed, 18 Nov 2020 09:41:30 +0100 Subject: [PATCH 23/27] Update CHANGES_NEXT_RELEASE MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Fermín Galán Márquez --- CHANGES_NEXT_RELEASE | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/CHANGES_NEXT_RELEASE b/CHANGES_NEXT_RELEASE index b4316febb..400c995c7 100644 --- a/CHANGES_NEXT_RELEASE +++ b/CHANGES_NEXT_RELEASE @@ -1,4 +1,7 @@ -Replace jshint with eslint +Update codebase to use ES6 +- Remove JSHint and jshint overrides +- Add esLint using standard tamia presets +- Replace var with let/const +- Fix or disable eslint errors Add prettier code formatting Add husky and lint-staged - From ae4416e25e9b3c6d19c21ade3d4d8a50c1f16c17 Mon Sep 17 00:00:00 2001 From: Jason Fox Date: Wed, 18 Nov 2020 09:43:42 +0100 Subject: [PATCH 24/27] Fix typo --- lib/errors.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/errors.js b/lib/errors.js index 022995c61..23eaf406c 100644 --- a/lib/errors.js +++ b/lib/errors.js @@ -6,8 +6,7 @@ * fiware-iotagent-lib is free software: you can redistribute it and/or * modify it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the License, - * or { - constructor(at your option) any later version. + * or (at your option) any later version. * * fiware-iotagent-lib is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of From ea6d399898f42b6b457b0afcc05bb3a194dc0415 Mon Sep 17 00:00:00 2001 From: Jason Fox Date: Wed, 18 Nov 2020 09:57:48 +0100 Subject: [PATCH 25/27] Update documentation. --- doc/development.md | 33 ++++++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/doc/development.md b/doc/development.md index b1db075c1..0afb3f6c2 100644 --- a/doc/development.md +++ b/doc/development.md @@ -41,9 +41,9 @@ npm test ### Coding guidelines -jshint +ESLint -Uses provided .jshintrc flag file. To check source code style, type +Uses the provided `.eslintrc.json` flag file. To check source code style, type ```bash npm run lint @@ -97,9 +97,36 @@ npm run lint:md ### Documentation Spell-checking -Checks the markdown documentation for spelling and grammar errors, dead links & etc. +Uses the provided `.textlintrc` flag file. To check the markdown documentation for spelling and grammar errors, dead links & etc. ```bash # Use git-bash on Windows npm run lint:text ``` + +### Clean + +Removes `node_modules` and `coverage` folders, and `package-lock.json` file so that a fresh copy of the project is +restored. + +```bash +# Use git-bash on Windows +npm run clean +``` + +### Prettify Code + +Runs the [prettier](https://prettier.io) code formatter to ensure consistent code style (whitespacing, parameter +placement and breakup of long lines etc.) within the codebase. + +```bash +# Use git-bash on Windows +npm run prettier +``` + +To ensure consistent Markdown formatting run the following: + +```bash +# Use git-bash on Windows +npm run prettier:text +``` From d2fd30184cb01954b6949b29c959b66bcfe574b7 Mon Sep 17 00:00:00 2001 From: Jason Fox Date: Tue, 3 Nov 2020 17:37:49 +0100 Subject: [PATCH 26/27] Add mixed mode --- doc/api.md | 10 +- doc/installationguide.md | 15 +- lib/commonConfig.js | 37 ++- lib/fiware-iotagent-lib.js | 3 +- lib/model/Device.js | 3 +- lib/model/Group.js | 3 +- lib/plugins/attributeAlias.js | 4 +- lib/plugins/bidirectionalData.js | 2 +- lib/plugins/expressionParser.js | 2 +- lib/plugins/expressionPlugin.js | 2 +- lib/plugins/jexlParser.js | 2 +- lib/plugins/multiEntity.js | 2 +- lib/plugins/pluginUtils.js | 7 +- lib/plugins/timestampProcessPlugin.js | 2 +- lib/services/common/iotManagerService.js | 3 +- lib/services/devices/deviceRegistryMongoDB.js | 61 ++-- lib/services/devices/deviceService.js | 35 ++- lib/services/devices/devices-NGSI-mixed.js | 65 ++++ lib/services/devices/registrationUtils.js | 15 +- lib/services/groups/groupRegistryMongoDB.js | 6 +- lib/services/ngsi/entities-NGSI-mixed.js | 65 ++++ lib/services/ngsi/ngsiService.js | 73 ++--- lib/services/ngsi/ngsiUtils.js | 2 +- lib/services/ngsi/subscription-NGSI-mixed.js | 62 ++++ lib/services/ngsi/subscriptionService.js | 18 +- .../northBound/contextServer-NGSI-mixed.js | 39 +++ lib/services/northBound/contextServer.js | 18 +- .../northBound/deviceProvisioningServer.js | 9 +- lib/templates/createDevice.json | 4 + lib/templates/createDeviceLax.json | 12 + lib/templates/deviceGroup.json | 4 + lib/templates/updateDevice.json | 4 + .../lazyAndCommands/polling-commands-test.js | 2 - .../provisioning/ngsi-versioning-test.js | 281 ++++++++++++++++++ 34 files changed, 731 insertions(+), 141 deletions(-) create mode 100644 lib/services/devices/devices-NGSI-mixed.js create mode 100644 lib/services/ngsi/entities-NGSI-mixed.js create mode 100644 lib/services/ngsi/subscription-NGSI-mixed.js create mode 100644 lib/services/northBound/contextServer-NGSI-mixed.js create mode 100644 test/unit/ngsi-mixed/provisioning/ngsi-versioning-test.js diff --git a/doc/api.md b/doc/api.md index 5f8673011..8611099cc 100644 --- a/doc/api.md +++ b/doc/api.md @@ -90,8 +90,9 @@ correspondence between the API resource fields and the same fields in the databa | `attributes` | `attributes` | list of common active attributes of the device. For each attribute, its `name` and `type` must be provided, additional `metadata` is optional. | | `static_attributes` | `staticAttributes` | this attributes will be added to all the entities of this group 'as is', additional `metadata` is optional. | | `internal_attributes` | `internalAttributes` | optional section with free format, to allow specific IoT Agents to store information along with the devices in the Device Registry. | -| `expressionLanguage` | `expresionLanguage` | optional boolean value, to set expression language used to compute expressions, possible values are: legacy or jexl. When not set or wrongly set, legacy is used as default value. | -| `explicitAttrs` | `explicitAttrs` | optional boolean value, to support selective ignore of measures so that IOTA doesn’t progress. If not specified default is false. | +| `expressionLanguage` | `expresionLanguage` | optional boolean value, to set expression language used to compute expressions, possible values are: legacy or jexl. When not set or wrongly set, `legacy` is used as default value. | +| `explicitAttrs` | `explicitAttrs` | optional boolean value, to support selective ignore of measures so that IOTA doesn’t progress. If not specified default is `false`. | +| `ngsiVersion` | `ngsiVersion` | optional string value used in mixed mode to switch between **NGSI-v2** and **NGSI-LD** payloads. The default is `v2`. ### Service Group Endpoint @@ -224,7 +225,12 @@ the API resource fields and the same fields in the database model. | `internal_attributes` | `internalAttributes` | List of internal attributes with free format for specific IoT Agent configuration | LWM2M mappings from object URIs to attributes | | `static_attributes` | `staticAttributes` | List of static attributes to append to the entity. All the updateContext requests to the CB will have this set of attributes appended. | `[ { "name": "attr_name", "type": "Text" } ]` | | `expressionLanguage` | `expresionLanguage` | optional boolean value, to set expression language used to compute expressions, possible values are: legacy or jexl. When not set or wrongly set, legacy is used as default value. | +<<<<<<< HEAD | `explicitAttrs` | `explicitAttrs` | Boolean value to support selective ignore of measures for device so that IOTA doesn’t progress. If not specified default is false. | `true/false` | +======= +| `explicitAttrs` | `explicitAttrs` | Boolean value to support selective ignore of measures for device so that IOTA doesn’t progress. If not specified default is `false`. | `true/false` | +| `ngsiVersion` | `ngsiVersion` | optional string value used in mixed mode to switch between **NGSI-v2** and **NGSI-LD**payloads. The default is `v2`. | `v2/ld` | +>>>>>>> d272d82... Add mixed mode #### Attribute lists diff --git a/doc/installationguide.md b/doc/installationguide.md index 386487a8a..8a5fd85dc 100644 --- a/doc/installationguide.md +++ b/doc/installationguide.md @@ -20,7 +20,7 @@ These are the parameters that can be configured in the global section: } ``` -- If you want to use NGSI v2: +- If you want to use **NGSI v2**: ```javascript { @@ -30,7 +30,7 @@ These are the parameters that can be configured in the global section: } ``` -- If you want to use NGSI-LD (experimental): +- If you want to use **NGSI-LD** (experimental): ```javascript { @@ -41,6 +41,17 @@ These are the parameters that can be configured in the global section: } ``` +- If you want to support a "mixed" mode with both **NGSI-v2** and **NGSI-LD** (experimental): + +```javascript +{ + host: '192.168.56.101', + port: '1026', + ngsiVersion: 'mixed', + jsonLdContext: 'http://context.json-ld' // or ['http://context1.json-ld','http://context2.json-ld'] if you need more than one +} +``` + Where `http://context.json-ld` is the location of the NGSI-LD `@context` element which provides additional information allowing the computer to interpret the rest of the data with more clarity and depth. Read the [JSON-LD specification](https://w3c.github.io/json-ld-syntax/#the-context) for more informtaion. diff --git a/lib/commonConfig.js b/lib/commonConfig.js index 8a8a3373e..22b0563b7 100644 --- a/lib/commonConfig.js +++ b/lib/commonConfig.js @@ -504,30 +504,40 @@ function getCommandRegistry() { } /** - * It checks if the configuration file states the use of NGSIv2 + * Returns the supported NGSI format * - * @return {boolean} Result of the checking + * @return {string} the supported NGSI format */ -function checkNgsi2() { - if (config.contextBroker && config.contextBroker.ngsiVersion && config.contextBroker.ngsiVersion === 'v2') { - return true; +function ngsiVersion() { + if (config && config.contextBroker && config.contextBroker.ngsiVersion) { + return config.contextBroker.ngsiVersion.toLowerCase(); } - - return false; + return 'unknown'; } /** - * It checks if the configuration file states the use of NGSI-LD + * It checks if the configuration file states a non-legacy format, + * either v2, LD or mixed. * * @return {boolean} Result of the checking */ -function checkNgsiLD() { - if (config.contextBroker && config.contextBroker.ngsiVersion && config.contextBroker.ngsiVersion === 'ld') { - return true; +function isCurrentNgsi() { + if (config.contextBroker && config.contextBroker.ngsiVersion) { + const version = config.contextBroker.ngsiVersion.toLowerCase(); + return version === 'v2' || version === 'ld' || version === 'mixed'; } - return false; } +/** + * It checks if a combination of typeInformation or common Config is LD + * + * @return {boolean} Result of the checking + */ +function checkNgsiLD(typeInformation) { + const format = typeInformation.ngsiVersion || ngsiVersion(); + return format.toLowerCase() === 'ld'; +} + function setSecurityService(newSecurityService) { securityService = newSecurityService; } @@ -544,8 +554,9 @@ exports.setGroupRegistry = setGroupRegistry; exports.getGroupRegistry = getGroupRegistry; exports.setCommandRegistry = setCommandRegistry; exports.getCommandRegistry = getCommandRegistry; -exports.checkNgsi2 = checkNgsi2; +exports.ngsiVersion = ngsiVersion; exports.checkNgsiLD = checkNgsiLD; +exports.isCurrentNgsi = isCurrentNgsi; exports.setSecurityService = setSecurityService; exports.getSecurityService = getSecurityService; exports.getSecretData = getSecretData; diff --git a/lib/fiware-iotagent-lib.js b/lib/fiware-iotagent-lib.js index 9e6f1ab07..da0c0f91f 100644 --- a/lib/fiware-iotagent-lib.js +++ b/lib/fiware-iotagent-lib.js @@ -27,7 +27,6 @@ const ngsi = require('./services/ngsi/ngsiService'); const intoTrans = require('./services/common/domain').intoTrans; const middlewares = require('./services/common/genericMiddleware'); const db = require('./model/dbConn'); -const ngsiService = require('./services/ngsi/ngsiService'); const subscriptions = require('./services/ngsi/subscriptionService'); const statsRegistry = require('./services/stats/statsRegistry'); const domainUtils = require('./services/common/domain'); @@ -179,7 +178,7 @@ function doActivate(newConfig, callback) { deviceService.init(); subscriptions.init(); contextServer.init(); - ngsiService.init(); + ngsi.init(); commands.start(); diff --git a/lib/model/Device.js b/lib/model/Device.js index 0090023fe..816ff9311 100644 --- a/lib/model/Device.js +++ b/lib/model/Device.js @@ -49,7 +49,8 @@ const Device = new Schema({ internalAttributes: Object, autoprovision: Boolean, expressionLanguage: String, - explicitAttrs: Boolean + explicitAttrs: Boolean, + ngsiVersion: String }); function load(db) { diff --git a/lib/model/Group.js b/lib/model/Group.js index de94694b2..fd4b95988 100644 --- a/lib/model/Group.js +++ b/lib/model/Group.js @@ -43,7 +43,8 @@ const Group = new Schema({ internalAttributes: Array, autoprovision: Boolean, expressionLanguage: String, - explicitAttrs: Boolean + explicitAttrs: Boolean, + ngsiVersion: String }); function load(db) { diff --git a/lib/plugins/attributeAlias.js b/lib/plugins/attributeAlias.js index 5f3501196..838206f13 100644 --- a/lib/plugins/attributeAlias.js +++ b/lib/plugins/attributeAlias.js @@ -73,7 +73,7 @@ function extractAllMappings(typeInformation) { function applyAlias(mappings) { return function aliasApplier(attribute) { if (mappings.direct[attribute.name]) { - if (config.checkNgsi2() || config.checkNgsiLD()) { + if (config.isCurrentNgsi()) { /*jshint camelcase: false */ attribute.object_id = attribute.name; // inverse not usefull due to collision } @@ -93,7 +93,7 @@ function applyAlias(mappings) { */ function updateAttribute(entity, typeInformation, callback) { const mappings = extractAllMappings(typeInformation); - if (config.checkNgsi2() || config.checkNgsiLD()) { + if (config.isCurrentNgsi()) { let attsArray = utils.extractAttributesArrayFromNgsi2Entity(entity); attsArray = attsArray.map(applyAlias(mappings)); entity = utils.createNgsi2Entity(entity.id, entity.type, attsArray, true); diff --git a/lib/plugins/bidirectionalData.js b/lib/plugins/bidirectionalData.js index e7ea9a70c..c782b1377 100644 --- a/lib/plugins/bidirectionalData.js +++ b/lib/plugins/bidirectionalData.js @@ -130,7 +130,7 @@ function sendSubscriptions(device, attributeList, callback) { logger.debug(context, 'Sending bidirectionality subscriptions for device [%s]', device.id); - if (config.checkNgsi2() || config.checkNgsiLD()) { + if (config.isCurrentNgsi()) { async.map(attributeList, sendSingleSubscriptionNgsi2, callback); } else { async.map(attributeList, sendSingleSubscriptionNgsi1, callback); diff --git a/lib/plugins/expressionParser.js b/lib/plugins/expressionParser.js index 9e5455030..d9137cf5a 100644 --- a/lib/plugins/expressionParser.js +++ b/lib/plugins/expressionParser.js @@ -176,7 +176,7 @@ function expressionApplier(context, typeInformation) { }; /*jshint camelcase: false */ - if ((config.checkNgsi2() || config.checkNgsiLD()) && attribute.object_id) { + if (config.isCurrentNgsi() && attribute.object_id) { newAttribute.object_id = attribute.object_id; } diff --git a/lib/plugins/expressionPlugin.js b/lib/plugins/expressionPlugin.js index 701b13a01..18852eb13 100644 --- a/lib/plugins/expressionPlugin.js +++ b/lib/plugins/expressionPlugin.js @@ -112,7 +112,7 @@ function update(entity, typeInformation, callback) { } try { - if (config.checkNgsi2() || config.checkNgsiLD()) { + if (config.isCurrentNgsi()) { let attsArray = utils.extractAttributesArrayFromNgsi2Entity(entity); attsArray = processEntityUpdateNgsi2(attsArray); entity = utils.createNgsi2Entity(entity.id, entity.type, attsArray, true); diff --git a/lib/plugins/jexlParser.js b/lib/plugins/jexlParser.js index 61de1036d..23146bdaa 100644 --- a/lib/plugins/jexlParser.js +++ b/lib/plugins/jexlParser.js @@ -119,7 +119,7 @@ function expressionApplier(context, typeInformation) { }; /*jshint camelcase: false */ - if (config.checkNgsi2() && attribute.object_id) { + if (config.isCurrentNgsi() && attribute.object_id) { newAttribute.object_id = attribute.object_id; } diff --git a/lib/plugins/multiEntity.js b/lib/plugins/multiEntity.js index ef036b232..255ff7f28 100644 --- a/lib/plugins/multiEntity.js +++ b/lib/plugins/multiEntity.js @@ -288,7 +288,7 @@ function updateAttributeNgsi2(entity, typeInformation, callback) { } function updateAttribute(entity, typeInformation, callback) { - if (config.checkNgsi2() || config.checkNgsiLD()) { + if (config.isCurrentNgsi()) { updateAttributeNgsi2(entity, typeInformation, callback); } else { updateAttributeNgsi1(entity, typeInformation, callback); diff --git a/lib/plugins/pluginUtils.js b/lib/plugins/pluginUtils.js index 778d719fc..01a9b4170 100644 --- a/lib/plugins/pluginUtils.js +++ b/lib/plugins/pluginUtils.js @@ -102,8 +102,7 @@ function createProcessAttribute(fn, attributeType) { if (attribute.type && attribute.type === attributeType) { attribute.value = fn(attribute.value); } - - if (config.checkNgsi2() || config.checkNgsiLD()) { + if (config.isCurrentNgsi()) { // This code is backwards compatible to process metadata in the older NGSIv1-style (array) // as well as supporting the newer NGSIv2-style (object). The redundant Array Check can be // therefore be removed if/when NGSIv1 support is removed from the library. @@ -149,7 +148,7 @@ function createUpdateFilter(fn, attributeType) { return entity; } - if (config.checkNgsi2() || config.checkNgsiLD()) { + if (config.isCurrentNgsi()) { entity = processEntityUpdateNgsi2(entity); } else { entity.contextElements = entity.contextElements.map(processEntityUpdateNgsi1); @@ -184,7 +183,7 @@ function createQueryFilter(fn, attributeType) { return entity; } - if (config.checkNgsi2() || config.checkNgsiLD()) { + if (config.isCurrentNgsi()) { entity = processEntityQueryNgsi2(entity); } else { entity.contextResponses = entity.contextResponses.map(processEntityQueryNgsi1); diff --git a/lib/plugins/timestampProcessPlugin.js b/lib/plugins/timestampProcessPlugin.js index d4e21a28c..8fd8d7842 100644 --- a/lib/plugins/timestampProcessPlugin.js +++ b/lib/plugins/timestampProcessPlugin.js @@ -130,7 +130,7 @@ function updatePluginNgsi1(entity, entityType, callback) { * @param {Object} entity NGSI Entity as it would have been sent before the plugin. */ function updatePlugin(entity, entityType, callback) { - if (config.checkNgsi2() || config.checkNgsiLD()) { + if (config.isCurrentNgsi()) { updatePluginNgsi2(entity, entityType, callback); } else { updatePluginNgsi1(entity, entityType, callback); diff --git a/lib/services/common/iotManagerService.js b/lib/services/common/iotManagerService.js index ad61a6108..dc0e4b9a4 100644 --- a/lib/services/common/iotManagerService.js +++ b/lib/services/common/iotManagerService.js @@ -56,7 +56,8 @@ function register(callback) { timestamp: service.timestamp, autoprovision: service.autoprovision, explicitAttrs: service.explicitAttrs, - expressionLanguage: service.expressionLanguage + expressionLanguage: service.expressionLanguage, + ngsiVersion: service.ngsiVersion }; } diff --git a/lib/services/devices/deviceRegistryMongoDB.js b/lib/services/devices/deviceRegistryMongoDB.js index 9912e856c..b5eea04ff 100644 --- a/lib/services/devices/deviceRegistryMongoDB.js +++ b/lib/services/devices/deviceRegistryMongoDB.js @@ -34,6 +34,32 @@ let context = { op: 'IoTAgentNGSI.MongoDBDeviceRegister' }; +const attributeList = [ + 'id', + 'type', + 'name', + 'service', + 'subservice', + 'lazy', + 'commands', + 'staticAttributes', + 'active', + 'registrationId', + 'internalId', + 'internalAttributes', + 'resource', + 'apikey', + 'protocol', + 'endpoint', + 'transport', + 'polling', + 'timestamp', + 'autoprovision', + 'explicitAttrs', + 'expressionLanguage', + 'ngsiVersion' +]; + /** * Generates a handler for the save device operations. The handler will take the customary error and the saved device * as the parameters (and pass the serialized DAO as the callback value). @@ -58,35 +84,11 @@ function saveDeviceHandler(callback) { * @param {Object} newDevice Device object to be stored */ function storeDevice(newDevice, callback) { - const deviceObj = new Device.model(); // eslint-disable-line new-cap - const attributeList = [ - 'id', - 'type', - 'name', - 'service', - 'subservice', - 'lazy', - 'commands', - 'staticAttributes', - 'active', - 'registrationId', - 'internalId', - 'internalAttributes', - 'resource', - 'apikey', - 'protocol', - 'endpoint', - 'transport', - 'polling', - 'timestamp', - 'autoprovision', - 'explicitAttrs', - 'expressionLanguage' - ]; - - for (let i = 0; i < attributeList.length; i++) { - deviceObj[attributeList[i]] = newDevice[attributeList[i]]; - } + /* eslint-disable-next-line new-cap */ + const deviceObj = new Device.model(); + attributeList.forEach((key) => { + deviceObj[key] = newDevice[key]; + }); // Ensure protocol is in newDevice if (!newDevice.protocol && config.getConfig().iotManager && config.getConfig().iotManager.protocol) { @@ -286,6 +288,7 @@ function update(device, callback) { data.name = device.name; data.type = device.type; data.explicitAttrs = device.explicitAttrs; + data.ngsiVersion = device.ngsiVersion; data.save(saveDeviceHandler(callback)); } diff --git a/lib/services/devices/deviceService.js b/lib/services/devices/deviceService.js index 8c829a4bc..c4afedd97 100644 --- a/lib/services/devices/deviceService.js +++ b/lib/services/devices/deviceService.js @@ -48,13 +48,20 @@ let deviceHandler; /** * Loads the correct device handler based on the current config. */ + function init() { - if (config.checkNgsiLD()) { - deviceHandler = require('./devices-NGSI-LD'); - } else if (config.checkNgsi2()) { - deviceHandler = require('./devices-NGSI-v2'); - } else { - deviceHandler = require('./devices-NGSI-v1'); + switch (config.ngsiVersion()) { + case 'ld': + deviceHandler = require('./devices-NGSI-LD'); + break; + case 'v2': + deviceHandler = require('./devices-NGSI-v2'); + break; + case 'mixed': + deviceHandler = require('./devices-NGSI-mixed'); + break; + default: + deviceHandler = require('./devices-NGSI-v1'); } } @@ -162,6 +169,10 @@ function mergeDeviceWithConfiguration(fields, defaults, deviceData, configuratio if (configuration && configuration.cbHost) { deviceData.cbHost = configuration.cbHost; } + if (configuration && configuration.ngsiVersion) { + deviceData.ngsiVersion = configuration.ngsiVersion; + } + logger.debug(context, 'deviceData after merge with conf: %j', deviceData); callback(null, deviceData); } @@ -244,9 +255,15 @@ function registerDevice(deviceObj, callback) { } } + if (!deviceData.ngsiVersion) { + if (configuration && configuration.ngsiVersion) { + deviceData.ngsiVersion = configuration.ngsiVersion; + } + } + if (!deviceData.name) { deviceData.name = deviceData.type + ':' + deviceData.id; - if (config.checkNgsiLD()) { + if (config.checkNgsiLD(configuration)) { deviceData.name = 'urn:ngsi-ld:' + deviceData.type + ':' + deviceData.id; } logger.debug(context, 'Device name not found, falling back to deviceType:deviceId [%s]', deviceData.name); @@ -532,7 +549,9 @@ function findOrCreate(deviceId, group, callback) { if ('autoprovision' in group && group.autoprovision !== undefined) { newDevice.autoprovision = group.autoprovision; } - + if ('ngsiVersion' in group && group.ngsiVersion !== undefined) { + newDevice.ngsiVersion = group.ngsiVersion; + } registerDevice(newDevice, function (error, device) { callback(error, device, group); }); diff --git a/lib/services/devices/devices-NGSI-mixed.js b/lib/services/devices/devices-NGSI-mixed.js new file mode 100644 index 000000000..bb8e2fc73 --- /dev/null +++ b/lib/services/devices/devices-NGSI-mixed.js @@ -0,0 +1,65 @@ +/* + * Copyright 2020 Telefonica Investigación y Desarrollo, S.A.U + * + * This file is part of fiware-iotagent-lib + * + * fiware-iotagent-lib is free software: you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the License, + * or (at your option) any later version. + * + * fiware-iotagent-lib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public + * License along with fiware-iotagent-lib. + * If not, see http://www.gnu.org/licenses/. + * + * For those usages not covered by the GNU Affero General Public License + * please contact with::daniel.moranjimenez@telefonica.com + * + * Modified by: Jason Fox - FIWARE Foundation + */ + +const config = require('../../commonConfig'); +const deviceHandlerLD = require('./devices-NGSI-LD'); +const deviceHandlerV2 = require('./devices-NGSI-v2'); + +/** + * Creates the initial entity representing the device in the Context Broker using both NGSI-LD and NGSI-v2 + * This is important mainly to allow the rest of the updateContext operations to be performed. + * + * @param {Object} deviceData Object containing all the deviceData needed to send the registration. + * @param {Object} newDevice Device object that will be stored in the database. + */ +function createInitialEntityNgsiMixed(deviceData, newDevice, callback) { + if (config.checkNgsiLD(deviceData)) { + deviceHandlerLD.createInitialEntity(deviceData, newDevice, callback); + } else { + deviceHandlerV2.createInitialEntity(deviceData, newDevice, callback); + } +} + +/** + * Updates the register of an existing device identified by the Id and Type in the Context Broker, and the internal + * registry. It uses both NGSI-LD and NGSI-v2 + * + * The device id and type are required fields for a registration updated. Only the following attributes will be + * updated: lazy, active and internalId. Any other change will be ignored. The registration for the lazy attributes + * of the updated entity will be updated if existing, and created if not. If new active attributes are created, + * the entity will be updated creating the new attributes. + * + * @param {Object} deviceObj Object with all the device information (mandatory). + */ +function updateRegisterDeviceNgsiMixed(deviceObj, callback) { + if (config.checkNgsiLD(deviceObj)) { + deviceHandlerLD.updateRegisterDevice(deviceObj, callback); + } else { + deviceHandlerV2.updateRegisterDevice(deviceObj, callback); + } +} + +exports.createInitialEntity = createInitialEntityNgsiMixed; +exports.updateRegisterDevice = updateRegisterDeviceNgsiMixed; diff --git a/lib/services/devices/registrationUtils.js b/lib/services/devices/registrationUtils.js index cb1573cb5..fa7c905d0 100644 --- a/lib/services/devices/registrationUtils.js +++ b/lib/services/devices/registrationUtils.js @@ -506,12 +506,15 @@ function sendRegistrationsNgsiLD(unregister, deviceData, callback) { * @param {Object} deviceData Object containing all the deviceData needed to send the registration. */ function sendRegistrations(unregister, deviceData, callback) { - if (config.checkNgsiLD()) { - sendRegistrationsNgsiLD(unregister, deviceData, callback); - } else if (config.checkNgsi2()) { - sendRegistrationsNgsi2(unregister, deviceData, callback); - } else { - sendRegistrationsNgsi1(unregister, deviceData, callback); + switch (config.ngsiVersion()) { + case 'ld': + sendRegistrationsNgsiLD(unregister, deviceData, callback); + break; + case 'v2': + sendRegistrationsNgsi2(unregister, deviceData, callback); + break; + default: + sendRegistrationsNgsi1(unregister, deviceData, callback); } } diff --git a/lib/services/groups/groupRegistryMongoDB.js b/lib/services/groups/groupRegistryMongoDB.js index 325490b74..e816c9e3e 100644 --- a/lib/services/groups/groupRegistryMongoDB.js +++ b/lib/services/groups/groupRegistryMongoDB.js @@ -77,7 +77,8 @@ function createGroup(group, callback) { 'internalAttributes', 'autoprovision', 'explicitAttrs', - 'expressionLanguage' + 'expressionLanguage', + 'ngsiVersion' ]; for (let i = 0; i < attributeList.length; i++) { @@ -270,7 +271,8 @@ function update(id, body, callback) { 'staticAttributes', 'internalAttributes', 'explicitAttrs', - 'expressionLanguage' + 'expressionLanguage', + 'ngsiVersion' ]; for (let i = 0; i < attributes.length; i++) { diff --git a/lib/services/ngsi/entities-NGSI-mixed.js b/lib/services/ngsi/entities-NGSI-mixed.js new file mode 100644 index 000000000..17984a359 --- /dev/null +++ b/lib/services/ngsi/entities-NGSI-mixed.js @@ -0,0 +1,65 @@ +/* + * Copyright 2020 Telefonica Investigación y Desarrollo, S.A.U + * + * This file is part of fiware-iotagent-lib + * + * fiware-iotagent-lib is free software: you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the License, + * or (at your option) any later version. + * + * fiware-iotagent-lib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public + * License along with fiware-iotagent-lib. + * If not, see http://www.gnu.org/licenses/. + * + * For those usages not covered by the GNU Affero General Public License + * please contact with::daniel.moranjimenez@telefonica.com + * + * Modified by: Jason Fox - FIWARE Foundation + */ + +const config = require('../../commonConfig'); +const entityHandlerLD = require('./entities-NGSI-LD'); +const entityHandlerV2 = require('./entities-NGSI-v2'); + +/** + * Makes a query to the Device's entity in the context broker using NGSI-LD, with the list + * of attributes given by the 'attributes' array. + * + * @param {String} entityName Name of the entity to query. + * @param {Array} attributes Attribute array containing the names of the attributes to query. + * @param {Object} typeInformation Configuration information for the device. + * @param {String} token User token to identify against the PEP Proxies (optional). + */ +function sendQueryValueNgsiMixed(entityName, attributes, typeInformation, token, callback) { + if (config.checkNgsiLD(typeInformation)) { + entityHandlerLD.sendQueryValue(entityName, attributes, typeInformation, token, callback); + } else { + entityHandlerV2.sendQueryValue(entityName, attributes, typeInformation, token, callback); + } +} + +/** + * Makes an update in the Device's entity in the context broker, with the values given + * in the 'attributes' array. This array should comply to the NGSI-LD or NGSI-v2 attribute format. + * + * @param {String} entityName Name of the entity to register. + * @param {Array} attributes Attribute array containing the values to update. + * @param {Object} typeInformation Configuration information for the device. + * @param {String} token User token to identify against the PEP Proxies (optional). + */ +function sendUpdateValueNgsiMixed(entityName, attributes, typeInformation, token, callback) { + if (config.checkNgsiLD(typeInformation)) { + entityHandlerLD.sendUpdateValue(entityName, attributes, typeInformation, token, callback); + } else { + entityHandlerV2.sendUpdateValue(entityName, attributes, typeInformation, token, callback); + } +} + +exports.sendUpdateValue = sendUpdateValueNgsiMixed; +exports.sendQueryValue = sendQueryValueNgsiMixed; diff --git a/lib/services/ngsi/ngsiService.js b/lib/services/ngsi/ngsiService.js index 236fd61aa..c2fc33648 100644 --- a/lib/services/ngsi/ngsiService.js +++ b/lib/services/ngsi/ngsiService.js @@ -38,18 +38,25 @@ const context = { op: 'IoTAgentNGSI.NGSIService' }; +const attributeList = ['trust', 'cbHost', 'ngsiVersion']; let entityHandler; /** * Loads the correct ngsiService handler based on the current config. */ function init() { - if (config.checkNgsiLD()) { - entityHandler = require('./entities-NGSI-LD'); - } else if (config.checkNgsi2()) { - entityHandler = require('./entities-NGSI-v2'); - } else { - entityHandler = require('./entities-NGSI-v1'); + switch (config.ngsiVersion()) { + case 'ld': + entityHandler = require('./entities-NGSI-LD'); + break; + case 'v2': + entityHandler = require('./entities-NGSI-v2'); + break; + case 'mixed': + entityHandler = require('./entities-NGSI-mixed'); + break; + default: + entityHandler = require('./entities-NGSI-v1'); } } @@ -130,30 +137,22 @@ function executeWithDeviceInformation(operationFunction) { ); config.getGroupRegistry().getType(type, function (error, deviceGroup) { let typeInformation; + const configDeviceInfo = config.getConfig().types[type]; if (error) { logger.debug(context, 'error %j in get group device', error); } + + // For anonymous devices use the typeInformation from the provisioned group and/or config directly. + // For preregistered devices, augment the existing deviceInformation with selected attributes. if (!callback) { callback = deviceInformation; - - if (deviceGroup) { - typeInformation = deviceGroup; - } else { - typeInformation = config.getConfig().types[type]; - } + typeInformation = deviceGroup || configDeviceInfo; } else { typeInformation = deviceInformation; - if (!typeInformation.trust) { - if (deviceGroup && deviceGroup.trust) { - typeInformation.trust = deviceGroup.trust; - } else if (config.getConfig().types[type] && config.getConfig().types[type].trust) { - typeInformation.trust = config.getConfig().types[type].trust; - } - - if (deviceGroup && deviceGroup.cbHost) { - typeInformation.cbHost = deviceGroup.cbHost; - } - } + attributeList.forEach((key) => { + typeInformation[key] = + typeInformation[key] || (deviceGroup || {})[key] || (configDeviceInfo || {})[key]; + }); } if (config.getConfig().authentication && config.getConfig().authentication.enabled) { @@ -216,33 +215,19 @@ function setCommandResult( } ]; + // For anonymous devices use the typeInformation from the provisioned group and/or config directly. + // For preregistered devices, augment the existing deviceInformation with selected attributes. if (!callback) { callback = deviceInformation; - - if (deviceGroup) { - typeInformation = deviceGroup; - } else { - typeInformation = config.getConfig().types[resource]; - } + typeInformation = deviceGroup || config.getConfig().types[resource]; } else { typeInformation = deviceInformation; } - if (!typeInformation.type) { - if (deviceGroup) { - typeInformation.type = deviceGroup.type; - } else { - typeInformation.type = resource; - } - } - - if (!typeInformation.service) { - typeInformation.service = config.getConfig().service; - } - - if (!typeInformation.subservice) { - typeInformation.subservice = config.getConfig().subservice; - } + // Ensure type, servce and subservice are always set, using fallbacks as necessary. + typeInformation.type = typeInformation.type || (deviceGroup || {}).type || resource; + typeInformation.service = typeInformation.service || config.getConfig().service; + typeInformation.subservice = typeInformation.subservice || config.getConfig().subservice; commandInfo = _.where(typeInformation.commands, { name: commandName }); diff --git a/lib/services/ngsi/ngsiUtils.js b/lib/services/ngsi/ngsiUtils.js index 9005fbab2..8b33a2dd2 100644 --- a/lib/services/ngsi/ngsiUtils.js +++ b/lib/services/ngsi/ngsiUtils.js @@ -126,7 +126,7 @@ function createRequestObject(url, typeInformation, token) { } } - if (config.checkNgsiLD()) { + if (config.checkNgsiLD(typeInformation)) { headers['Content-Type'] = 'application/ld+json'; headers['NGSILD-Tenant'] = headers['fiware-service']; headers['NGSILD-Path'] = headers['fiware-servicepath']; diff --git a/lib/services/ngsi/subscription-NGSI-mixed.js b/lib/services/ngsi/subscription-NGSI-mixed.js new file mode 100644 index 000000000..4e0b4ed4f --- /dev/null +++ b/lib/services/ngsi/subscription-NGSI-mixed.js @@ -0,0 +1,62 @@ +/* + * Copyright 2020 Telefonica Investigación y Desarrollo, S.A.U + * + * This file is part of fiware-iotagent-lib + * + * fiware-iotagent-lib is free software: you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the License, + * or (at your option) any later version. + * + * fiware-iotagent-lib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public + * License along with fiware-iotagent-lib. + * If not, see http://www.gnu.org/licenses/. + * + * For those usages not covered by the GNU Affero General Public License + * please contact with::daniel.moranjimenez@telefonica.com + * + * Modified by: Jason Fox - FIWARE Foundation + */ + +const config = require('../../commonConfig'); +const subscriptionHandlerLD = require('./subscription-NGSI-LD'); +const subscriptionHandlerV2 = require('./subscription-NGSI-v2'); + +/** + * Makes a subscription for the given device's entity using NGSI-LD, triggered by the given attributes. + * The contents of the notification can be selected using the "content" array (that can be left blank + * to notify the complete entity). + * + * @param {Object} device Object containing all the information about a particular device. + * @param {Object} triggers Array with the names of the attributes that would trigger the subscription + * @param {Object} content Array with the names of the attributes to retrieve in the notification. + */ +function subscribeNgsiMixed(device, triggers, content, callback) { + if (config.checkNgsiLD(device)) { + subscriptionHandlerLD.subscribe(device, triggers, content, callback); + } else { + subscriptionHandlerV2.subscribe(device, triggers, content, callback); + } +} + +/** + * Remove the subscription with the given ID from the Context Broker and from the device repository using NGSI-LD. + * + * @param {Object} device Object containing all the information about a particular device. + * @param {String} id ID of the subscription to remove. + */ +function unsubscribeNgsiMixed(device, id, callback) { + if (config.checkNgsiLD(device)) { + subscriptionHandlerLD.unsubscribe(device, id, callback); + } else { + subscriptionHandlerV2.unsubscribe(device, id, callback); + } +} + +exports.subscribe = subscribeNgsiMixed; +exports.unsubscribe = unsubscribeNgsiMixed; diff --git a/lib/services/ngsi/subscriptionService.js b/lib/services/ngsi/subscriptionService.js index 46ac49fa4..536b2d7e0 100644 --- a/lib/services/ngsi/subscriptionService.js +++ b/lib/services/ngsi/subscriptionService.js @@ -36,12 +36,18 @@ let subscriptionHandler; * Loads the correct subscription handler based on the current config. */ function init() { - if (config.checkNgsiLD()) { - subscriptionHandler = require('./subscription-NGSI-LD'); - } else if (config.checkNgsi2()) { - subscriptionHandler = require('./subscription-NGSI-v2'); - } else { - subscriptionHandler = require('./subscription-NGSI-v1'); + switch (config.ngsiVersion()) { + case 'ld': + subscriptionHandler = require('./subscription-NGSI-LD'); + break; + case 'v2': + subscriptionHandler = require('./subscription-NGSI-v2'); + break; + case 'mixed': + subscriptionHandler = require('./subscription-NGSI-mixed'); + break; + default: + subscriptionHandler = require('./subscription-NGSI-v1'); } } diff --git a/lib/services/northBound/contextServer-NGSI-mixed.js b/lib/services/northBound/contextServer-NGSI-mixed.js new file mode 100644 index 000000000..d14f909b3 --- /dev/null +++ b/lib/services/northBound/contextServer-NGSI-mixed.js @@ -0,0 +1,39 @@ +/* + * Copyright 2020 Telefonica Investigación y Desarrollo, S.A.U + * + * This file is part of fiware-iotagent-lib + * + * fiware-iotagent-lib is free software: you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the License, + * or (at your option) any later version. + * + * fiware-iotagent-lib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public + * License along with fiware-iotagent-lib. + * If not, see http://www.gnu.org/licenses/. + * + * For those usages not covered by the GNU Affero General Public License + * please contact with::daniel.moranjimenez@telefonica.com + * + * Modified by: Jason Fox - FIWARE Foundation + */ + +const contextServerHandlerLD = require('./contextServer-NGSI-LD'); +const contextServerHandlerV2 = require('./contextServer-NGSI-v2'); + +/** + * Load the routes related to context dispatching (NGSI10 calls) for both v2 and LD (mixed mode) + * + * @param {Object} router Express request router object. + */ +function loadContextRoutesMixed(router) { + contextServerHandlerLD.loadContextRoutes(router); + contextServerHandlerV2.loadContextRoutes(router); +} + +exports.loadContextRoutes = loadContextRoutesMixed; diff --git a/lib/services/northBound/contextServer.js b/lib/services/northBound/contextServer.js index b1a578e28..a5c4534ba 100644 --- a/lib/services/northBound/contextServer.js +++ b/lib/services/northBound/contextServer.js @@ -37,12 +37,18 @@ let contextServerHandler; * Loads the correct context server handler based on the current config. */ function init() { - if (config.checkNgsiLD()) { - contextServerHandler = require('./contextServer-NGSI-LD'); - } else if (config.checkNgsi2()) { - contextServerHandler = require('./contextServer-NGSI-v2'); - } else { - contextServerHandler = require('./contextServer-NGSI-v1'); + switch (config.ngsiVersion()) { + case 'ld': + contextServerHandler = require('./contextServer-NGSI-LD'); + break; + case 'v2': + contextServerHandler = require('./contextServer-NGSI-v2'); + break; + case 'mixed': + contextServerHandler = require('./contextServer-NGSI-mixed'); + break; + default: + contextServerHandler = require('./contextServer-NGSI-v1'); } } diff --git a/lib/services/northBound/deviceProvisioningServer.js b/lib/services/northBound/deviceProvisioningServer.js index 7b9248edb..9b8b88034 100644 --- a/lib/services/northBound/deviceProvisioningServer.js +++ b/lib/services/northBound/deviceProvisioningServer.js @@ -59,7 +59,8 @@ const provisioningAPITranslation = { static_attributes: 'staticAttributes', autoprovision: 'autoprovision', explicitAttrs: 'explicitAttrs', - expressionLanguage: 'expressionLanguage' + expressionLanguage: 'expressionLanguage', + ngsiVersion: 'ngsiVersion' }; /** @@ -137,7 +138,8 @@ function handleProvision(req, res, next) { internalId: null, autoprovision: body.autoprovision, explicitAttrs: body.explicitAttrs, - expressionLanguage: body.expressionLanguage + expressionLanguage: body.expressionLanguage, + ngsiVersion: body.ngsiVersion }); } @@ -207,8 +209,9 @@ function toProvisioningAPIFormat(device) { internal_attributes: device.internalAttributes, protocol: device.protocol, autoprovision: device.autoprovision, + expressionLanguage: device.expressionLanguage, explicitAttrs: device.explicitAttrs, - expressionLanguage: device.expressionLanguage + ngsiVersion: device.ngsiVersion }; } diff --git a/lib/templates/createDevice.json b/lib/templates/createDevice.json index a89d33916..26fe72e72 100644 --- a/lib/templates/createDevice.json +++ b/lib/templates/createDevice.json @@ -44,6 +44,10 @@ "description": "Flag about only provisioned attributes will be processed to Context Broker", "type": "boolean" }, + "ngsiVersion": { + "description": "NGSI Interface for this device", + "type": "string" + }, "lazy": { "description": "list of lazy attributes of the devices", "type": "array", diff --git a/lib/templates/createDeviceLax.json b/lib/templates/createDeviceLax.json index 1920cb761..64d25efda 100644 --- a/lib/templates/createDeviceLax.json +++ b/lib/templates/createDeviceLax.json @@ -36,6 +36,18 @@ "description": "Transport protocol used by the platform to communicate with the device", "type": "string" }, + "expressionLanguage": { + "description": "Expression language used to apply expressions for this device", + "type": "boolean" + }, + "explicitAttrs": { + "description": "Flag about only provisioned attributes will be processed to Context Broker", + "type": "boolean" + }, + "ngsiVersion": { + "description": "NGSI Interface for this device", + "type": "string" + }, "lazy": { "description": "list of lazy attributes of the devices", "type": "array", diff --git a/lib/templates/deviceGroup.json b/lib/templates/deviceGroup.json index 8c9279cdb..fcf63dc11 100644 --- a/lib/templates/deviceGroup.json +++ b/lib/templates/deviceGroup.json @@ -41,6 +41,10 @@ "description": "Expression language used to for the group of devices", "type": "string" }, + "ngsiVersion": { + "description": "NGSI Interface for this group of devices", + "type": "string" + }, "attributes": { "description": "list of active attributes of the devices", "type": "array" diff --git a/lib/templates/updateDevice.json b/lib/templates/updateDevice.json index 46d7bf338..d3fd7b116 100644 --- a/lib/templates/updateDevice.json +++ b/lib/templates/updateDevice.json @@ -179,6 +179,10 @@ "explicitAttrs": { "description": "Flag to decide update of active attributes only", "type": "Boolean" + }, + "ngsiVersion": { + "description": "NGSI Interface for this device", + "type": "string" } } } diff --git a/test/unit/lazyAndCommands/polling-commands-test.js b/test/unit/lazyAndCommands/polling-commands-test.js index d596e81c5..2672138b3 100644 --- a/test/unit/lazyAndCommands/polling-commands-test.js +++ b/test/unit/lazyAndCommands/polling-commands-test.js @@ -122,9 +122,7 @@ const device3 = { describe('NGSI-v1 - Polling commands', function () { beforeEach(function (done) { logger.setLevel('FATAL'); - nock.cleanAll(); - contextBrokerMock = nock('http://192.168.1.1:1026') .matchHeader('fiware-service', 'smartGondor') .matchHeader('fiware-servicepath', 'gardens') diff --git a/test/unit/ngsi-mixed/provisioning/ngsi-versioning-test.js b/test/unit/ngsi-mixed/provisioning/ngsi-versioning-test.js new file mode 100644 index 000000000..0366dd870 --- /dev/null +++ b/test/unit/ngsi-mixed/provisioning/ngsi-versioning-test.js @@ -0,0 +1,281 @@ +/* + * Copyright 2015 Telefonica Investigación y Desarrollo, S.A.U + * + * This file is part of fiware-iotagent-lib + * + * fiware-iotagent-lib is free software: you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the License, + * or (at your option) any later version. + * + * fiware-iotagent-lib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public + * License along with fiware-iotagent-lib. + * If not, see http://www.gnu.org/licenses/. + * + * For those usages not covered by the GNU Affero General Public License + * please contact with::[contacto@tid.es] + * + * Modified by: Daniel Calvo - ATOS Research & Innovation + */ + +/* eslint-disable no-unused-vars */ + +const iotAgentLib = require('../../../../lib/fiware-iotagent-lib'); +const request = require('request'); +const should = require('should'); +const iotAgentConfig = { + logLevel: 'FATAL', + contextBroker: { + host: '192.168.1.1', + port: '1026', + ngsiVersion: 'mixed' + }, + server: { + name: 'testAgent', + port: 4041, + baseRoot: '/' + }, + types: {}, + deviceRegistry: { + type: 'mongodb' + }, + mongodb: { + host: 'localhost', + port: '27017', + db: 'iotagent' + }, + service: 'smartGondor', + subservice: 'gardens', + providerUrl: 'http://smartGondor.com', + deviceRegistrationDuration: 'P1M' +}; +const mongo = require('mongodb').MongoClient; +const mongoUtils = require('../../mongodb/mongoDBUtils'); +const optionsCreationDefault = { + url: 'http://localhost:4041/iot/services', + method: 'POST', + json: { + services: [ + { + apikey: 'default-test', + cbroker: 'http://orion:1026', + entity_type: 'Device', + resource: '/iot/default', + attributes: [ + { + object_id: 's', + name: 'status', + type: 'Property' + } + ] + } + ] + }, + headers: { + 'fiware-service': 'smartGondor', + 'fiware-servicepath': 'gardens' + } +}; +const optionsCreationV2 = { + url: 'http://localhost:4041/iot/services', + method: 'POST', + json: { + services: [ + { + apikey: 'v2-test', + cbroker: 'http://orion:1026', + ngsiVersion: 'v2', + entity_type: 'Device', + resource: '/iot/v2', + attributes: [ + { + object_id: 's', + name: 'status', + type: 'Property' + } + ] + } + ] + }, + headers: { + 'fiware-service': 'smartGondor', + 'fiware-servicepath': 'gardens' + } +}; + +const optionsCreationLD = { + url: 'http://localhost:4041/iot/services', + method: 'POST', + json: { + services: [ + { + apikey: 'ld-test', + cbroker: 'http://orion:1026', + entity_type: 'Device', + ngsiVersion: 'ld', + resource: '/iot/ld', + attributes: [ + { + object_id: 's', + name: 'status', + type: 'Property' + } + ] + } + ] + }, + headers: { + 'fiware-service': 'smartGondor', + 'fiware-servicepath': 'gardens' + } +}; + +const deviceCreationV2 = { + url: 'http://localhost:4041/iot/devices', + method: 'POST', + json: { + devices: [ + { + device_id: 'light2', + entity_name: 'light2', + entity_type: 'Device', + ngsiVersion: 'v2' + } + ] + }, + headers: { + 'fiware-service': 'smartGondor', + 'fiware-servicepath': 'gardens' + } +}; +let iotAgentDb; +const nock = require('nock'); +let contextBrokerMock; + +describe('Mixed Mode: ngsiVersion test', function () { + const values = [ + { + name: 's', + type: 'Property', + value: true + } + ]; + + beforeEach(function (done) { + mongoUtils.cleanDbs(function () { + iotAgentLib.activate(iotAgentConfig, function () { + mongo.connect('mongodb://localhost:27017/iotagent', { useNewUrlParser: true }, function (err, db) { + iotAgentDb = db; + done(); + }); + }); + }); + }); + + afterEach(function (done) { + iotAgentLib.deactivate(function () { + iotAgentDb.close(function (error) { + mongoUtils.cleanDbs(done); + }); + }); + }); + describe('When a new default device group is provisioned', function () { + beforeEach(function (done) { + nock.cleanAll(); + contextBrokerMock = nock('http://192.168.1.1:1026') + .matchHeader('fiware-service', 'smartGondor') + .post('/v2/entities/light1/attrs') + .query({ type: 'Device' }) + .reply(204); + + request(optionsCreationDefault, function (error, response, body) { + done(); + }); + }); + it('should operate using NGSI-v2', function (done) { + iotAgentLib.update('light1', 'Device', 'default-test', values, function (error) { + should.not.exist(error); + contextBrokerMock.done(); + done(); + }); + }); + }); + + describe('When a new v2 device group is provisioned', function () { + beforeEach(function (done) { + nock.cleanAll(); + contextBrokerMock = nock('http://192.168.1.1:1026') + .matchHeader('fiware-service', 'smartGondor') + .post('/v2/entities/light1/attrs') + .query({ type: 'Device' }) + .reply(204); + + request(optionsCreationV2, function (error, response, body) { + done(); + }); + }); + it('should operate using NGSI-v2', function (done) { + iotAgentLib.update('light1', 'Device', 'v2-test', values, function (error) { + should.not.exist(error); + contextBrokerMock.done(); + done(); + }); + }); + }); + + describe('When an NGSI-LD device group is provisioned', function () { + beforeEach(function (done) { + nock.cleanAll(); + contextBrokerMock = nock('http://192.168.1.1:1026') + .matchHeader('NGSILD-Tenant', 'smartGondor') + .post('/ngsi-ld/v1/entityOperations/upsert/') + .reply(204); + request(optionsCreationLD, function (error, response, body) { + done(); + }); + }); + it('should operate using NGSI-LD', function (done) { + iotAgentLib.update('light1', 'Device', 'ld-test', values, function (error) { + should.not.exist(error); + contextBrokerMock.done(); + done(); + }); + }); + }); + + describe('When a new NGSI-LD device group is provisioned and overridden', function () { + beforeEach(function (done) { + nock.cleanAll(); + + contextBrokerMock = nock('http://192.168.1.1:1026') + .matchHeader('fiware-service', 'smartGondor') + .matchHeader('fiware-servicepath', 'gardens') + .post('/v2/entities?options=upsert') + .reply(204); + + contextBrokerMock = nock('http://192.168.1.1:1026') + .post('/v2/entities/light2/attrs') + .query({ type: 'Device' }) + .reply(204); + request(optionsCreationLD, function (error, response, body) { + request(deviceCreationV2, function (error, response, body) { + done(); + }); + }); + }); + it('should operate using NGSI-v2', function (done) { + iotAgentLib.update('light2', 'Device', 'v2-test', values, { ngsiVersion: 'v2', type: 'Device' }, function ( + error + ) { + should.not.exist(error); + contextBrokerMock.done(); + done(); + }); + }); + }); +}); From 4ed3e789bd9c2e772daa5d00587c24f63876d61b Mon Sep 17 00:00:00 2001 From: Jason Fox Date: Thu, 26 Nov 2020 16:29:28 +0100 Subject: [PATCH 27/27] Remove merge artifact. --- doc/api.md | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/doc/api.md b/doc/api.md index 8611099cc..e1a294552 100644 --- a/doc/api.md +++ b/doc/api.md @@ -225,12 +225,9 @@ the API resource fields and the same fields in the database model. | `internal_attributes` | `internalAttributes` | List of internal attributes with free format for specific IoT Agent configuration | LWM2M mappings from object URIs to attributes | | `static_attributes` | `staticAttributes` | List of static attributes to append to the entity. All the updateContext requests to the CB will have this set of attributes appended. | `[ { "name": "attr_name", "type": "Text" } ]` | | `expressionLanguage` | `expresionLanguage` | optional boolean value, to set expression language used to compute expressions, possible values are: legacy or jexl. When not set or wrongly set, legacy is used as default value. | -<<<<<<< HEAD -| `explicitAttrs` | `explicitAttrs` | Boolean value to support selective ignore of measures for device so that IOTA doesn’t progress. If not specified default is false. | `true/false` | -======= + | `explicitAttrs` | `explicitAttrs` | Boolean value to support selective ignore of measures for device so that IOTA doesn’t progress. If not specified default is `false`. | `true/false` | -| `ngsiVersion` | `ngsiVersion` | optional string value used in mixed mode to switch between **NGSI-v2** and **NGSI-LD**payloads. The default is `v2`. | `v2/ld` | ->>>>>>> d272d82... Add mixed mode +| `ngsiVersion` | `ngsiVersion` | optional string value used in mixed mode to switch between **NGSI-v2** and **NGSI-LD**payloads. The default is `v2`. | `v2/ld/mixed` | #### Attribute lists