From 53624dd7d02167d9982ad3af5087ae1de63a7b58 Mon Sep 17 00:00:00 2001 From: Bas Date: Mon, 28 May 2018 18:43:06 +0200 Subject: [PATCH 01/17] wip --- package.json | 1 + src/CharacteristicEnums.js | 33 ++++-- src/DroneCommand.js | 2 +- src/DroneConnection.js | 38 ++----- src/connectors/BLEConnector.js | 190 ++++++++++++++++++++++++++++++++ src/connectors/WifiConnector.js | 0 test-wifi.js | 54 +++++++++ yarn.lock | 15 +++ 8 files changed, 298 insertions(+), 35 deletions(-) create mode 100644 src/connectors/BLEConnector.js create mode 100644 src/connectors/WifiConnector.js create mode 100644 test-wifi.js diff --git a/package.json b/package.json index 965fbb51..385ba4e6 100644 --- a/package.json +++ b/package.json @@ -20,6 +20,7 @@ "ava": "0.25.0", "eslint": "4.19.1", "jsdoc": "3.5.5", + "mdns": "^2.4.0", "minami-compat": "1.2.4" }, "scripts": { diff --git a/src/CharacteristicEnums.js b/src/CharacteristicEnums.js index e4028f1a..0c5259be 100644 --- a/src/CharacteristicEnums.js +++ b/src/CharacteristicEnums.js @@ -17,10 +17,10 @@ const Enum = require('./util/Enum'); * @type {Enum} */ const characteristicSendUuids = new Enum({ - SEND_NO_ACK: '0a', // not-ack commands (PCMD only) - SEND_WITH_ACK: '0b', // ack commands (all piloting commands) - SEND_HIGH_PRIORITY: '0c', // emergency commands - ACK_COMMAND: '1e', // ack for data sent on 0e + SEND_NO_ACK: 'fa0a', // not-ack commands (PCMD only) + SEND_WITH_ACK: 'fa0b', // ack commands (all piloting commands) + SEND_HIGH_PRIORITY: 'fa0c', // emergency commands + ACK_COMMAND: 'fa1e', // ack for data sent on 0e }); /** @@ -34,13 +34,30 @@ const characteristicSendUuids = new Enum({ * @type {Enum} */ const characteristicReceiveUuids = new Enum({ - ACK_DRONE_DATA: '0e', // drone data that needs an ack (needs to be ack on 1e) - NO_ACK_DRONE_DATA: '0f', // data from drone (including battery and others), no ack - ACK_COMMAND_SENT: '1b', // ack 0b channel, SEND_WITH_ACK - ACK_HIGH_PRIORITY: '1c', // ack 0c channel, SEND_HIGH_PRIORITY + ACK_DRONE_DATA: 'fb0e', // drone data that needs an ack (needs to be ack on 1e) + NO_ACK_DRONE_DATA: 'fb0f', // data from drone (including battery and others), no ack + ACK_COMMAND_SENT: 'fb1b', // ack 0b channel, SEND_WITH_ACK + ACK_HIGH_PRIORITY: 'fb1c', // ack 0c channel, SEND_HIGH_PRIORITY }); +/** + * Receive and send characteristsic UUIDs + * + * @property {string} ACK_DRONE_DATA - drone data that needs an ack (needs to be ack on 1e) + * @property {string} NO_ACK_DRONE_DATA - data from drone (including battery and others), no ack + * @property {string} ACK_COMMAND_SENT - ack 0b channel, SEND_WITH_ACK + * @property {string} ACK_HIGH_PRIORITY - ack 0c channel, SEND_HIGH_PRIORITY + * @property {string} SEND_NO_ACK - not-ack commands (PCMD only) + * @property {string} SEND_WITH_ACK - ack commands (all piloting commands) + * @property {string} SEND_HIGH_PRIORITY - emergency commands + * @property {string} ACK_COMMAND - ack for data sent on 0e + * + * @type {Enum} + */ +const characteristicUuids = new Enum(Object.assign({}, characteristicSendUuids, characteristicReceiveUuids)); + module.exports = { characteristicSendUuids, characteristicReceiveUuids, + characteristicUuids, }; diff --git a/src/DroneCommand.js b/src/DroneCommand.js index d359dcb4..be578aac 100644 --- a/src/DroneCommand.js +++ b/src/DroneCommand.js @@ -177,7 +177,7 @@ class DroneCommand { get sendCharacteristicUuid() { const t = bufferCharTranslationMap[this.bufferType] || 'SEND_WITH_ACK'; - return 'fa' + characteristicSendUuids[t]; + return characteristicSendUuids[t]; } /** diff --git a/src/DroneConnection.js b/src/DroneConnection.js index 23dc6ec2..5ed6c974 100644 --- a/src/DroneConnection.js +++ b/src/DroneConnection.js @@ -173,12 +173,13 @@ class DroneConnection extends EventEmitter { for (const uuid of handshakeUuids) { const target = this.getCharacteristic(uuid); + // @todo Function needs a callback, should investigate target.subscribe(); } Logger.debug('Adding listeners (fb uuid prefix)'); for (const uuid of characteristicReceiveUuids.values()) { - const target = this.getCharacteristic('fb' + uuid); + const target = this.getCharacteristic(uuid); target.subscribe(); target.on('data', data => this._handleIncoming(uuid, data)); @@ -251,28 +252,13 @@ class DroneConnection extends EventEmitter { return new Promise(accept => { Logger.debug(`SEND ${command.bufferType}[${packetId}]: `, command.toString()); - this.getCharacteristic(command.sendCharacteristicUuid).write(buffer, true); - - switch (command.bufferType) { - case 'DATA_WITH_ACK': - case 'SEND_WITH_ACK': - if (!this._commandCallback['ACK_COMMAND_SENT']) { - this._commandCallback['ACK_COMMAND_SENT'] = []; - } - - this._commandCallback['ACK_COMMAND_SENT'][packetId] = accept; - break; - case 'SEND_HIGH_PRIORITY': - if (!this._commandCallback['ACK_HIGH_PRIORITY']) { - this._commandCallback['ACK_HIGH_PRIORITY'] = []; - } - - this._commandCallback['ACK_HIGH_PRIORITY'][packetId] = accept; - break; - default: - accept(); - break; + if (command.shouldAck) { + this._commandCallback[packetId] = accept; + } else { + accept(); } + + this.getCharacteristic(command.sendCharacteristicUuid).write(buffer, true); }); } @@ -298,10 +284,10 @@ class DroneConnection extends EventEmitter { case 'ACK_HIGH_PRIORITY': const packetId = buffer.readUInt8(2); - callback = (this._commandCallback[channel] || {})[packetId]; + callback = this._commandCallback[packetId]; if (callback) { - delete this._commandCallback[channel][packetId]; + delete this._commandCallback[packetId]; } if (typeof callback === 'function') { @@ -337,7 +323,7 @@ class DroneConnection extends EventEmitter { this._sensorStore[token] = command; - Logger.debug('RECV:', command.toString()); + Logger.debug(`RECV ${command.bufferType}:`, command.toString()); /** * Fires when a new sensor reading has been received @@ -448,7 +434,7 @@ class DroneConnection extends EventEmitter { buffer.writeUIntLE(this._getStep(characteristic), 1, 1); buffer.writeUIntLE(packetId, 2, 1); - this.getCharacteristic('fa' + characteristic).write(buffer, true); + this.getCharacteristic(characteristic).write(buffer, true); } } diff --git a/src/connectors/BLEConnector.js b/src/connectors/BLEConnector.js new file mode 100644 index 00000000..fe592e8d --- /dev/null +++ b/src/connectors/BLEConnector.js @@ -0,0 +1,190 @@ +const noble = require('noble'); +const EventEmitter = require('events'); +const Logger = require('winston'); +const { characteristicUuids, characteristicReceiveUuids } = require('../CharacteristicEnums'); + +const MANUFACTURER_SERIALS = [ + '4300cf1900090100', + '4300cf1909090100', + '4300cf1907090100', +]; + +const DRONE_PREFIXES = [ + 'RS_', + 'Mars_', + 'Travis_', + 'Maclan_', + 'Mambo_', + 'Blaze_', + 'NewZ_', +]; + +class BLEConnector extends EventEmitter { + constructor() { + + } + + connect() { + if (this.peripheral) { + noble.warn('Already connected. Ignoring connect request'); + } + + if (noble.state === 'unknown') { + Logger.debug('Noble state is unknown. Waiting for it to change to poweredOn'); + noble.once('stateChange', () => this.connect()); + } else if (noble.state === 'poweredOn') { + Logger.info('Searching for drones...'); + + noble.on('discover', peripheral => this._onPeripheralDiscovery(peripheral)); + + noble.startScanning(); + } + } + + /** + * Event handler for when noble discovers a peripheral + * Validates it is a drone and attempts to connect. + * + * @param {Peripheral} peripheral a noble peripheral class + * @return {undefined} + * @private + */ + _onPeripheralDiscovery(peripheral) { + if (!this._validatePeripheral(peripheral)) { + return; + } + + Logger.info(`Peripheral found ${peripheral.advertisement.localName}`); //ex: Mambo_646859 + + noble.stopScanning(); + + peripheral.connect((error) => { + if (error) { + throw error; + } + + this._peripheral = peripheral; + + this._setupPeripheral(); + }); + } + + /** + * Validates a noble Peripheral class is a Parrot MiniDrone + * @param {Peripheral} peripheral a noble peripheral object class + * @return {boolean} If the peripheral is a drone + * @private + */ + _validatePeripheral(peripheral) { + if (!peripheral) { + return false; + } + + const localName = peripheral.advertisement.localName; + const manufacturer = peripheral.advertisement.manufacturerData; + const matchesFilter = this.droneFilter ? localName === this.droneFilter : false; + + const localNameMatch = matchesFilter || DRONE_PREFIXES.some((prefix) => localName && localName.indexOf(prefix) >= 0); + const manufacturerMatch = manufacturer && MANUFACTURER_SERIALS.indexOf(manufacturer) >= 0; + + // Is TRUE according to droneFilter or if empty, for EITHER an "RS_" name OR manufacturer code. + return localNameMatch || manufacturerMatch; + } + + /** + * Sets up a peripheral and finds all of it's services and characteristics + * @return {undefined} + */ + _setupPeripheral() { + this.peripheral.discoverAllServicesAndCharacteristics((err, services, characteristics) => { + if (err) { + throw err; + } + + this.characteristics = characteristics; + + if (Logger.level === 'debug') { + Logger.debug('Found the following characteristics:'); + + // Get uuids + const characteristicUuids = this.characteristics.map(x => x.uuid.substr(4, 4).toLowerCase()); + + characteristicUuids.sort(); + + characteristicUuids.join(', ').replace(/([^\n]{40,}?), /g, '$1|').split('|').map(s => Logger.debug(s)); + } + + Logger.debug('Preforming handshake'); + for (const uuid of handshakeUuids) { + const target = this.getCharacteristic(uuid); + + target.subscribe(); + } + + Logger.debug('Adding listeners (fb uuid prefix)'); + for (const uuid of characteristicReceiveUuids.values()) { + const target = this.getCharacteristic('fb' + uuid); + + target.subscribe(); + target.on('data', data => this._handleIncoming(uuid, data)); + } + + Logger.info(`Device connected ${this.peripheral.advertisement.localName}`); + + // Register some event handlers + /** + * Drone disconnected event + * Fired when the bluetooth connection has been disconnected + * + * @event DroneCommand#disconnected + */ + noble.on('disconnect', () => this.disconnect()); + + setTimeout(() => { + /** + * Drone connected event + * You can control the drone once this event has been triggered. + * + * @event DroneCommand#connected + */ + this.emit('connected'); + }, 200); + }); + } + + /** + * @returns {Peripheral} a noble peripheral object class + */ + get peripheral() { + return this._peripheral; + } + + /** + * Finds a Noble Characteristic class for the given characteristic UUID + * @param {String} uuid The characteristics UUID + * @return {Characteristic} The Noble Characteristic corresponding to that UUID + */ + getCharacteristic(uuid) { + uuid = uuid.toLowerCase(); + + if (typeof this._characteristicLookupCache[uuid] === 'undefined') { + this._characteristicLookupCache[uuid] = this.characteristics.find(x => x.uuid.substr(4, 4).toLowerCase() === uuid); + } + + return this._characteristicLookupCache[uuid]; + } + + write(characteristic, buffer) { + this.getCharacteristic(characteristicUuids[characteristic]).write(buffer, true); + } + + disconnect() { + delete this._peripheral; + + this.characteristics = []; + + this.emit('disconnected'); + } +} + +module.exports = BLEConnector; diff --git a/src/connectors/WifiConnector.js b/src/connectors/WifiConnector.js new file mode 100644 index 00000000..e69de29b diff --git a/test-wifi.js b/test-wifi.js new file mode 100644 index 00000000..0ba95326 --- /dev/null +++ b/test-wifi.js @@ -0,0 +1,54 @@ +const mdns = require('mdns'); +const Logger = require('winston'); +const net = require('net'); + +Logger.level = 'debug'; + +let mambo; + +function _onMdnsServiceDiscovery(service) { + if (service.type.name.startsWith('arsdk-') && service.type.protocol === 'udp') { + browser.stop(); + + Logger.info('Found service ' + service.type.toString()); + + mambo = service; + console.log(service); + + const ip = service.addresses[0]; + const port = service.port; + + const config = { + 'd2c_port': 43210, + 'controller_type': 'minidrone-js', + 'controller_name': 'com.example.arsdkapp' + }; + + var client = new net.Socket(); + client.connect(port, ip, function() { + console.log('Connected'); + console.log('Sending: ' + JSON.stringify(config)); + client.write(JSON.stringify(config)); + }); + + client.on('data', function(data) { + console.log('Received: ' + data); + client.destroy(); // kill client after server's response + }); + + client.on('close', function() { + console.log('Connection closed'); + }); + } +} + +var sequence = [ + mdns.rst.DNSServiceResolve() + , mdns.rst.DNSServiceGetAddrInfo({ families: [4] }), +]; + +let browser = mdns.createBrowser(mdns.udp('_arsdk-090b'), { resolverSequence: sequence }); // createBrowser(mdns.udp('arsdk-090b')); + +browser.on('serviceUp', _onMdnsServiceDiscovery); + +browser.start(); diff --git a/yarn.lock b/yarn.lock index 60916294..731a0ea6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -641,6 +641,10 @@ binary-extensions@^1.0.0: version "1.11.0" resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.11.0.tgz#46aa1751fb6a2f93ee5e689bb1087d4b14c6c205" +bindings@~1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.2.1.tgz#14ad6113812d2d37d72e67b4cacb4bb726505f11" + block-stream@*: version "0.0.9" resolved "https://registry.yarnpkg.com/block-stream/-/block-stream-0.0.9.tgz#13ebfe778a03205cfe03751481ebb4b3300c126a" @@ -2213,6 +2217,13 @@ md5-o-matic@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/md5-o-matic/-/md5-o-matic-0.1.1.tgz#822bccd65e117c514fab176b25945d54100a03c3" +mdns@^2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/mdns/-/mdns-2.4.0.tgz#dc9d7152086a2ca8f1ed81eb451a7ee4cb456940" + dependencies: + bindings "~1.2.1" + nan "^2.10.0" + meow@^3.7.0: version "3.7.0" resolved "https://registry.yarnpkg.com/meow/-/meow-3.7.0.tgz#72cb668b425228290abbfa856892587308a801fb" @@ -2313,6 +2324,10 @@ nan@^2.0.5, nan@^2.3.0, nan@^2.8.0: version "2.8.0" resolved "https://registry.yarnpkg.com/nan/-/nan-2.8.0.tgz#ed715f3fe9de02b57a5e6252d90a96675e1f085a" +nan@^2.10.0: + version "2.10.0" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.10.0.tgz#96d0cd610ebd58d4b4de9cc0c6828cda99c7548f" + natural-compare@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" From f0f71c419878c4471db8ffb74dc640eef3b06589 Mon Sep 17 00:00:00 2001 From: Bas Date: Mon, 28 May 2018 22:50:29 +0200 Subject: [PATCH 02/17] wip --- examples/toggleAutoTakeOff.js | 14 +- src/ARDiscoveryError.js | 4 +- src/DroneCommand.js | 33 +--- src/DroneConnection.js | 308 +++++--------------------------- src/connectors/BLEConnector.js | 48 ++++- src/connectors/WifiConnector.js | 144 +++++++++++++++ src/index.js | 2 + 7 files changed, 247 insertions(+), 306 deletions(-) diff --git a/examples/toggleAutoTakeOff.js b/examples/toggleAutoTakeOff.js index b6d550ca..d49b0ffd 100644 --- a/examples/toggleAutoTakeOff.js +++ b/examples/toggleAutoTakeOff.js @@ -1,20 +1,28 @@ -const { DroneConnection, CommandParser } = require('../src'); +const { DroneConnection, CommandParser, WifiConnector, BLEConnector } = require('../src'); const Logger = require('winston'); Logger.level = 'debug'; const parser = new CommandParser(); -const drone = new DroneConnection(); +const connector = new WifiConnector(); +const drone = new DroneConnection(connector); +connector.connect(); const autoTakeOffOn = parser.getCommand('minidrone', 'Piloting', 'AutoTakeOffMode', { state: 1 }); const autoTakeOffOff = parser.getCommand('minidrone', 'Piloting', 'AutoTakeOffMode', { state: 0 }); +const allState = parser.getCommand('common', 'Common', 'AllStates'); function sleep(ms) { return new Promise(a => setTimeout(a, ms)); } drone.on('connected', async () => { - await drone.runCommand(autoTakeOffOff); + await sleep(200); + drone.runCommand(allState); + + await sleep(1000); + + await drone.runCommand(autoTakeOffOn); Logger.debug('Command got ACK\'d'); await sleep(2000); diff --git a/src/ARDiscoveryError.js b/src/ARDiscoveryError.js index 1651b65d..002eec58 100644 --- a/src/ARDiscoveryError.js +++ b/src/ARDiscoveryError.js @@ -47,7 +47,7 @@ const Enum = require('./util/Enum'); * * @see https://github.com/Parrot-Developers/libARDiscovery/blob/master/Includes/libARDiscovery/ARDISCOVERY_Error.h */ -const ARDiscoveryError = module.exports = new Enum({ +const ARDiscoveryError = new Enum({ // Do not change these values, they are sent by the device in the Json of connection. OK: 0, ERROR: -1, @@ -100,3 +100,5 @@ const ARDiscoveryError = module.exports = new Enum({ ERROR_JSON_PARSSING: -5999, ERROR_JSON_BUFFER_SIZE: -5998, }); + +module.exports = ARDiscoveryError; diff --git a/src/DroneCommand.js b/src/DroneCommand.js index be578aac..fef0d65d 100644 --- a/src/DroneCommand.js +++ b/src/DroneCommand.js @@ -1,36 +1,7 @@ const DroneCommandArgument = require('./DroneCommandArgument'); const Enum = require('./util/Enum'); const { characteristicSendUuids } = require('./CharacteristicEnums'); - -/** - * Buffer types - * - * @property {number} ACK - Acknowledgment of previously received data - * @property {number} DATA - Normal data (no ack requested) - * @property {number} NON_ACK - Same as DATA - * @property {number} HIGH_PRIO - Not sure about this one could be LLD - * @property {number} LOW_LATENCY_DATA - Treated as normal data on the network, but are given higher priority internally - * @property {number} DATA_WITH_ACK - Data requesting an ack. The receiver must send an ack for this data unit! - * - * @type {Enum} - */ -const bufferType = new Enum({ - ACK: 0x02, - DATA: 0x02, - NON_ACK: 0x02, - HIGH_PRIO: 0x02, - LOW_LATENCY_DATA: 0x03, - DATA_WITH_ACK: 0x04, -}); - -const bufferCharTranslationMap = new Enum({ - ACK: 'ACK_COMMAND', - DATA: 'SEND_NO_ACK', - NON_ACK: 'SEND_NO_ACK', - HIGH_PRIO: 'SEND_HIGH_PRIORITY', - LOW_LATENCY_DATA: 'SEND_NO_ACK', - DATA_WITH_ACK: 'SEND_WITH_ACK', -}); +const { bufferType, bufferCharacteristicTranslationMap } = require('./BufferEnums'); /** * Drone command @@ -175,7 +146,7 @@ class DroneCommand { * @returns {string} - uuid as a string */ get sendCharacteristicUuid() { - const t = bufferCharTranslationMap[this.bufferType] || 'SEND_WITH_ACK'; + const t = bufferCharacteristicTranslationMap[this.bufferType] || 'SEND_WITH_ACK'; return characteristicSendUuids[t]; } diff --git a/src/DroneConnection.js b/src/DroneConnection.js index 5ed6c974..cf85c8e1 100644 --- a/src/DroneConnection.js +++ b/src/DroneConnection.js @@ -3,43 +3,7 @@ const Logger = require('winston'); const Enum = require('./util/Enum'); const CommandParser = require('./CommandParser'); const { characteristicSendUuids, characteristicReceiveUuids } = require('./CharacteristicEnums'); - -const MANUFACTURER_SERIALS = [ - '4300cf1900090100', - '4300cf1909090100', - '4300cf1907090100', -]; - -const DRONE_PREFIXES = [ - 'RS_', - 'Mars_', - 'Travis_', - 'Maclan_', - 'Mambo_', - 'Blaze_', - 'NewZ_', -]; - -// http://forum.developer.parrot.com/t/minidrone-characteristics-uuid/4686/3 -const handshakeUuids = [ - 'fb0f', 'fb0e', 'fb1b', 'fb1c', - 'fd22', 'fd23', 'fd24', 'fd52', - 'fd53', 'fd54', -]; - -// the following UUID segments come from the Mambo and from the documenation at -// http://forum.developer.parrot.com/t/minidrone-characteristics-uuid/4686/3 -// the 3rd and 4th bytes are used to identify the service -const serviceUuids = new Enum({ - 'fa': 'ARCOMMAND_SENDING_SERVICE', - 'fb': 'ARCOMMAND_RECEIVING_SERVICE', - 'fc': 'PERFORMANCE_COUNTER_SERVICE', - 'fd21': 'NORMAL_BLE_FTP_SERVICE', - 'fd51': 'UPDATE_BLE_FTP', - 'fe00': 'UPDATE_RFCOMM_SERVICE', - '1800': 'Device Info', - '1801': 'unknown', -}); +const { bufferType } = require('./BufferEnums'); /** * Drone connection class @@ -54,187 +18,35 @@ const serviceUuids = new Enum({ class DroneConnection extends EventEmitter { /** * Creates a new DroneConnection instance - * @param {string} [droneFilter=] - The drone name leave blank for no filter + * @param {BLEConnector} connector - The drone connector to use (BLE, Wifi) * @param {boolean} [warmup=true] - Warmup the command parser */ - constructor(droneFilter = '', warmup = true) { + constructor(connector, warmup = true) { super(); - this.characteristics = []; - - this._characteristicLookupCache = {}; this._commandCallback = {}; this._sensorStore = {}; this._stepStore = {}; - this.droneFilter = droneFilter; + this.connector = connector; + + this.connector.on('disconnect', () => this.emit('disconnect')); + this.connector.on('connected', () => this.emit('connected')); + this.connector.on('data', data => this._handleIncoming(data)); - this.noble = require('noble'); this.parser = new CommandParser(); if (warmup) { // We'll do it for you so you don't have to this.parser.warmup(); } - - // bind noble event handlers - this.noble.on('stateChange', state => this._onNobleStateChange(state)); - this.noble.on('discover', peripheral => this._onPeripheralDiscovery(peripheral)); - } - - /** - * Event handler for when noble broadcasts a state change - * @param {String} state a string describing noble's state - * @return {undefined} - * @private - */ - _onNobleStateChange(state) { - Logger.debug(`Noble state changed to ${state}`); - - if (state === 'poweredOn') { - Logger.info('Searching for drones...'); - this.noble.startScanning(); - } - } - - /** - * Event handler for when noble discovers a peripheral - * Validates it is a drone and attempts to connect. - * - * @param {Peripheral} peripheral a noble peripheral class - * @return {undefined} - * @private - */ - _onPeripheralDiscovery(peripheral) { - if (!this._validatePeripheral(peripheral)) { - return; - } - - Logger.info(`Peripheral found ${peripheral.advertisement.localName}`); - - this.noble.stopScanning(); - - peripheral.connect((error) => { - if (error) { - throw error; - } - this._peripheral = peripheral; - - this._setupPeripheral(); - }); - } - - /** - * Validates a noble Peripheral class is a Parrot MiniDrone - * @param {Peripheral} peripheral a noble peripheral object class - * @return {boolean} If the peripheral is a drone - * @private - */ - _validatePeripheral(peripheral) { - if (!peripheral) { - return false; - } - - const localName = peripheral.advertisement.localName; - const manufacturer = peripheral.advertisement.manufacturerData; - const matchesFilter = this.droneFilter ? localName === this.droneFilter : false; - - const localNameMatch = matchesFilter || DRONE_PREFIXES.some((prefix) => localName && localName.indexOf(prefix) >= 0); - const manufacturerMatch = manufacturer && MANUFACTURER_SERIALS.indexOf(manufacturer) >= 0; - - // Is TRUE according to droneFilter or if empty, for EITHER an "RS_" name OR manufacturer code. - return localNameMatch || manufacturerMatch; - } - - /** - * Sets up a peripheral and finds all of it's services and characteristics - * @return {undefined} - */ - _setupPeripheral() { - this.peripheral.discoverAllServicesAndCharacteristics((err, services, characteristics) => { - if (err) { - throw err; - } - - this.characteristics = characteristics; - - if (Logger.level === 'debug') { - Logger.debug('Found the following characteristics:'); - - // Get uuids - const characteristicUuids = this.characteristics.map(x => x.uuid.substr(4, 4).toLowerCase()); - - characteristicUuids.sort(); - - characteristicUuids.join(', ').replace(/([^\n]{40,}?), /g, '$1|').split('|').map(s => Logger.debug(s)); - } - - Logger.debug('Preforming handshake'); - for (const uuid of handshakeUuids) { - const target = this.getCharacteristic(uuid); - - // @todo Function needs a callback, should investigate - target.subscribe(); - } - - Logger.debug('Adding listeners (fb uuid prefix)'); - for (const uuid of characteristicReceiveUuids.values()) { - const target = this.getCharacteristic(uuid); - - target.subscribe(); - target.on('data', data => this._handleIncoming(uuid, data)); - } - - Logger.info(`Device connected ${this.peripheral.advertisement.localName}`); - - // Register some event handlers - /** - * Drone disconnected event - * Fired when the bluetooth connection has been disconnected - * - * @event DroneCommand#disconnected - */ - this.noble.on('disconnect', () => this.emit('disconnected')); - - setTimeout(() => { - /** - * Drone connected event - * You can control the drone once this event has been triggered. - * - * @event DroneCommand#connected - */ - this.emit('connected'); - }, 200); - }); - } - - /** - * @returns {Peripheral} a noble peripheral object class - */ - get peripheral() { - return this._peripheral; } /** * @returns {boolean} If the drone is connected */ get connected() { - return this.characteristics.length > 0; - } - - /** - * Finds a Noble Characteristic class for the given characteristic UUID - * @param {String} uuid The characteristics UUID - * @return {Characteristic} The Noble Characteristic corresponding to that UUID - */ - getCharacteristic(uuid) { - uuid = uuid.toLowerCase(); - - if (typeof this._characteristicLookupCache[uuid] === 'undefined') { - this._characteristicLookupCache[uuid] = this.characteristics.find(x => x.uuid.substr(4, 4).toLowerCase() === uuid); - } - - return this._characteristicLookupCache[uuid]; + return this.connector.connected; } /** @@ -245,7 +57,7 @@ class DroneConnection extends EventEmitter { */ runCommand(command) { const buffer = command.toBuffer(); - const packetId = this._getStep(command.bufferType); + const packetId = this._getStep(command.bufferFlag); buffer.writeUIntLE(packetId, 1, 1); @@ -257,8 +69,7 @@ class DroneConnection extends EventEmitter { } else { accept(); } - - this.getCharacteristic(command.sendCharacteristicUuid).write(buffer, true); + this.connector.write(buffer, command.sendCharacteristicUuid); }); } @@ -268,39 +79,27 @@ class DroneConnection extends EventEmitter { * @param {Buffer} buffer - The packet data * @private */ - _handleIncoming(channelUuid, buffer) { - const channel = characteristicReceiveUuids.findForValue(channelUuid); - let callback; - - switch (channel) { - case 'ACK_DRONE_DATA': - // We need to response with an ack - this._updateSensors(buffer, true); - break; - case 'NO_ACK_DRONE_DATA': - this._updateSensors(buffer); - break; - case 'ACK_COMMAND_SENT': - case 'ACK_HIGH_PRIORITY': - const packetId = buffer.readUInt8(2); - - callback = this._commandCallback[packetId]; - - if (callback) { - delete this._commandCallback[packetId]; - } - - if (typeof callback === 'function') { - Logger.debug(`${channel}: packet id ${packetId}`); - callback(); - } else { - Logger.debug(`${channel}: packet id ${packetId}, no callback :(`); - } - - break; - default: - Logger.warn(`Got data on an unknown channel ${channel}(${channelUuid}) (wtf!?)`); - break; + _handleIncoming(buffer) { + const characteristic = bufferType.findForValue(buffer.readUInt8(0)); + + Logger.debug(buffer); + + if (characteristic !== 'ACK') { + this._updateSensors(buffer); + } else { + // @todo figure out why two ACK's in a row are received + const packetId = buffer.readUInt8(2); + const callback = this._commandCallback[packetId]; + + if (typeof callback === 'function') { + Logger.debug(`ACK_*: packet id ${packetId}`); + + delete this._commandCallback[packetId]; + + callback(); + } else { + Logger.debug(`ACK_*: packet id ${packetId}, no callback :(`); + } } } @@ -308,11 +107,10 @@ class DroneConnection extends EventEmitter { * Update the sensor * * @param {Buffer} buffer - Command buffer - * @param {boolean} ack - If an acknowledgement for receiving the data should be sent * @private * @fires DroneConnection#sensor: */ - _updateSensors(buffer, ack = false) { + _updateSensors(buffer) { if (buffer[2] === 0) { return; } @@ -325,6 +123,12 @@ class DroneConnection extends EventEmitter { Logger.debug(`RECV ${command.bufferType}:`, command.toString()); + if (command.shouldAck) { + const packetId = buffer.readUInt8(1); + + this.ack(packetId); + } + /** * Fires when a new sensor reading has been received * @@ -343,12 +147,6 @@ class DroneConnection extends EventEmitter { Logger.warn('Unable to parse packet:', buffer); Logger.warn(e); } - - if (ack) { - const packetId = buffer.readUInt8(1); - - this.ack(packetId); - } } /** @@ -384,28 +182,11 @@ class DroneConnection extends EventEmitter { return command; } - /** - * Get the logger level - * @returns {string|number} - logger level - * @see {@link https://github.com/winstonjs/winston} - */ - get logLevel() { - return Logger.level; - } - - /** - * Set the logger level - * @param {string|number} value - logger level - * @see {@link https://github.com/winstonjs/winston} - */ - set logLevel(value) { - Logger.level = typeof value === 'number' ? value : value.toString(); - } - /** * used to count the drone command steps * @param {string} id - Step store id * @returns {number} - step number + * @todo steps should be grouped on bufferType (see bufferType enum) */ _getStep(id) { if (typeof this._stepStore[id] === 'undefined') { @@ -425,16 +206,15 @@ class DroneConnection extends EventEmitter { * @param {number} packetId - Id of the packet to ack */ ack(packetId) { - Logger.debug('ACK: packet id ' + packetId); + Logger.debug('SEND ACK: packet id ' + packetId); - const characteristic = characteristicSendUuids.ACK_COMMAND; const buffer = new Buffer(3); - buffer.writeUIntLE(characteristic, 0, 1); - buffer.writeUIntLE(this._getStep(characteristic), 1, 1); + buffer.writeUIntLE(bufferType.ACK, 0, 1); + buffer.writeUIntLE(this._getStep(bufferType.ACK), 1, 1); buffer.writeUIntLE(packetId, 2, 1); - this.getCharacteristic(characteristic).write(buffer, true); + this.connector.write(buffer, characteristicSendUuids.ACK_COMMAND); } } diff --git a/src/connectors/BLEConnector.js b/src/connectors/BLEConnector.js index fe592e8d..773d8002 100644 --- a/src/connectors/BLEConnector.js +++ b/src/connectors/BLEConnector.js @@ -1,6 +1,7 @@ const noble = require('noble'); const EventEmitter = require('events'); const Logger = require('winston'); +const Enum = require('../util/Enum'); const { characteristicUuids, characteristicReceiveUuids } = require('../CharacteristicEnums'); const MANUFACTURER_SERIALS = [ @@ -19,9 +20,35 @@ const DRONE_PREFIXES = [ 'NewZ_', ]; +// http://forum.developer.parrot.com/t/minidrone-characteristics-uuid/4686/3 +const handshakeUuids = [ + 'fb0f', 'fb0e', 'fb1b', 'fb1c', + 'fd22', 'fd23', 'fd24', 'fd52', + 'fd53', 'fd54', +]; + +// the following UUID segments come from the Mambo and from the documenation at +// http://forum.developer.parrot.com/t/minidrone-characteristics-uuid/4686/3 +// the 3rd and 4th bytes are used to identify the service +const serviceUuids = new Enum({ + 'fa': 'ARCOMMAND_SENDING_SERVICE', + 'fb': 'ARCOMMAND_RECEIVING_SERVICE', + 'fc': 'PERFORMANCE_COUNTER_SERVICE', + 'fd21': 'NORMAL_BLE_FTP_SERVICE', + 'fd51': 'UPDATE_BLE_FTP', + 'fe00': 'UPDATE_RFCOMM_SERVICE', + '1800': 'Device Info', + '1801': 'unknown', +}); + class BLEConnector extends EventEmitter { - constructor() { + constructor (droneFilter = '') { + super(); + this.droneFilter = droneFilter; + + this._characteristicLookupCache = {}; + this.characteristics = []; } connect() { @@ -54,7 +81,7 @@ class BLEConnector extends EventEmitter { return; } - Logger.info(`Peripheral found ${peripheral.advertisement.localName}`); //ex: Mambo_646859 + Logger.info(`Peripheral found ${peripheral.advertisement.localName}`); // ex: Mambo_646859 noble.stopScanning(); @@ -119,14 +146,15 @@ class BLEConnector extends EventEmitter { const target = this.getCharacteristic(uuid); target.subscribe(); + target.on('data', data => this.emit('data', data)); } - Logger.debug('Adding listeners (fb uuid prefix)'); + Logger.debug('Adding listeners: ' + characteristicReceiveUuids.values().join(', ')); for (const uuid of characteristicReceiveUuids.values()) { - const target = this.getCharacteristic('fb' + uuid); + const target = this.getCharacteristic(uuid); target.subscribe(); - target.on('data', data => this._handleIncoming(uuid, data)); + target.on('data', data => this.emit('data', data)); } Logger.info(`Device connected ${this.peripheral.advertisement.localName}`); @@ -174,8 +202,10 @@ class BLEConnector extends EventEmitter { return this._characteristicLookupCache[uuid]; } - write(characteristic, buffer) { - this.getCharacteristic(characteristicUuids[characteristic]).write(buffer, true); + write(buffer, characteristic) { + return new Promise(accept => { + this.getCharacteristic(characteristic).write(buffer, true, accept); + }); } disconnect() { @@ -185,6 +215,10 @@ class BLEConnector extends EventEmitter { this.emit('disconnected'); } + + get connected() { + return this.characteristics.length > 0; + } } module.exports = BLEConnector; diff --git a/src/connectors/WifiConnector.js b/src/connectors/WifiConnector.js index e69de29b..594c13a6 100644 --- a/src/connectors/WifiConnector.js +++ b/src/connectors/WifiConnector.js @@ -0,0 +1,144 @@ +const EventEmitter = require('events'); +const Logger = require('winston'); +const dgram = require('dgram'); +const net = require('net'); +const ARDiscoveryError = require('../ARDiscoveryError'); +const mdns = require('mdns'); + +class WifiConnector extends EventEmitter { + constructor(droneFilter = '', deviceId = '') { + super(); + + this.droneFilter = droneFilter; + this.deviceId = deviceId || Math.random().toString(36); // Should be persistant between connections + } + + connect() { + if (!this.browser && !this.server && !this.client) { + Logger.debug('Starting mDNS browser'); + + const resolverSequence = [ + // eslint-disable-next-line new-cap + mdns.rst.DNSServiceResolve(), + // eslint-disable-next-line new-cap + mdns.rst.DNSServiceGetAddrInfo({ families: [4] }), + ]; + + this.browser = mdns.createBrowser(mdns.udp('_arsdk-090b'), { resolverSequence }); // @todo browse all + + this.browser.on('serviceUp', service => this._onMdnsServiceDiscovery(service)); + + this.browser.start(); + } + } + + _onMdnsServiceDiscovery(service) { + if (!service.fullname.includes('_arsdk-')) { + return; + } + + if (this.droneFilter && service.name !== this.droneFilter) { + Logger.debug(`Found drone ${service.name} but it didn't match the drone filter`); + return; + } + + this.browser.stop(); + delete this.browser; + + Logger.debug(`Found drone ${service.name}`); + + this._handshake(service); + } + + _handshake(service) { + Logger.info('Doing Wifi handshake'); + + this.server = dgram.createSocket('udp4'); + + this.server.on('data', msg => { + Logger.debug('got data from server'); + this.emit(msg.msg) + }); + this.server.on('close', () => this.disconnect()); + this.server.on('error', (err) => { + this.disconnect(); + + throw err; + }); + + this.server.on('listening', () => { + const address = this.server.address(); + + Logger.debug(`Server listening ${address.address}:${address.port}`); + + const handshakeClient = new net.Socket(); + + handshakeClient.connect(service.port, service.addresses[0], () => { + const config = { + 'd2c_port': this.server.address().port, + 'controller_type': 'minidrone-js', + 'controller_name': 'me.shodan.minidrone-js', + // 'device_id': this.deviceId, // @ todo drone returns errors + }; + + Logger.debug('Negotiating connection:', config); + + handshakeClient.write(JSON.stringify(config)); + }); + + handshakeClient.on('data', data => { + data = data.toString(); + data = data.replace('\0', ''); // Remove trailing nullbyte + data = JSON.parse(data); + + Logger.debug('Got drone response: ', data); + + if (data.status !== 0) { + const error = ARDiscoveryError.findForValue(data.status); + + throw new Error(error); + } + + handshakeClient.destroy(); + + this.ip = service.addresses[0]; + this.port = data.c2d_port; + this.client = dgram.createSocket('udp4'); + + this.emit('connected'); + }); + }); + + this.server.bind(0); // random utp port + } + + write(buffer, characteristic) { + return new Promise((accept, reject) => { + this.client.send(buffer, this.port, this.ip, err => { + if (err) { + reject(err); + } + + accept(); + }); + }); + } + + disconnect() { + Logger.info('Disconnected'); + + delete this.browser; + delete this.server; + delete this.ip; + delete this.port; + delete this.client; + + this.emit('disconnected'); + } + + get connected() { + return this.server && this.client; + } +} + +module.exports = WifiConnector; diff --git a/src/index.js b/src/index.js index 0480b819..6eba4bed 100644 --- a/src/index.js +++ b/src/index.js @@ -3,4 +3,6 @@ module.exports = { CommandParser: require('./CommandParser'), DroneConnection: require('./DroneConnection'), ARDiscoveryError: require('./ARDiscoveryError'), + BLEConnector: require('./connectors/BLEConnector'), + WifiConnector: require('./connectors/WifiConnector'), }; From e1610d7b8f5df4830ddb4cc404ba25e4dc5b055e Mon Sep 17 00:00:00 2001 From: Bas Date: Mon, 28 May 2018 22:53:29 +0200 Subject: [PATCH 03/17] Add missing file --- src/BufferEnums.js | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 src/BufferEnums.js diff --git a/src/BufferEnums.js b/src/BufferEnums.js new file mode 100644 index 00000000..d8f75361 --- /dev/null +++ b/src/BufferEnums.js @@ -0,0 +1,41 @@ +const Enum = require('./util/Enum'); + +/** + * Buffer types + * + * @property {number} ACK - Acknowledgment of previously received data + * @property {number} DATA - Normal data (no ack requested) + * @property {number} NON_ACK - Same as DATA + * @property {number} HIGH_PRIO - Not sure about this one could be LLD + * @property {number} LOW_LATENCY_DATA - Treated as normal data on the network, but are given higher priority internally + * @property {number} DATA_WITH_ACK - Data requesting an ack. The receiver must send an ack for this data unit! + * + * @type {Enum} + */ +const bufferType = new Enum({ + ACK: 0x01, + DATA: 0x02, + NON_ACK: 0x02, + HIGH_PRIO: 0x02, + LOW_LATENCY_DATA: 0x03, + DATA_WITH_ACK: 0x04, +}); + +/** + * Maps buffer types against characteristics for BLE + * + * @type {Enum} + */ +const bufferCharacteristicTranslationMap = new Enum({ + ACK: 'ACK_COMMAND', + DATA: 'SEND_NO_ACK', + NON_ACK: 'SEND_NO_ACK', + HIGH_PRIO: 'SEND_HIGH_PRIORITY', + LOW_LATENCY_DATA: 'SEND_NO_ACK', + DATA_WITH_ACK: 'SEND_WITH_ACK', +}); + +module.exports = { + bufferType, + bufferCharacteristicTranslationMap, +}; From 6fd0019dd88cff066433b06a46eee960b3b705e0 Mon Sep 17 00:00:00 2001 From: Bas Date: Mon, 4 Jun 2018 21:17:28 +0200 Subject: [PATCH 04/17] wip --- examples/doAFlip.js | 6 +- examples/toggleAutoTakeOff.js | 15 ++--- package.json | 2 + src/BufferEnums.js | 15 +++++ src/DroneCommand.js | 32 +++++++---- src/DroneConnection.js | 68 +++-------------------- src/connectors/BLEConnector.js | 31 ++++++++++- src/connectors/BaseConnector.js | 32 +++++++++++ src/connectors/WifiConnector.js | 97 +++++++++++++++++++++++++++++---- src/util/reflection.js | 20 ++++++- yarn.lock | 8 +++ 11 files changed, 230 insertions(+), 96 deletions(-) create mode 100644 src/connectors/BaseConnector.js diff --git a/examples/doAFlip.js b/examples/doAFlip.js index 842a76ed..5fde21de 100644 --- a/examples/doAFlip.js +++ b/examples/doAFlip.js @@ -1,11 +1,13 @@ -const {DroneConnection, CommandParser} = require('../src'); +const {DroneConnection, CommandParser, BLEConnector} = require('../src'); +const connector = new BLEConnector(); const parser = new CommandParser(); -const drone = new DroneConnection(); +const drone = new DroneConnection(connector); const takeoff = parser.getCommand('minidrone', 'Piloting', 'TakeOff'); const landing = parser.getCommand('minidrone', 'Piloting', 'Landing'); const backFlip = parser.getCommand('minidrone', 'Animations', 'Flip', {direction: 'back'}); +connector.connect(); drone.on('connected', () => { // Makes the code a bit clearer diff --git a/examples/toggleAutoTakeOff.js b/examples/toggleAutoTakeOff.js index d49b0ffd..4d7cd1d9 100644 --- a/examples/toggleAutoTakeOff.js +++ b/examples/toggleAutoTakeOff.js @@ -18,22 +18,19 @@ function sleep(ms) { drone.on('connected', async () => { await sleep(200); - drone.runCommand(allState); - - await sleep(1000); + await drone.runCommand(allState); await drone.runCommand(autoTakeOffOn); - Logger.debug('Command got ACK\'d'); await sleep(2000); - await drone.runCommand(autoTakeOffOn); - Logger.debug('Command got ACK\'d'); + await drone.runCommand(autoTakeOffOff); - await sleep(2000); + Logger.debug('values: '); - await drone.runCommand(autoTakeOffOff); - Logger.debug('Command got ACK\'d'); + for (const command of Object.values(drone._sensorStore)) { + Logger.debug(command.toString(true)); + } process.exit(); }); diff --git a/package.json b/package.json index 385ba4e6..b1d001fb 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,9 @@ "dependencies": { "arsdk-xml": "1.0.0", "case": "^1.5.4", + "dgram": "^1.0.1", "events": "^3.0.0", + "net": "^1.0.2", "noble": "git://github.com/jacobrosenthal/noble.git#highsierra", "node-gyp": "^3.6.2", "resolve": "^1.6.0", diff --git a/src/BufferEnums.js b/src/BufferEnums.js index d8f75361..ee066570 100644 --- a/src/BufferEnums.js +++ b/src/BufferEnums.js @@ -35,7 +35,22 @@ const bufferCharacteristicTranslationMap = new Enum({ DATA_WITH_ACK: 'SEND_WITH_ACK', }); +const bufferIds = new Enum({ + PING: 0, // pings from device + PONG: 1, // respond to pings + SEND_NO_ACK: 10, + SEND_WITH_ACK: 11, + SEND_HIGH_PRIORITY: 12, // emergency + VIDEO_ACK: 13, // ack for video + ACK_DRONE_DATA: 127, // drone data that needs an ack + ACK_COMMAND: 127, + NO_ACK_DRONE_DATA: 126, // data from drone (including battery and others), no ack + VIDEO_DATA: 125, // video data + ACK_FROM_SEND_WITH_ACK: 139, // 128 + buffer id for 'SEND_WITH_ACK' is 139 +}); + module.exports = { bufferType, bufferCharacteristicTranslationMap, + bufferIds, }; diff --git a/src/DroneCommand.js b/src/DroneCommand.js index fef0d65d..54191d7f 100644 --- a/src/DroneCommand.js +++ b/src/DroneCommand.js @@ -1,7 +1,7 @@ const DroneCommandArgument = require('./DroneCommandArgument'); const Enum = require('./util/Enum'); const { characteristicSendUuids } = require('./CharacteristicEnums'); -const { bufferType, bufferCharacteristicTranslationMap } = require('./BufferEnums'); +const { bufferType, bufferCharacteristicTranslationMap, bufferIds } = require('./BufferEnums'); /** * Drone command @@ -141,14 +141,20 @@ class DroneCommand { return this._deprecated; } + /** + * Get the send characteristic + * @returns {string} - send characteristic + */ + get sendCharacteristic() { + return bufferCharacteristicTranslationMap[this.bufferType] || 'SEND_WITH_ACK'; + } + /** * Get the send characteristic uuid based on the buffer type * @returns {string} - uuid as a string */ get sendCharacteristicUuid() { - const t = bufferCharacteristicTranslationMap[this.bufferType] || 'SEND_WITH_ACK'; - - return characteristicSendUuids[t]; + return characteristicSendUuids[this.sendCharacteristic]; } /** @@ -188,20 +194,18 @@ class DroneCommand { * @throws TypeError */ toBuffer() { - const bufferLength = 6 + this.arguments.reduce((acc, val) => val.getValueSize() + acc, 0); + let bufferOffset = 4; + + const bufferLength = bufferOffset + this.arguments.reduce((acc, val) => val.getValueSize() + acc, 0); const buffer = new Buffer(bufferLength); buffer.fill(0); - buffer.writeUInt16LE(this.bufferFlag, 0); - // Skip command counter (offset 1) because it's set in DroneConnection::runCommand - buffer.writeUInt16LE(this.projectId, 2); - buffer.writeUInt16LE(this.classId, 3); - buffer.writeUInt16LE(this.commandId, 4); // two bytes - - let bufferOffset = 6; + buffer.writeUInt8(this.projectId, 0); + buffer.writeUInt8(this.classId, 1); + buffer.writeUInt16LE(this.commandId, 2); // two bytes for (const arg of this.arguments) { const valueSize = arg.getValueSize(); @@ -285,6 +289,10 @@ class DroneCommand { return this._buffer.toUpperCase(); } + get bufferId() { + return bufferIds[this.sendCharacteristic]; + } + /** * Get the command buffer flag based on it's type * @returns {number} - Buffer flag diff --git a/src/DroneConnection.js b/src/DroneConnection.js index cf85c8e1..a2532548 100644 --- a/src/DroneConnection.js +++ b/src/DroneConnection.js @@ -1,8 +1,6 @@ const EventEmitter = require('events'); const Logger = require('winston'); -const Enum = require('./util/Enum'); const CommandParser = require('./CommandParser'); -const { characteristicSendUuids, characteristicReceiveUuids } = require('./CharacteristicEnums'); const { bufferType } = require('./BufferEnums'); /** @@ -26,13 +24,17 @@ class DroneConnection extends EventEmitter { this._commandCallback = {}; this._sensorStore = {}; - this._stepStore = {}; this.connector = connector; this.connector.on('disconnect', () => this.emit('disconnect')); this.connector.on('connected', () => this.emit('connected')); this.connector.on('data', data => this._handleIncoming(data)); + this.connector.on('incoming', command => { + // @todo move code + + this._sensorStore[command.getToken()] = command; + }); this.parser = new CommandParser(); @@ -56,21 +58,7 @@ class DroneConnection extends EventEmitter { * @async */ runCommand(command) { - const buffer = command.toBuffer(); - const packetId = this._getStep(command.bufferFlag); - - buffer.writeUIntLE(packetId, 1, 1); - - return new Promise(accept => { - Logger.debug(`SEND ${command.bufferType}[${packetId}]: `, command.toString()); - - if (command.shouldAck) { - this._commandCallback[packetId] = accept; - } else { - accept(); - } - this.connector.write(buffer, command.sendCharacteristicUuid); - }); + return this.connector.sendCommand(command); } /** @@ -80,11 +68,10 @@ class DroneConnection extends EventEmitter { * @private */ _handleIncoming(buffer) { - const characteristic = bufferType.findForValue(buffer.readUInt8(0)); + const type = bufferType.findForValue(buffer.readUInt8(0)); - Logger.debug(buffer); - if (characteristic !== 'ACK') { + if (type !== 'ACK') { this._updateSensors(buffer); } else { // @todo figure out why two ACK's in a row are received @@ -124,9 +111,7 @@ class DroneConnection extends EventEmitter { Logger.debug(`RECV ${command.bufferType}:`, command.toString()); if (command.shouldAck) { - const packetId = buffer.readUInt8(1); - - this.ack(packetId); + // @todo ack } /** @@ -181,41 +166,6 @@ class DroneConnection extends EventEmitter { return command; } - - /** - * used to count the drone command steps - * @param {string} id - Step store id - * @returns {number} - step number - * @todo steps should be grouped on bufferType (see bufferType enum) - */ - _getStep(id) { - if (typeof this._stepStore[id] === 'undefined') { - this._stepStore[id] = 0; - } - - const out = this._stepStore[id]; - - this._stepStore[id]++; - this._stepStore[id] &= 0xFF; - - return out; - } - - /** - * Acknowledge a packet - * @param {number} packetId - Id of the packet to ack - */ - ack(packetId) { - Logger.debug('SEND ACK: packet id ' + packetId); - - const buffer = new Buffer(3); - - buffer.writeUIntLE(bufferType.ACK, 0, 1); - buffer.writeUIntLE(this._getStep(bufferType.ACK), 1, 1); - buffer.writeUIntLE(packetId, 2, 1); - - this.connector.write(buffer, characteristicSendUuids.ACK_COMMAND); - } } module.exports = DroneConnection; diff --git a/src/connectors/BLEConnector.js b/src/connectors/BLEConnector.js index 773d8002..fb5aa4f9 100644 --- a/src/connectors/BLEConnector.js +++ b/src/connectors/BLEConnector.js @@ -1,5 +1,5 @@ const noble = require('noble'); -const EventEmitter = require('events'); +const BaseConnector = require('./BaseConnector'); const Logger = require('winston'); const Enum = require('../util/Enum'); const { characteristicUuids, characteristicReceiveUuids } = require('../CharacteristicEnums'); @@ -41,8 +41,8 @@ const serviceUuids = new Enum({ '1801': 'unknown', }); -class BLEConnector extends EventEmitter { - constructor (droneFilter = '') { +class BLEConnector extends BaseConnector { + constructor(droneFilter = '') { super(); this.droneFilter = droneFilter; @@ -219,6 +219,31 @@ class BLEConnector extends EventEmitter { get connected() { return this.characteristics.length > 0; } + + sendCommand(command) { + const buffer = Buffer.concat([new Buffer(2), command.toBuffer()]); + const packetId = this._getStep(command.bufferFlag); + + buffer.writeUInt16LE(command.bufferFlag, 0); + buffer.writeUInt8(packetId, 1); + + return new Promise(accept => { + Logger.debug(`SEND ${command.bufferType}[${packetId}]: `, command.toString()); + + if (command.shouldAck) { + // @todo ack + // this._commandCallback[packetId] = accept; + setTimeout(accept, 100); + } else { + accept(); + } + this.write(buffer, command.sendCharacteristicUuid); + }); + } + + ack() { + + } } module.exports = BLEConnector; diff --git a/src/connectors/BaseConnector.js b/src/connectors/BaseConnector.js new file mode 100644 index 00000000..89e3d589 --- /dev/null +++ b/src/connectors/BaseConnector.js @@ -0,0 +1,32 @@ +const EventEmitter = require('events'); +const CommandParser = require('../CommandParser'); + +class BaseConnector extends EventEmitter { + constructor() { + super(); + + this._stepStore = {}; + this.parser = new CommandParser(); + this._commandCallback = {}; + } + + /** + * used to count the drone command steps + * @param {string} id - Step store id + * @returns {number} - step number + */ + _getStep(id) { + if (typeof this._stepStore[id] === 'undefined') { + this._stepStore[id] = 0; + } + + const out = this._stepStore[id]; + + this._stepStore[id]++; + this._stepStore[id] &= 0xFF; + + return out; + } +} + +module.exports = BaseConnector; diff --git a/src/connectors/WifiConnector.js b/src/connectors/WifiConnector.js index 594c13a6..ae0ac3de 100644 --- a/src/connectors/WifiConnector.js +++ b/src/connectors/WifiConnector.js @@ -1,11 +1,12 @@ -const EventEmitter = require('events'); +const BaseConnector = require('./BaseConnector'); const Logger = require('winston'); const dgram = require('dgram'); const net = require('net'); const ARDiscoveryError = require('../ARDiscoveryError'); const mdns = require('mdns'); +const { bufferType } = require('../BufferEnums'); -class WifiConnector extends EventEmitter { +class WifiConnector extends BaseConnector { constructor(droneFilter = '', deviceId = '') { super(); @@ -51,14 +52,10 @@ class WifiConnector extends EventEmitter { } _handshake(service) { - Logger.info('Doing Wifi handshake'); + Logger.info(`Doing Wifi handshake with ${service.addresses[0]} [${service.addresses.join(', ')}]`); this.server = dgram.createSocket('udp4'); - this.server.on('data', msg => { - Logger.debug('got data from server'); - this.emit(msg.msg) - }); this.server.on('close', () => this.disconnect()); this.server.on('error', (err) => { this.disconnect(); @@ -66,6 +63,12 @@ class WifiConnector extends EventEmitter { throw err; }); + this.server.on('message', (msg, info) => { + Logger.debug(`Got data from server ${info.address}:${info.port} (${info.size} bytes)`); + + this._handleIncoming(msg); + }); + this.server.on('listening', () => { const address = this.server.address(); @@ -103,8 +106,15 @@ class WifiConnector extends EventEmitter { this.ip = service.addresses[0]; this.port = data.c2d_port; + this.client = dgram.createSocket('udp4'); + this.client.on('error', err => { + this.disconnect(); + + throw err; + }); + this.emit('connected'); }); }); @@ -112,14 +122,14 @@ class WifiConnector extends EventEmitter { this.server.bind(0); // random utp port } - write(buffer, characteristic) { + write(buffer) { return new Promise((accept, reject) => { - this.client.send(buffer, this.port, this.ip, err => { + this.client.send(buffer, 0, buffer.length, this.port, this.ip, err => { if (err) { reject(err); } - accept(); + accept(buffer.length); }); }); } @@ -139,6 +149,73 @@ class WifiConnector extends EventEmitter { get connected() { return this.server && this.client; } + + sendCommand(command) { + const commandBuffer = command.toBuffer(); + const buffer = Buffer.concat([new Buffer(7), commandBuffer]); + const bufferId = command.bufferId; + const packetId = this._getStep(bufferId); + + buffer.writeUInt8(command.bufferFlag, 0); // data type + buffer.writeUInt8(bufferId, 1); // buffer id + buffer.writeUInt8(packetId, 2); // sequence number + buffer.writeUInt32LE(commandBuffer.length + 7, 3); // frame size + + return new Promise(accept => { + Logger.debug(`SEND ${command.bufferType}[${packetId}]: `, command.toString()); + + if (command.shouldAck) { + if (!this._commandCallback[bufferId]) { + this._commandCallback[bufferId] = {}; + } + + this._commandCallback[bufferId][packetId] = accept; + } else { + accept(); + } + this.write(buffer, command.sendCharacteristicUuid); + }); + } + + _handleIncoming(buffer) { + const type = bufferType.findForValue(buffer.readUInt8(0)); + + switch (type) { + case 'ACK': + const bufferId = buffer.readUInt8(1) - 128; + const packetId = buffer.readUInt8(7); + + const callback = (this._commandCallback[bufferId] || {})[packetId]; + + if (typeof callback === 'function') { + callback(); + } + + break; + case 'DATA_WITH_ACK': + const ackBuffer = Buffer.alloc(8); + + ackBuffer.writeUInt8(bufferType.ACK, 0); + ackBuffer.writeUInt8(buffer.readUInt8(1) + 128, 1); + ackBuffer.writeUInt8(this._getStep(bufferType.ACK), 2); + ackBuffer.writeUInt32LE(8, 3); // frame size, always 8 for an ACK + ackBuffer.writeUInt8(buffer.readUInt8(2), 7); + + Logger.debug(`SEND ACK: buffer ${buffer.readUInt8(1)}, step ${buffer.readUInt8(2)}`); + this.write(ackBuffer); + case 'DATA': + case 'LOW_LATENCY_DATA': + try { + const command = this.parser.parseBuffer(buffer.slice(7)); + + Logger.debug(command.toString(true)); + + this.emit('incoming', command); + } catch (e) { + Logger.error(e); + } + } + } } module.exports = WifiConnector; diff --git a/src/util/reflection.js b/src/util/reflection.js index a24d736e..c5363ce4 100644 --- a/src/util/reflection.js +++ b/src/util/reflection.js @@ -4,8 +4,26 @@ * @private * @returns {string} - Value type name */ -module.exports.getTypeName = function getTypeName(value) { +function getTypeName(value) { value = typeof value === 'function' ? value : value.constructor; return value.name; +} + +function promiseify(func) { + return function() { + return new Promise((accept, reject) => { + try { + func(...arguments, accept); + } catch (e) { + reject(e); + } + }); + }; +} + + +module.exports = { + getTypeName, + promiseify, }; diff --git a/yarn.lock b/yarn.lock index 731a0ea6..e837c896 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1109,6 +1109,10 @@ detect-libc@^1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" +dgram@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/dgram/-/dgram-1.0.1.tgz#37f3b200f8033a5ff759303089c81ce361b651c3" + doctrine@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d" @@ -2332,6 +2336,10 @@ natural-compare@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" +net@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/net/-/net-1.0.2.tgz#d1757ec9a7fb2371d83cf4755ce3e27e10829388" + "noble@git://github.com/jacobrosenthal/noble.git#highsierra": version "1.8.1" resolved "git://github.com/jacobrosenthal/noble.git#15179890f7dd39ed8b40c0c5b11a5538498d03fd" From eea48397484fdc24b944f67ace36a343b4289a94 Mon Sep 17 00:00:00 2001 From: Bas Date: Tue, 5 Jun 2018 12:39:00 +0200 Subject: [PATCH 05/17] Fix string parsing --- src/CommandParser.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CommandParser.js b/src/CommandParser.js index 3df4096e..5dfae615 100644 --- a/src/CommandParser.js +++ b/src/CommandParser.js @@ -193,7 +193,7 @@ class CommandParser { let c = ''; // Last character for (valueSize = 0; valueSize < buffer.length && c !== '\0'; valueSize++) { - c = String.fromCharCode(buffer[bufferOffset]); + c = String.fromCharCode(buffer[bufferOffset + valueSize]); value += c; } From ae8e9258b34660922f0ecbd2dacc664f9231dbd2 Mon Sep 17 00:00:00 2001 From: Bas Date: Fri, 8 Jun 2018 14:39:28 +0200 Subject: [PATCH 06/17] Wifi works like a charm --- .eslintrc.json | 3 + examples/toggleAutoTakeOff.js | 2 +- src/DroneConnection.js | 2 +- src/connectors/BaseConnector.js | 39 ++++++++++ src/connectors/WifiConnector.js | 126 ++++++++++++++++---------------- src/util/reflection.js | 4 +- 6 files changed, 110 insertions(+), 66 deletions(-) diff --git a/.eslintrc.json b/.eslintrc.json index 9f4542fa..ddf529c7 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -14,6 +14,9 @@ "VERSION": false, "LICENSE": false }, + "parserOptions": { + "ecmaVersion": 2017 + }, "rules": { "comma-dangle": [1,"always-multiline"], "no-cond-assign": [1,"always"], diff --git a/examples/toggleAutoTakeOff.js b/examples/toggleAutoTakeOff.js index 4d7cd1d9..2e4cbef7 100644 --- a/examples/toggleAutoTakeOff.js +++ b/examples/toggleAutoTakeOff.js @@ -32,5 +32,5 @@ drone.on('connected', async () => { Logger.debug(command.toString(true)); } - process.exit(); + // process.exit(); }); diff --git a/src/DroneConnection.js b/src/DroneConnection.js index a2532548..95194ade 100644 --- a/src/DroneConnection.js +++ b/src/DroneConnection.js @@ -29,7 +29,7 @@ class DroneConnection extends EventEmitter { this.connector.on('disconnect', () => this.emit('disconnect')); this.connector.on('connected', () => this.emit('connected')); - this.connector.on('data', data => this._handleIncoming(data)); + this.connector.on('incoming', command => { // @todo move code diff --git a/src/connectors/BaseConnector.js b/src/connectors/BaseConnector.js index 89e3d589..0d3e6a7f 100644 --- a/src/connectors/BaseConnector.js +++ b/src/connectors/BaseConnector.js @@ -1,5 +1,6 @@ const EventEmitter = require('events'); const CommandParser = require('../CommandParser'); +const Logger = require('winston'); class BaseConnector extends EventEmitter { constructor() { @@ -27,6 +28,44 @@ class BaseConnector extends EventEmitter { return out; } + + /** + * Set the ack callback (if needed) for a command. + * Should be called directly after sending it. It will log the sending of the command. + * @param {DroneCommand} command - Sent command + * @param {number} packetId - Packet id + * @returns {Promise} - Resolves when the command has been acknowledged (if needed) + * @protected + * @async + */ + _setAckCallback(command, packetId) { + const bufferId = command.bufferId; + + return new Promise((_accept, reject) => { + if (command.shouldAck) { + if (!this._commandCallback[bufferId]) { + this._commandCallback[bufferId] = {}; + } + + // For if the command times out + const timeout = setTimeout(reject, 10 * 1000, new Error('Command timed out after 10 seconds')); + + const accept = () => { + clearTimeout(timeout); + + _accept(...arguments); + }; + + this._commandCallback[bufferId][packetId] = { accept, reject }; + } + + Logger.debug(`SENT ${command.bufferType}[${packetId}]: `, command.toString()); + + if (!command.shouldAck) { + _accept(); + } + }); + } } module.exports = BaseConnector; diff --git a/src/connectors/WifiConnector.js b/src/connectors/WifiConnector.js index ae0ac3de..5467f08c 100644 --- a/src/connectors/WifiConnector.js +++ b/src/connectors/WifiConnector.js @@ -5,6 +5,7 @@ const net = require('net'); const ARDiscoveryError = require('../ARDiscoveryError'); const mdns = require('mdns'); const { bufferType } = require('../BufferEnums'); +const { promisify } = require('../util/reflection'); class WifiConnector extends BaseConnector { constructor(droneFilter = '', deviceId = '') { @@ -27,20 +28,25 @@ class WifiConnector extends BaseConnector { this.browser = mdns.createBrowser(mdns.udp('_arsdk-090b'), { resolverSequence }); // @todo browse all - this.browser.on('serviceUp', service => this._onMdnsServiceDiscovery(service)); + return new Promise(accept => { + this.browser.on('serviceUp', service => this._onMdnsServiceDiscovery(service).then(c => !c || accept())); - this.browser.start(); + this.browser.start(); + }); } + + return new Promise(accept => accept()); } - _onMdnsServiceDiscovery(service) { + async _onMdnsServiceDiscovery(service) { if (!service.fullname.includes('_arsdk-')) { - return; + Logger.debug(`Skipping mdns service ${service.fullname}`); + return false; } if (this.droneFilter && service.name !== this.droneFilter) { Logger.debug(`Found drone ${service.name} but it didn't match the drone filter`); - return; + return false; } this.browser.stop(); @@ -48,10 +54,12 @@ class WifiConnector extends BaseConnector { Logger.debug(`Found drone ${service.name}`); - this._handshake(service); + await this._handshake(service); + + return true; } - _handshake(service) { + async _handshake(service) { Logger.info(`Doing Wifi handshake with ${service.addresses[0]} [${service.addresses.join(', ')}]`); this.server = dgram.createSocket('udp4'); @@ -63,63 +71,61 @@ class WifiConnector extends BaseConnector { throw err; }); - this.server.on('message', (msg, info) => { - Logger.debug(`Got data from server ${info.address}:${info.port} (${info.size} bytes)`); + this.server.on('message', msg => this._handleIncoming(msg)); - this._handleIncoming(msg); - }); + this.server.bind(0); // random utp port - this.server.on('listening', () => { - const address = this.server.address(); + await promisify(this.server.once.bind(this.server))('listening'); - Logger.debug(`Server listening ${address.address}:${address.port}`); + const address = this.server.address(); - const handshakeClient = new net.Socket(); + Logger.debug(`Server listening ${address.address}:${address.port}`); - handshakeClient.connect(service.port, service.addresses[0], () => { - const config = { - 'd2c_port': this.server.address().port, - 'controller_type': 'minidrone-js', - 'controller_name': 'me.shodan.minidrone-js', - // 'device_id': this.deviceId, // @ todo drone returns errors - }; + const handshakeClient = new net.Socket(); - Logger.debug('Negotiating connection:', config); + handshakeClient.connect(service.port, service.addresses[0], () => { + const config = { + 'd2c_port': this.server.address().port, + 'controller_type': 'minidrone-js', + 'controller_name': 'me.shodan.minidrone-js', + // 'device_id': this.deviceId, // @ todo drone returns errors + }; - handshakeClient.write(JSON.stringify(config)); - }); + Logger.debug('Negotiating connection:', config); - handshakeClient.on('data', data => { - data = data.toString(); - data = data.replace('\0', ''); // Remove trailing nullbyte - data = JSON.parse(data); + handshakeClient.write(JSON.stringify(config)); + }); - Logger.debug('Got drone response: ', data); + let data = await promisify(handshakeClient.once.bind(handshakeClient))('data'); - if (data.status !== 0) { - const error = ARDiscoveryError.findForValue(data.status); + data = data.toString(); + data = data.replace('\0', ''); // Remove trailing nullbyte + data = JSON.parse(data); - throw new Error(error); - } + Logger.debug('Got drone response: ', data); - handshakeClient.destroy(); + if (data.status !== 0) { + const error = ARDiscoveryError.findForValue(data.status); - this.ip = service.addresses[0]; - this.port = data.c2d_port; + throw new Error(error); + } - this.client = dgram.createSocket('udp4'); + handshakeClient.destroy(); - this.client.on('error', err => { - this.disconnect(); + this.ip = service.addresses[0]; + this.port = data.c2d_port; - throw err; - }); + this.client = dgram.createSocket('udp4'); - this.emit('connected'); - }); + this.client.on('error', err => { + this.disconnect(); + + throw err; }); - this.server.bind(0); // random utp port + Logger.debug(`Stream available at ${this.rtspStreamUri}`); + + this.emit('connected'); } write(buffer) { @@ -161,20 +167,9 @@ class WifiConnector extends BaseConnector { buffer.writeUInt8(packetId, 2); // sequence number buffer.writeUInt32LE(commandBuffer.length + 7, 3); // frame size - return new Promise(accept => { - Logger.debug(`SEND ${command.bufferType}[${packetId}]: `, command.toString()); - - if (command.shouldAck) { - if (!this._commandCallback[bufferId]) { - this._commandCallback[bufferId] = {}; - } + this.write(buffer, command.sendCharacteristicUuid); - this._commandCallback[bufferId][packetId] = accept; - } else { - accept(); - } - this.write(buffer, command.sendCharacteristicUuid); - }); + return this._setAckCallback(command, packetId); } _handleIncoming(buffer) { @@ -187,8 +182,8 @@ class WifiConnector extends BaseConnector { const callback = (this._commandCallback[bufferId] || {})[packetId]; - if (typeof callback === 'function') { - callback(); + if (typeof callback.accept === 'function') { + callback.accept(); } break; @@ -201,12 +196,15 @@ class WifiConnector extends BaseConnector { ackBuffer.writeUInt32LE(8, 3); // frame size, always 8 for an ACK ackBuffer.writeUInt8(buffer.readUInt8(2), 7); - Logger.debug(`SEND ACK: buffer ${buffer.readUInt8(1)}, step ${buffer.readUInt8(2)}`); this.write(ackBuffer); case 'DATA': case 'LOW_LATENCY_DATA': + const frame = buffer.slice(7); + + this.emit('data', frame); + try { - const command = this.parser.parseBuffer(buffer.slice(7)); + const command = this.parser.parseBuffer(frame); Logger.debug(command.toString(true)); @@ -216,6 +214,10 @@ class WifiConnector extends BaseConnector { } } } + + get rtspStreamUri() { + return `rtsp://${this.ip}/media/stream2`; + } } module.exports = WifiConnector; diff --git a/src/util/reflection.js b/src/util/reflection.js index c5363ce4..7361c210 100644 --- a/src/util/reflection.js +++ b/src/util/reflection.js @@ -10,7 +10,7 @@ function getTypeName(value) { return value.name; } -function promiseify(func) { +function promisify(func) { return function() { return new Promise((accept, reject) => { try { @@ -25,5 +25,5 @@ function promiseify(func) { module.exports = { getTypeName, - promiseify, + promisify, }; From cc11aeaf89b6d3f0453ca50a25885ad7b36bcfd6 Mon Sep 17 00:00:00 2001 From: Bas Date: Fri, 8 Jun 2018 17:38:55 +0200 Subject: [PATCH 07/17] feels good --- src/connectors/BLEConnector.js | 4 +- src/connectors/BaseConnector.js | 85 +++++++++++++++++++- src/connectors/WifiConnector.js | 138 +++++++++++++++++++++++--------- 3 files changed, 188 insertions(+), 39 deletions(-) diff --git a/src/connectors/BLEConnector.js b/src/connectors/BLEConnector.js index fb5aa4f9..87a094ba 100644 --- a/src/connectors/BLEConnector.js +++ b/src/connectors/BLEConnector.js @@ -164,7 +164,7 @@ class BLEConnector extends BaseConnector { * Drone disconnected event * Fired when the bluetooth connection has been disconnected * - * @event DroneCommand#disconnected + * @event BaseConnector#disconnected */ noble.on('disconnect', () => this.disconnect()); @@ -173,7 +173,7 @@ class BLEConnector extends BaseConnector { * Drone connected event * You can control the drone once this event has been triggered. * - * @event DroneCommand#connected + * @event BaseConnector#connected */ this.emit('connected'); }, 200); diff --git a/src/connectors/BaseConnector.js b/src/connectors/BaseConnector.js index 0d3e6a7f..08a9501c 100644 --- a/src/connectors/BaseConnector.js +++ b/src/connectors/BaseConnector.js @@ -2,6 +2,16 @@ const EventEmitter = require('events'); const CommandParser = require('../CommandParser'); const Logger = require('winston'); +/** + * Base drone connector + * + * @fires BaseConnector#connected + * @fires BaseConnector#disconnected + * @fires BaseConnector#sensor: + * @fires BaseConnector#incoming + * + * @abstract + */ class BaseConnector extends EventEmitter { constructor() { super(); @@ -9,6 +19,10 @@ class BaseConnector extends EventEmitter { this._stepStore = {}; this.parser = new CommandParser(); this._commandCallback = {}; + this._sensorStore = {}; + + this.on('incoming', command => this.setSensor(command)); + this.on('incoming', command => Logger.debug(`RECV ${command.bufferType}:`, command.toString())); } /** @@ -35,7 +49,6 @@ class BaseConnector extends EventEmitter { * @param {DroneCommand} command - Sent command * @param {number} packetId - Packet id * @returns {Promise} - Resolves when the command has been acknowledged (if needed) - * @protected * @async */ _setAckCallback(command, packetId) { @@ -66,6 +79,76 @@ class BaseConnector extends EventEmitter { } }); } + + /** + * Get the most recent sensor reading + * + * @param {string} project - Project name + * @param {string} class_ - Class name + * @param {string} command - Command name + * @returns {DroneCommand|undefined} - {@link DroneCommand} instance or {@link undefined} if no sensor reading could be found + * @see {@link https://github.com/Parrot-Developers/arsdk-xml/blob/master/xml/} + */ + getSensor(project, class_, command) { + const token = [project, class_, command].join('-'); + + return this.getSensorFromToken(token); + } + + /** + * Get the most recent sensor reading using the sensor token + * + * @param {string} token - Command token + * @returns {DroneCommand|undefined} - {@link DroneCommand} instance or {@link undefined} if no sensor reading could be found + * @see {@link https://github.com/Parrot-Developers/arsdk-xml/blob/master/xml/} + * @see {@link DroneCommand.getToken} + */ + getSensorFromToken(token) { + let command = this._sensorStore[token]; + + if (command) { + command = command.copy(); + } + + return command; + } + + setSensor(command) { + this._sensorStore[command.getToken()] = command; + + /** + * Fires when a new sensor reading has been received + * + * @event DroneConnection#sensor: + * @type {DroneCommand} - The sensor reading + * @example + * connection.on('sensor:minidrone-UsbAccessoryState-GunState', function(sensor) { + * if (sensor.state.value === sensor.state.enum.READY) { + * console.log('The gun is ready to fire!'); + * } + * }); + */ + this.emit('sensor:' + token, command); + this.emit('sensor:*', command); + } + + /** + * @returns {boolean} If the drone is connected + * @abstract + */ + get connected() { + return false; + } + + /** + * Connect to the drone + * @returns {Promise} - Resolves when the connection has been established + * @async + * @abstract + */ + connect() { + throw new Error('Abstract class'); + } } module.exports = BaseConnector; diff --git a/src/connectors/WifiConnector.js b/src/connectors/WifiConnector.js index 5467f08c..d3e0479f 100644 --- a/src/connectors/WifiConnector.js +++ b/src/connectors/WifiConnector.js @@ -7,14 +7,27 @@ const mdns = require('mdns'); const { bufferType } = require('../BufferEnums'); const { promisify } = require('../util/reflection'); +/** + * Wifi connector for the drone + * + * Used for connecting to drones using Wifi + */ class WifiConnector extends BaseConnector { + /** + * Create a Wifi connector + * @param {string?} droneFilter - Name of the drone + * @param {string?} deviceId - Persistent device id for reconnection + */ constructor(droneFilter = '', deviceId = '') { super(); this.droneFilter = droneFilter; - this.deviceId = deviceId || Math.random().toString(36); // Should be persistant between connections + this.deviceId = deviceId || ('000' + Math.round(Math.random() * 1000).toString()).slice(-4); // Should be persistant between connections } + /** + * @inheritDoc + */ connect() { if (!this.browser && !this.server && !this.client) { Logger.debug('Starting mDNS browser'); @@ -38,6 +51,13 @@ class WifiConnector extends BaseConnector { return new Promise(accept => accept()); } + /** + * @inheritDoc + */ + get connected() { + return this.browser && this.server && this.client; + } + async _onMdnsServiceDiscovery(service) { if (!service.fullname.includes('_arsdk-')) { Logger.debug(`Skipping mdns service ${service.fullname}`); @@ -54,14 +74,65 @@ class WifiConnector extends BaseConnector { Logger.debug(`Found drone ${service.name}`); - await this._handshake(service); + try { + await this._connect(service); + } catch (e) { + this.disconnect(); + + throw e; + } return true; } - async _handshake(service) { + async _connect(service) { Logger.info(`Doing Wifi handshake with ${service.addresses[0]} [${service.addresses.join(', ')}]`); + await this._startServer(); + + this.ip = service.addresses[0]; + + let data = await this._sendHandshake(this.ip, service.port); + + data = data.toString(); + data = data.replace('\0', ''); // Remove trailing nullbyte + data = JSON.parse(data); + + Logger.debug('Got drone response: ', data); + + if (data.status !== 0) { + const error = ARDiscoveryError.findForValue(data.status); + + throw new Error(error); + } + + this.port = data.c2d_port; + + this.client = dgram.createSocket('udp4'); + + this.client.on('error', err => { + this.disconnect(); + + throw err; + }); + + Logger.debug(`Stream available at ${this.rtspStreamUri}`); + + /** + * Drone connected event + * You can control the drone once this event has been triggered. + * + * @event BaseConnector#connected + */ + this.emit('connected'); + } + + async _startServer() { + if (this.server) { + Logger.warn('Found existing running server, closing it'); + this.server.close(); + } + this.server = dgram.createSocket('udp4'); this.server.on('close', () => this.disconnect()); @@ -76,14 +147,16 @@ class WifiConnector extends BaseConnector { this.server.bind(0); // random utp port await promisify(this.server.once.bind(this.server))('listening'); + } + async _sendHandshake(ip, port) { const address = this.server.address(); Logger.debug(`Server listening ${address.address}:${address.port}`); const handshakeClient = new net.Socket(); - handshakeClient.connect(service.port, service.addresses[0], () => { + handshakeClient.connect(port, ip, () => { const config = { 'd2c_port': this.server.address().port, 'controller_type': 'minidrone-js', @@ -96,38 +169,19 @@ class WifiConnector extends BaseConnector { handshakeClient.write(JSON.stringify(config)); }); - let data = await promisify(handshakeClient.once.bind(handshakeClient))('data'); - - data = data.toString(); - data = data.replace('\0', ''); // Remove trailing nullbyte - data = JSON.parse(data); - - Logger.debug('Got drone response: ', data); - - if (data.status !== 0) { - const error = ARDiscoveryError.findForValue(data.status); - - throw new Error(error); - } + const data = await promisify(handshakeClient.once.bind(handshakeClient))('data'); handshakeClient.destroy(); - this.ip = service.addresses[0]; - this.port = data.c2d_port; - - this.client = dgram.createSocket('udp4'); - - this.client.on('error', err => { - this.disconnect(); - - throw err; - }); - - Logger.debug(`Stream available at ${this.rtspStreamUri}`); - - this.emit('connected'); + return data; } + /** + * Write raw buffer to the drone + * @param {Buffer} buffer + * @returns {number} - Resolves with the number of bytes sent + * @async + */ write(buffer) { return new Promise((accept, reject) => { this.client.send(buffer, 0, buffer.length, this.port, this.ip, err => { @@ -140,8 +194,13 @@ class WifiConnector extends BaseConnector { }); } + /** + * Disconnect from the drone + * @emits BaseConnector#disconnected + * @returns {void} + */ disconnect() { - Logger.info('Disconnected'); + this.server.close(); delete this.browser; delete this.server; @@ -149,13 +208,16 @@ class WifiConnector extends BaseConnector { delete this.port; delete this.client; - this.emit('disconnected'); - } + Logger.info('Disconnected'); - get connected() { - return this.server && this.client; + this.emit('disconnected'); } + /** + * Send a command to the drone + * @param {DroneCommand} command - Command to send + * @returns {Promise} - Resolves when the command has been acknowledged or rejects if it times out + */ sendCommand(command) { const commandBuffer = command.toBuffer(); const buffer = Buffer.concat([new Buffer(7), commandBuffer]); @@ -215,6 +277,10 @@ class WifiConnector extends BaseConnector { } } + /** + * Returns an approximation of the rtsp stream uri. Sometimes it's the gateway not the drone itself oddly enough. + * @returns {string} - stream uri + */ get rtspStreamUri() { return `rtsp://${this.ip}/media/stream2`; } From cd2c068d6ce2b42ba28884b28e0863d20872cf42 Mon Sep 17 00:00:00 2001 From: Bas Date: Tue, 12 Jun 2018 16:47:44 +0200 Subject: [PATCH 08/17] wip --- examples/directFlight.js | 2 +- examples/doAFlip.js | 2 +- examples/package-lock.json | 5066 +++++++++++++++++++++++++++++++ examples/package.json | 9 +- examples/toggleAutoTakeOff.js | 20 +- examples/wifi/directFlight.js | 84 + package-lock.json | 62 +- src/connectors/BaseConnector.js | 22 +- src/connectors/WifiConnector.js | 14 +- 9 files changed, 5235 insertions(+), 46 deletions(-) create mode 100644 examples/package-lock.json create mode 100644 examples/wifi/directFlight.js diff --git a/examples/directFlight.js b/examples/directFlight.js index 648dbb17..40453a49 100644 --- a/examples/directFlight.js +++ b/examples/directFlight.js @@ -1,5 +1,5 @@ const dualShock = require('dualshock-controller'); -const {DroneConnection, CommandParser} = require('../src'); +const {DroneConnection, CommandParser} = require('minidrone-js'); const controller = dualShock({config: 'dualShock4-alternate-driver'}); const parser = new CommandParser(); diff --git a/examples/doAFlip.js b/examples/doAFlip.js index 5fde21de..dab5e0a9 100644 --- a/examples/doAFlip.js +++ b/examples/doAFlip.js @@ -1,4 +1,4 @@ -const {DroneConnection, CommandParser, BLEConnector} = require('../src'); +const {DroneConnection, CommandParser, BLEConnector} = require('minidrone-js'); const connector = new BLEConnector(); const parser = new CommandParser(); diff --git a/examples/package-lock.json b/examples/package-lock.json new file mode 100644 index 00000000..08944fb6 --- /dev/null +++ b/examples/package-lock.json @@ -0,0 +1,5066 @@ +{ + "name": "direct-flight", + "requires": true, + "lockfileVersion": 1, + "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==", + "optional": true + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + }, + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + }, + "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==", + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "async": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async/-/async-1.0.0.tgz", + "integrity": "sha1-+PwEyjoTeErenhZBr5hXjPvWR6k=" + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + }, + "bindings": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.3.0.tgz", + "integrity": "sha512-DpLh5EzMR2kzvX1KIlVC0VkC3iZtHKTgdtZ0a3pglBZdaQFjt5S9g9xd1lE+YvXyfd6mtCeRnrUfOLYiTMlNSw==" + }, + "bl": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.2.tgz", + "integrity": "sha512-e8tQYnZodmebYDWGH7KMRvtzKXaJHx3BbilrgZCfvyLUYdKpK1t5PSPmpkny/SgiTSCnjfLW7v5rlONXVFkQEA==", + "requires": { + "readable-stream": "^2.3.5", + "safe-buffer": "^5.1.1" + } + }, + "bluetooth-hci-socket": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/bluetooth-hci-socket/-/bluetooth-hci-socket-0.5.1.tgz", + "integrity": "sha1-774hUk/Bz10/rl1RNl1WHUq77Qs=", + "optional": true, + "requires": { + "debug": "^2.2.0", + "nan": "^2.0.5", + "usb": "^1.1.0" + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "buffer-alloc": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", + "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==", + "requires": { + "buffer-alloc-unsafe": "^1.1.0", + "buffer-fill": "^1.0.0" + } + }, + "buffer-alloc-unsafe": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz", + "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==" + }, + "buffer-fill": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", + "integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw=" + }, + "chownr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.0.1.tgz", + "integrity": "sha1-4qdQQqlVGQi+vSW4Uj1fl2nXkYE=" + }, + "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=" + }, + "colors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz", + "integrity": "sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs=" + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "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=" + }, + "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=" + }, + "cycle": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/cycle/-/cycle-1.0.3.tgz", + "integrity": "sha1-IegLK+hYD5i0aPN5QwZisEbDStI=" + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "optional": true, + "requires": { + "ms": "2.0.0" + } + }, + "decompress-response": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", + "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", + "requires": { + "mimic-response": "^1.0.0" + } + }, + "deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==" + }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=" + }, + "detect-libc": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", + "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=" + }, + "dualshock-controller": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/dualshock-controller/-/dualshock-controller-1.1.1.tgz", + "integrity": "sha1-ltiJTTq8ElKxx6WVR/ktoS0fb4E=", + "requires": { + "node-hid": "^0.5.0" + } + }, + "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==", + "requires": { + "once": "^1.4.0" + } + }, + "expand-template": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-1.1.1.tgz", + "integrity": "sha512-cebqLtV8KOZfw0UI8TEFWxtczxxC1jvyUvx6H4fyp1K1FN7A4Q+uggVUlOsI1K8AGU0rwOGqP8nCapdrw8CYQg==" + }, + "eyes": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/eyes/-/eyes-0.1.8.tgz", + "integrity": "sha1-Ys8SAjTGg3hdkCNIqADvPgzCC8A=" + }, + "fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, + "fs-minipass": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.5.tgz", + "integrity": "sha512-JhBl0skXjUPCFH7x6x61gQxrKyXsxB5gcgePLZCwfyCGGsTISMoIeObbrvVeP6Xmyaudw4TT43qV2Gz+iyd2oQ==", + "optional": true, + "requires": { + "minipass": "^2.2.1" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "optional": true + }, + "gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", + "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" + } + }, + "github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4=" + }, + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "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=" + }, + "iconv-lite": { + "version": "0.4.23", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", + "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", + "optional": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ignore-walk": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.1.tgz", + "integrity": "sha512-DTVlMx3IYPe0/JJcYP7Gxg7ttZZu3IInhuEhbchuqneY9wWe5Ojy2mXLBaQFUQmo0AW2r3qG7m1mg86js+gnlQ==", + "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=", + "optional": 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==" + }, + "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=", + "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=" + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" + }, + "mimic-response": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.0.tgz", + "integrity": "sha1-3z02Uqc/3ta5sLJBRub9BSNTRY4=" + }, + "minidrone-js": { + "version": "file:..", + "requires": { + "arsdk-xml": "1.0.0", + "case": "^1.5.4", + "dgram": "^1.0.1", + "events": "^3.0.0", + "net": "^1.0.2", + "noble": "git://github.com/jacobrosenthal/noble.git#highsierra", + "node-gyp": "^3.6.2", + "resolve": "^1.6.0", + "winston": "^2.4.0", + "xml2js": "^0.4.19" + }, + "dependencies": { + "@ava/babel-plugin-throws-helper": { + "version": "2.0.0", + "bundled": true + }, + "@ava/babel-preset-stage-4": { + "version": "1.1.0", + "bundled": true, + "requires": { + "babel-plugin-check-es2015-constants": "^6.8.0", + "babel-plugin-syntax-trailing-function-commas": "^6.20.0", + "babel-plugin-transform-async-to-generator": "^6.16.0", + "babel-plugin-transform-es2015-destructuring": "^6.19.0", + "babel-plugin-transform-es2015-function-name": "^6.9.0", + "babel-plugin-transform-es2015-modules-commonjs": "^6.18.0", + "babel-plugin-transform-es2015-parameters": "^6.21.0", + "babel-plugin-transform-es2015-spread": "^6.8.0", + "babel-plugin-transform-es2015-sticky-regex": "^6.8.0", + "babel-plugin-transform-es2015-unicode-regex": "^6.11.0", + "babel-plugin-transform-exponentiation-operator": "^6.8.0", + "package-hash": "^1.2.0" + }, + "dependencies": { + "md5-hex": { + "version": "1.3.0", + "bundled": true, + "requires": { + "md5-o-matic": "^0.1.1" + } + }, + "package-hash": { + "version": "1.2.0", + "bundled": true, + "requires": { + "md5-hex": "^1.3.0" + } + } + } + }, + "@ava/babel-preset-transform-test-files": { + "version": "3.0.0", + "bundled": true, + "requires": { + "@ava/babel-plugin-throws-helper": "^2.0.0", + "babel-plugin-espower": "^2.3.2" + } + }, + "@ava/write-file-atomic": { + "version": "2.2.0", + "bundled": true, + "requires": { + "graceful-fs": "^4.1.11", + "imurmurhash": "^0.1.4", + "slide": "^1.1.5" + } + }, + "@concordance/react": { + "version": "1.0.0", + "bundled": true, + "requires": { + "arrify": "^1.0.1" + } + }, + "@ladjs/time-require": { + "version": "0.1.4", + "bundled": true, + "requires": { + "chalk": "^0.4.0", + "date-time": "^0.1.1", + "pretty-ms": "^0.2.1", + "text-table": "^0.2.0" + }, + "dependencies": { + "ansi-styles": { + "version": "1.0.0", + "bundled": true + }, + "chalk": { + "version": "0.4.0", + "bundled": true, + "requires": { + "ansi-styles": "~1.0.0", + "has-color": "~0.1.0", + "strip-ansi": "~0.1.0" + } + }, + "pretty-ms": { + "version": "0.2.2", + "bundled": true, + "requires": { + "parse-ms": "^0.1.0" + } + }, + "strip-ansi": { + "version": "0.1.1", + "bundled": true + } + } + }, + "abbrev": { + "version": "1.1.1", + "bundled": true + }, + "acorn": { + "version": "5.5.3", + "bundled": true + }, + "acorn-jsx": { + "version": "3.0.1", + "bundled": true, + "requires": { + "acorn": "^3.0.4" + }, + "dependencies": { + "acorn": { + "version": "3.3.0", + "bundled": true + } + } + }, + "ajv": { + "version": "5.5.2", + "bundled": true, + "requires": { + "co": "^4.6.0", + "fast-deep-equal": "^1.0.0", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.3.0" + } + }, + "ajv-keywords": { + "version": "2.1.1", + "bundled": true + }, + "ansi-align": { + "version": "2.0.0", + "bundled": true, + "requires": { + "string-width": "^2.0.0" + } + }, + "ansi-escapes": { + "version": "3.1.0", + "bundled": true + }, + "ansi-regex": { + "version": "2.1.1", + "bundled": true + }, + "ansi-styles": { + "version": "3.2.1", + "bundled": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "anymatch": { + "version": "1.3.2", + "bundled": true, + "requires": { + "micromatch": "^2.1.5", + "normalize-path": "^2.0.0" + } + }, + "aproba": { + "version": "1.2.0", + "bundled": true + }, + "are-we-there-yet": { + "version": "1.1.5", + "bundled": true, + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "argparse": { + "version": "1.0.10", + "bundled": true, + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "arr-diff": { + "version": "2.0.0", + "bundled": true, + "requires": { + "arr-flatten": "^1.0.1" + } + }, + "arr-exclude": { + "version": "1.0.0", + "bundled": true + }, + "arr-flatten": { + "version": "1.1.0", + "bundled": true + }, + "array-differ": { + "version": "1.0.0", + "bundled": true + }, + "array-find-index": { + "version": "1.0.2", + "bundled": true + }, + "array-union": { + "version": "1.0.2", + "bundled": true, + "requires": { + "array-uniq": "^1.0.1" + } + }, + "array-uniq": { + "version": "1.0.3", + "bundled": true + }, + "array-unique": { + "version": "0.2.1", + "bundled": true + }, + "arrify": { + "version": "1.0.1", + "bundled": true + }, + "arsdk-xml": { + "version": "1.0.0", + "bundled": true + }, + "asn1": { + "version": "0.2.3", + "bundled": true + }, + "assert-plus": { + "version": "0.2.0", + "bundled": true + }, + "async": { + "version": "1.0.0", + "bundled": true + }, + "async-each": { + "version": "1.0.1", + "bundled": true + }, + "asynckit": { + "version": "0.4.0", + "bundled": true + }, + "auto-bind": { + "version": "1.2.0", + "bundled": true + }, + "ava": { + "version": "0.25.0", + "bundled": true, + "requires": { + "@ava/babel-preset-stage-4": "^1.1.0", + "@ava/babel-preset-transform-test-files": "^3.0.0", + "@ava/write-file-atomic": "^2.2.0", + "@concordance/react": "^1.0.0", + "@ladjs/time-require": "^0.1.4", + "ansi-escapes": "^3.0.0", + "ansi-styles": "^3.1.0", + "arr-flatten": "^1.0.1", + "array-union": "^1.0.1", + "array-uniq": "^1.0.2", + "arrify": "^1.0.0", + "auto-bind": "^1.1.0", + "ava-init": "^0.2.0", + "babel-core": "^6.17.0", + "babel-generator": "^6.26.0", + "babel-plugin-syntax-object-rest-spread": "^6.13.0", + "bluebird": "^3.0.0", + "caching-transform": "^1.0.0", + "chalk": "^2.0.1", + "chokidar": "^1.4.2", + "clean-stack": "^1.1.1", + "clean-yaml-object": "^0.1.0", + "cli-cursor": "^2.1.0", + "cli-spinners": "^1.0.0", + "cli-truncate": "^1.0.0", + "co-with-promise": "^4.6.0", + "code-excerpt": "^2.1.1", + "common-path-prefix": "^1.0.0", + "concordance": "^3.0.0", + "convert-source-map": "^1.5.1", + "core-assert": "^0.2.0", + "currently-unhandled": "^0.4.1", + "debug": "^3.0.1", + "dot-prop": "^4.1.0", + "empower-core": "^0.6.1", + "equal-length": "^1.0.0", + "figures": "^2.0.0", + "find-cache-dir": "^1.0.0", + "fn-name": "^2.0.0", + "get-port": "^3.0.0", + "globby": "^6.0.0", + "has-flag": "^2.0.0", + "hullabaloo-config-manager": "^1.1.0", + "ignore-by-default": "^1.0.0", + "import-local": "^0.1.1", + "indent-string": "^3.0.0", + "is-ci": "^1.0.7", + "is-generator-fn": "^1.0.0", + "is-obj": "^1.0.0", + "is-observable": "^1.0.0", + "is-promise": "^2.1.0", + "last-line-stream": "^1.0.0", + "lodash.clonedeepwith": "^4.5.0", + "lodash.debounce": "^4.0.3", + "lodash.difference": "^4.3.0", + "lodash.flatten": "^4.2.0", + "loud-rejection": "^1.2.0", + "make-dir": "^1.0.0", + "matcher": "^1.0.0", + "md5-hex": "^2.0.0", + "meow": "^3.7.0", + "ms": "^2.0.0", + "multimatch": "^2.1.0", + "observable-to-promise": "^0.5.0", + "option-chain": "^1.0.0", + "package-hash": "^2.0.0", + "pkg-conf": "^2.0.0", + "plur": "^2.0.0", + "pretty-ms": "^3.0.0", + "require-precompiled": "^0.1.0", + "resolve-cwd": "^2.0.0", + "safe-buffer": "^5.1.1", + "semver": "^5.4.1", + "slash": "^1.0.0", + "source-map-support": "^0.5.0", + "stack-utils": "^1.0.1", + "strip-ansi": "^4.0.0", + "strip-bom-buf": "^1.0.0", + "supertap": "^1.0.0", + "supports-color": "^5.0.0", + "trim-off-newlines": "^1.0.1", + "unique-temp-dir": "^1.0.0", + "update-notifier": "^2.3.0" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "bundled": true, + "requires": { + "ms": "2.0.0" + } + } + } + }, + "ava-init": { + "version": "0.2.1", + "bundled": true, + "requires": { + "arr-exclude": "^1.0.0", + "execa": "^0.7.0", + "has-yarn": "^1.0.0", + "read-pkg-up": "^2.0.0", + "write-pkg": "^3.1.0" + } + }, + "aws-sign2": { + "version": "0.6.0", + "bundled": true + }, + "aws4": { + "version": "1.7.0", + "bundled": true + }, + "babel-code-frame": { + "version": "6.26.0", + "bundled": true, + "requires": { + "chalk": "^1.1.3", + "esutils": "^2.0.2", + "js-tokens": "^3.0.2" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "bundled": true + }, + "chalk": { + "version": "1.1.3", + "bundled": 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" + } + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "supports-color": { + "version": "2.0.0", + "bundled": true + } + } + }, + "babel-core": { + "version": "6.26.3", + "bundled": true, + "requires": { + "babel-code-frame": "^6.26.0", + "babel-generator": "^6.26.0", + "babel-helpers": "^6.24.1", + "babel-messages": "^6.23.0", + "babel-register": "^6.26.0", + "babel-runtime": "^6.26.0", + "babel-template": "^6.26.0", + "babel-traverse": "^6.26.0", + "babel-types": "^6.26.0", + "babylon": "^6.18.0", + "convert-source-map": "^1.5.1", + "debug": "^2.6.9", + "json5": "^0.5.1", + "lodash": "^4.17.4", + "minimatch": "^3.0.4", + "path-is-absolute": "^1.0.1", + "private": "^0.1.8", + "slash": "^1.0.0", + "source-map": "^0.5.7" + } + }, + "babel-generator": { + "version": "6.26.1", + "bundled": true, + "requires": { + "babel-messages": "^6.23.0", + "babel-runtime": "^6.26.0", + "babel-types": "^6.26.0", + "detect-indent": "^4.0.0", + "jsesc": "^1.3.0", + "lodash": "^4.17.4", + "source-map": "^0.5.7", + "trim-right": "^1.0.1" + }, + "dependencies": { + "jsesc": { + "version": "1.3.0", + "bundled": true + } + } + }, + "babel-helper-builder-binary-assignment-operator-visitor": { + "version": "6.24.1", + "bundled": true, + "requires": { + "babel-helper-explode-assignable-expression": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } + }, + "babel-helper-call-delegate": { + "version": "6.24.1", + "bundled": true, + "requires": { + "babel-helper-hoist-variables": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" + } + }, + "babel-helper-explode-assignable-expression": { + "version": "6.24.1", + "bundled": true, + "requires": { + "babel-runtime": "^6.22.0", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" + } + }, + "babel-helper-function-name": { + "version": "6.24.1", + "bundled": true, + "requires": { + "babel-helper-get-function-arity": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" + } + }, + "babel-helper-get-function-arity": { + "version": "6.24.1", + "bundled": true, + "requires": { + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } + }, + "babel-helper-hoist-variables": { + "version": "6.24.1", + "bundled": true, + "requires": { + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } + }, + "babel-helper-regex": { + "version": "6.26.0", + "bundled": true, + "requires": { + "babel-runtime": "^6.26.0", + "babel-types": "^6.26.0", + "lodash": "^4.17.4" + } + }, + "babel-helper-remap-async-to-generator": { + "version": "6.24.1", + "bundled": true, + "requires": { + "babel-helper-function-name": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" + } + }, + "babel-helpers": { + "version": "6.24.1", + "bundled": true, + "requires": { + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1" + } + }, + "babel-messages": { + "version": "6.23.0", + "bundled": true, + "requires": { + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-check-es2015-constants": { + "version": "6.22.0", + "bundled": true, + "requires": { + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-espower": { + "version": "2.4.0", + "bundled": true, + "requires": { + "babel-generator": "^6.1.0", + "babylon": "^6.1.0", + "call-matcher": "^1.0.0", + "core-js": "^2.0.0", + "espower-location-detector": "^1.0.0", + "espurify": "^1.6.0", + "estraverse": "^4.1.1" + } + }, + "babel-plugin-syntax-async-functions": { + "version": "6.13.0", + "bundled": true + }, + "babel-plugin-syntax-exponentiation-operator": { + "version": "6.13.0", + "bundled": true + }, + "babel-plugin-syntax-object-rest-spread": { + "version": "6.13.0", + "bundled": true + }, + "babel-plugin-syntax-trailing-function-commas": { + "version": "6.22.0", + "bundled": true + }, + "babel-plugin-transform-async-to-generator": { + "version": "6.24.1", + "bundled": true, + "requires": { + "babel-helper-remap-async-to-generator": "^6.24.1", + "babel-plugin-syntax-async-functions": "^6.8.0", + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-transform-es2015-destructuring": { + "version": "6.23.0", + "bundled": true, + "requires": { + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-transform-es2015-function-name": { + "version": "6.24.1", + "bundled": true, + "requires": { + "babel-helper-function-name": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } + }, + "babel-plugin-transform-es2015-modules-commonjs": { + "version": "6.26.2", + "bundled": true, + "requires": { + "babel-plugin-transform-strict-mode": "^6.24.1", + "babel-runtime": "^6.26.0", + "babel-template": "^6.26.0", + "babel-types": "^6.26.0" + } + }, + "babel-plugin-transform-es2015-parameters": { + "version": "6.24.1", + "bundled": true, + "requires": { + "babel-helper-call-delegate": "^6.24.1", + "babel-helper-get-function-arity": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" + } + }, + "babel-plugin-transform-es2015-spread": { + "version": "6.22.0", + "bundled": true, + "requires": { + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-transform-es2015-sticky-regex": { + "version": "6.24.1", + "bundled": true, + "requires": { + "babel-helper-regex": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } + }, + "babel-plugin-transform-es2015-unicode-regex": { + "version": "6.24.1", + "bundled": true, + "requires": { + "babel-helper-regex": "^6.24.1", + "babel-runtime": "^6.22.0", + "regexpu-core": "^2.0.0" + } + }, + "babel-plugin-transform-exponentiation-operator": { + "version": "6.24.1", + "bundled": true, + "requires": { + "babel-helper-builder-binary-assignment-operator-visitor": "^6.24.1", + "babel-plugin-syntax-exponentiation-operator": "^6.8.0", + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-transform-strict-mode": { + "version": "6.24.1", + "bundled": true, + "requires": { + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } + }, + "babel-register": { + "version": "6.26.0", + "bundled": true, + "requires": { + "babel-core": "^6.26.0", + "babel-runtime": "^6.26.0", + "core-js": "^2.5.0", + "home-or-tmp": "^2.0.0", + "lodash": "^4.17.4", + "mkdirp": "^0.5.1", + "source-map-support": "^0.4.15" + }, + "dependencies": { + "source-map-support": { + "version": "0.4.18", + "bundled": true, + "requires": { + "source-map": "^0.5.6" + } + } + } + }, + "babel-runtime": { + "version": "6.26.0", + "bundled": true, + "requires": { + "core-js": "^2.4.0", + "regenerator-runtime": "^0.11.0" + } + }, + "babel-template": { + "version": "6.26.0", + "bundled": true, + "requires": { + "babel-runtime": "^6.26.0", + "babel-traverse": "^6.26.0", + "babel-types": "^6.26.0", + "babylon": "^6.18.0", + "lodash": "^4.17.4" + } + }, + "babel-traverse": { + "version": "6.26.0", + "bundled": true, + "requires": { + "babel-code-frame": "^6.26.0", + "babel-messages": "^6.23.0", + "babel-runtime": "^6.26.0", + "babel-types": "^6.26.0", + "babylon": "^6.18.0", + "debug": "^2.6.8", + "globals": "^9.18.0", + "invariant": "^2.2.2", + "lodash": "^4.17.4" + } + }, + "babel-types": { + "version": "6.26.0", + "bundled": true, + "requires": { + "babel-runtime": "^6.26.0", + "esutils": "^2.0.2", + "lodash": "^4.17.4", + "to-fast-properties": "^1.0.3" + } + }, + "babylon": { + "version": "6.18.0", + "bundled": true + }, + "balanced-match": { + "version": "1.0.0", + "bundled": true + }, + "bcrypt-pbkdf": { + "version": "1.0.1", + "bundled": true, + "optional": true, + "requires": { + "tweetnacl": "^0.14.3" + } + }, + "binary-extensions": { + "version": "1.11.0", + "bundled": true + }, + "bindings": { + "version": "1.2.1", + "bundled": true + }, + "block-stream": { + "version": "0.0.9", + "bundled": true, + "requires": { + "inherits": "~2.0.0" + } + }, + "bluebird": { + "version": "3.5.1", + "bundled": true + }, + "boom": { + "version": "2.10.1", + "bundled": true, + "requires": { + "hoek": "2.x.x" + } + }, + "boxen": { + "version": "1.3.0", + "bundled": true, + "requires": { + "ansi-align": "^2.0.0", + "camelcase": "^4.0.0", + "chalk": "^2.0.1", + "cli-boxes": "^1.0.0", + "string-width": "^2.0.0", + "term-size": "^1.2.0", + "widest-line": "^2.0.0" + }, + "dependencies": { + "camelcase": { + "version": "4.1.0", + "bundled": true + } + } + }, + "bplist-parser": { + "version": "0.0.6", + "bundled": true, + "optional": true + }, + "brace-expansion": { + "version": "1.1.11", + "bundled": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "1.8.5", + "bundled": true, + "requires": { + "expand-range": "^1.8.1", + "preserve": "^0.2.0", + "repeat-element": "^1.1.2" + } + }, + "buf-compare": { + "version": "1.0.1", + "bundled": true + }, + "buffer-from": { + "version": "1.0.0", + "bundled": true + }, + "builtin-modules": { + "version": "1.1.1", + "bundled": true + }, + "caching-transform": { + "version": "1.0.1", + "bundled": true, + "requires": { + "md5-hex": "^1.2.0", + "mkdirp": "^0.5.1", + "write-file-atomic": "^1.1.4" + }, + "dependencies": { + "md5-hex": { + "version": "1.3.0", + "bundled": true, + "requires": { + "md5-o-matic": "^0.1.1" + } + }, + "write-file-atomic": { + "version": "1.3.4", + "bundled": true, + "requires": { + "graceful-fs": "^4.1.11", + "imurmurhash": "^0.1.4", + "slide": "^1.1.5" + } + } + } + }, + "call-matcher": { + "version": "1.0.1", + "bundled": true, + "requires": { + "core-js": "^2.0.0", + "deep-equal": "^1.0.0", + "espurify": "^1.6.0", + "estraverse": "^4.0.0" + } + }, + "call-signature": { + "version": "0.0.2", + "bundled": true + }, + "caller-path": { + "version": "0.1.0", + "bundled": true, + "requires": { + "callsites": "^0.2.0" + } + }, + "callsites": { + "version": "0.2.0", + "bundled": true + }, + "camelcase": { + "version": "2.1.1", + "bundled": true + }, + "camelcase-keys": { + "version": "2.1.0", + "bundled": true, + "requires": { + "camelcase": "^2.0.0", + "map-obj": "^1.0.0" + } + }, + "capture-stack-trace": { + "version": "1.0.0", + "bundled": true + }, + "case": { + "version": "1.5.4", + "bundled": true + }, + "caseless": { + "version": "0.12.0", + "bundled": true + }, + "catharsis": { + "version": "0.8.9", + "bundled": true, + "requires": { + "underscore-contrib": "~0.3.0" + } + }, + "chalk": { + "version": "2.4.1", + "bundled": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "chardet": { + "version": "0.4.2", + "bundled": true + }, + "chokidar": { + "version": "1.7.0", + "bundled": true, + "requires": { + "anymatch": "^1.3.0", + "async-each": "^1.0.0", + "fsevents": "^1.0.0", + "glob-parent": "^2.0.0", + "inherits": "^2.0.1", + "is-binary-path": "^1.0.0", + "is-glob": "^2.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.0.0" + } + }, + "ci-info": { + "version": "1.1.3", + "bundled": true + }, + "circular-json": { + "version": "0.3.3", + "bundled": true + }, + "clean-stack": { + "version": "1.3.0", + "bundled": true + }, + "clean-yaml-object": { + "version": "0.1.0", + "bundled": true + }, + "cli-boxes": { + "version": "1.0.0", + "bundled": true + }, + "cli-cursor": { + "version": "2.1.0", + "bundled": true, + "requires": { + "restore-cursor": "^2.0.0" + } + }, + "cli-spinners": { + "version": "1.3.1", + "bundled": true + }, + "cli-truncate": { + "version": "1.1.0", + "bundled": true, + "requires": { + "slice-ansi": "^1.0.0", + "string-width": "^2.0.0" + } + }, + "cli-width": { + "version": "2.2.0", + "bundled": true + }, + "co": { + "version": "4.6.0", + "bundled": true + }, + "co-with-promise": { + "version": "4.6.0", + "bundled": true, + "requires": { + "pinkie-promise": "^1.0.0" + } + }, + "code-excerpt": { + "version": "2.1.1", + "bundled": true, + "requires": { + "convert-to-spaces": "^1.0.1" + } + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true + }, + "color-convert": { + "version": "1.9.1", + "bundled": true, + "requires": { + "color-name": "^1.1.1" + } + }, + "color-name": { + "version": "1.1.3", + "bundled": true + }, + "colors": { + "version": "1.0.3", + "bundled": true + }, + "combined-stream": { + "version": "1.0.6", + "bundled": true, + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "common-path-prefix": { + "version": "1.0.0", + "bundled": true + }, + "commondir": { + "version": "1.0.1", + "bundled": true + }, + "concat-map": { + "version": "0.0.1", + "bundled": true + }, + "concat-stream": { + "version": "1.6.2", + "bundled": true, + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "concordance": { + "version": "3.0.0", + "bundled": true, + "requires": { + "date-time": "^2.1.0", + "esutils": "^2.0.2", + "fast-diff": "^1.1.1", + "function-name-support": "^0.2.0", + "js-string-escape": "^1.0.1", + "lodash.clonedeep": "^4.5.0", + "lodash.flattendeep": "^4.4.0", + "lodash.merge": "^4.6.0", + "md5-hex": "^2.0.0", + "semver": "^5.3.0", + "well-known-symbols": "^1.0.0" + }, + "dependencies": { + "date-time": { + "version": "2.1.0", + "bundled": true, + "requires": { + "time-zone": "^1.0.0" + } + } + } + }, + "configstore": { + "version": "3.1.2", + "bundled": true, + "requires": { + "dot-prop": "^4.1.0", + "graceful-fs": "^4.1.2", + "make-dir": "^1.0.0", + "unique-string": "^1.0.0", + "write-file-atomic": "^2.0.0", + "xdg-basedir": "^3.0.0" + } + }, + "console-control-strings": { + "version": "1.1.0", + "bundled": true + }, + "convert-source-map": { + "version": "1.5.1", + "bundled": true + }, + "convert-to-spaces": { + "version": "1.0.2", + "bundled": true + }, + "core-assert": { + "version": "0.2.1", + "bundled": true, + "requires": { + "buf-compare": "^1.0.0", + "is-error": "^2.2.0" + } + }, + "core-js": { + "version": "2.5.7", + "bundled": true + }, + "core-util-is": { + "version": "1.0.2", + "bundled": true + }, + "create-error-class": { + "version": "3.0.2", + "bundled": true, + "requires": { + "capture-stack-trace": "^1.0.0" + } + }, + "cross-spawn": { + "version": "5.1.0", + "bundled": true, + "requires": { + "lru-cache": "^4.0.1", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "cryptiles": { + "version": "2.0.5", + "bundled": true, + "requires": { + "boom": "2.x.x" + } + }, + "crypto-random-string": { + "version": "1.0.0", + "bundled": true + }, + "currently-unhandled": { + "version": "0.4.1", + "bundled": true, + "requires": { + "array-find-index": "^1.0.1" + } + }, + "cycle": { + "version": "1.0.3", + "bundled": true + }, + "dashdash": { + "version": "1.14.1", + "bundled": true, + "requires": { + "assert-plus": "^1.0.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true + } + } + }, + "date-time": { + "version": "0.1.1", + "bundled": true + }, + "debug": { + "version": "2.6.9", + "bundled": true, + "requires": { + "ms": "2.0.0" + } + }, + "decamelize": { + "version": "1.2.0", + "bundled": true + }, + "deep-equal": { + "version": "1.0.1", + "bundled": true + }, + "deep-extend": { + "version": "0.4.2", + "bundled": true + }, + "deep-is": { + "version": "0.1.3", + "bundled": true + }, + "del": { + "version": "2.2.2", + "bundled": true, + "requires": { + "globby": "^5.0.0", + "is-path-cwd": "^1.0.0", + "is-path-in-cwd": "^1.0.0", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "rimraf": "^2.2.8" + }, + "dependencies": { + "globby": { + "version": "5.0.0", + "bundled": true, + "requires": { + "array-union": "^1.0.1", + "arrify": "^1.0.0", + "glob": "^7.0.3", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "pinkie": { + "version": "2.0.4", + "bundled": true + }, + "pinkie-promise": { + "version": "2.0.1", + "bundled": true, + "requires": { + "pinkie": "^2.0.0" + } + } + } + }, + "delayed-stream": { + "version": "1.0.0", + "bundled": true + }, + "delegates": { + "version": "1.0.0", + "bundled": true + }, + "detect-indent": { + "version": "4.0.0", + "bundled": true, + "requires": { + "repeating": "^2.0.0" + } + }, + "dgram": { + "version": "1.0.1", + "bundled": true + }, + "doctrine": { + "version": "2.1.0", + "bundled": true, + "requires": { + "esutils": "^2.0.2" + } + }, + "dot-prop": { + "version": "4.2.0", + "bundled": true, + "requires": { + "is-obj": "^1.0.0" + } + }, + "duplexer3": { + "version": "0.1.4", + "bundled": true + }, + "ecc-jsbn": { + "version": "0.1.1", + "bundled": true, + "optional": true, + "requires": { + "jsbn": "~0.1.0" + } + }, + "empower-core": { + "version": "0.6.2", + "bundled": true, + "requires": { + "call-signature": "0.0.2", + "core-js": "^2.0.0" + } + }, + "equal-length": { + "version": "1.0.1", + "bundled": true + }, + "error-ex": { + "version": "1.3.1", + "bundled": true, + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "es6-error": { + "version": "4.1.1", + "bundled": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "bundled": true + }, + "eslint": { + "version": "4.19.1", + "bundled": true, + "requires": { + "ajv": "^5.3.0", + "babel-code-frame": "^6.22.0", + "chalk": "^2.1.0", + "concat-stream": "^1.6.0", + "cross-spawn": "^5.1.0", + "debug": "^3.1.0", + "doctrine": "^2.1.0", + "eslint-scope": "^3.7.1", + "eslint-visitor-keys": "^1.0.0", + "espree": "^3.5.4", + "esquery": "^1.0.0", + "esutils": "^2.0.2", + "file-entry-cache": "^2.0.0", + "functional-red-black-tree": "^1.0.1", + "glob": "^7.1.2", + "globals": "^11.0.1", + "ignore": "^3.3.3", + "imurmurhash": "^0.1.4", + "inquirer": "^3.0.6", + "is-resolvable": "^1.0.0", + "js-yaml": "^3.9.1", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.3.0", + "lodash": "^4.17.4", + "minimatch": "^3.0.2", + "mkdirp": "^0.5.1", + "natural-compare": "^1.4.0", + "optionator": "^0.8.2", + "path-is-inside": "^1.0.2", + "pluralize": "^7.0.0", + "progress": "^2.0.0", + "regexpp": "^1.0.1", + "require-uncached": "^1.0.3", + "semver": "^5.3.0", + "strip-ansi": "^4.0.0", + "strip-json-comments": "~2.0.1", + "table": "4.0.2", + "text-table": "~0.2.0" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "bundled": true, + "requires": { + "ms": "2.0.0" + } + }, + "globals": { + "version": "11.5.0", + "bundled": true + } + } + }, + "eslint-scope": { + "version": "3.7.1", + "bundled": true, + "requires": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + }, + "eslint-visitor-keys": { + "version": "1.0.0", + "bundled": true + }, + "espower-location-detector": { + "version": "1.0.0", + "bundled": true, + "requires": { + "is-url": "^1.2.1", + "path-is-absolute": "^1.0.0", + "source-map": "^0.5.0", + "xtend": "^4.0.0" + } + }, + "espree": { + "version": "3.5.4", + "bundled": true, + "requires": { + "acorn": "^5.5.0", + "acorn-jsx": "^3.0.0" + } + }, + "esprima": { + "version": "4.0.0", + "bundled": true + }, + "espurify": { + "version": "1.8.0", + "bundled": true, + "requires": { + "core-js": "^2.0.0" + } + }, + "esquery": { + "version": "1.0.1", + "bundled": true, + "requires": { + "estraverse": "^4.0.0" + } + }, + "esrecurse": { + "version": "4.2.1", + "bundled": true, + "requires": { + "estraverse": "^4.1.0" + } + }, + "estraverse": { + "version": "4.2.0", + "bundled": true + }, + "esutils": { + "version": "2.0.2", + "bundled": true + }, + "events": { + "version": "3.0.0", + "bundled": true + }, + "execa": { + "version": "0.7.0", + "bundled": 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" + } + }, + "expand-brackets": { + "version": "0.1.5", + "bundled": true, + "requires": { + "is-posix-bracket": "^0.1.0" + } + }, + "expand-range": { + "version": "1.8.2", + "bundled": true, + "requires": { + "fill-range": "^2.1.0" + } + }, + "extend": { + "version": "3.0.1", + "bundled": true + }, + "external-editor": { + "version": "2.2.0", + "bundled": true, + "requires": { + "chardet": "^0.4.0", + "iconv-lite": "^0.4.17", + "tmp": "^0.0.33" + } + }, + "extglob": { + "version": "0.3.2", + "bundled": true, + "requires": { + "is-extglob": "^1.0.0" + } + }, + "extsprintf": { + "version": "1.3.0", + "bundled": true + }, + "eyes": { + "version": "0.1.8", + "bundled": true + }, + "fast-deep-equal": { + "version": "1.1.0", + "bundled": true + }, + "fast-diff": { + "version": "1.1.2", + "bundled": true + }, + "fast-json-stable-stringify": { + "version": "2.0.0", + "bundled": true + }, + "fast-levenshtein": { + "version": "2.0.6", + "bundled": true + }, + "figures": { + "version": "2.0.0", + "bundled": true, + "requires": { + "escape-string-regexp": "^1.0.5" + } + }, + "file-entry-cache": { + "version": "2.0.0", + "bundled": true, + "requires": { + "flat-cache": "^1.2.1", + "object-assign": "^4.0.1" + } + }, + "filename-regex": { + "version": "2.0.1", + "bundled": true + }, + "fill-range": { + "version": "2.2.4", + "bundled": true, + "requires": { + "is-number": "^2.1.0", + "isobject": "^2.0.0", + "randomatic": "^3.0.0", + "repeat-element": "^1.1.2", + "repeat-string": "^1.5.2" + } + }, + "find-cache-dir": { + "version": "1.0.0", + "bundled": true, + "requires": { + "commondir": "^1.0.1", + "make-dir": "^1.0.0", + "pkg-dir": "^2.0.0" + } + }, + "find-up": { + "version": "2.1.0", + "bundled": true, + "requires": { + "locate-path": "^2.0.0" + } + }, + "flat-cache": { + "version": "1.3.0", + "bundled": true, + "requires": { + "circular-json": "^0.3.1", + "del": "^2.0.2", + "graceful-fs": "^4.1.2", + "write": "^0.2.1" + } + }, + "fn-name": { + "version": "2.0.1", + "bundled": true + }, + "for-in": { + "version": "1.0.2", + "bundled": true + }, + "for-own": { + "version": "0.1.5", + "bundled": true, + "requires": { + "for-in": "^1.0.1" + } + }, + "forever-agent": { + "version": "0.6.1", + "bundled": true + }, + "form-data": { + "version": "2.1.4", + "bundled": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.5", + "mime-types": "^2.1.12" + } + }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true + }, + "fsevents": { + "version": "1.2.4", + "bundled": true, + "optional": true, + "requires": { + "nan": "^2.9.2", + "node-pre-gyp": "^0.10.0" + }, + "dependencies": { + "abbrev": { + "version": "1.1.1", + "bundled": true, + "optional": true + }, + "ansi-regex": { + "version": "2.1.1", + "bundled": true + }, + "aproba": { + "version": "1.2.0", + "bundled": true, + "optional": true + }, + "are-we-there-yet": { + "version": "1.1.4", + "bundled": true, + "optional": true, + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "balanced-match": { + "version": "1.0.0", + "bundled": true + }, + "brace-expansion": { + "version": "1.1.11", + "bundled": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "chownr": { + "version": "1.0.1", + "bundled": true, + "optional": true + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true + }, + "concat-map": { + "version": "0.0.1", + "bundled": true + }, + "console-control-strings": { + "version": "1.1.0", + "bundled": true + }, + "core-util-is": { + "version": "1.0.2", + "bundled": true, + "optional": true + }, + "debug": { + "version": "2.6.9", + "bundled": true, + "optional": true, + "requires": { + "ms": "2.0.0" + } + }, + "deep-extend": { + "version": "0.5.1", + "bundled": true, + "optional": true + }, + "delegates": { + "version": "1.0.0", + "bundled": true, + "optional": true + }, + "detect-libc": { + "version": "1.0.3", + "bundled": true, + "optional": true + }, + "fs-minipass": { + "version": "1.2.5", + "bundled": true, + "optional": true, + "requires": { + "minipass": "^2.2.1" + } + }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true, + "optional": true + }, + "gauge": { + "version": "2.7.4", + "bundled": 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.2", + "bundled": 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", + "bundled": true, + "optional": true + }, + "iconv-lite": { + "version": "0.4.21", + "bundled": true, + "optional": true, + "requires": { + "safer-buffer": "^2.1.0" + } + }, + "ignore-walk": { + "version": "3.0.1", + "bundled": true, + "optional": true, + "requires": { + "minimatch": "^3.0.4" + } + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "optional": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.3", + "bundled": true + }, + "ini": { + "version": "1.3.5", + "bundled": true, + "optional": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "isarray": { + "version": "1.0.0", + "bundled": true, + "optional": true + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "0.0.8", + "bundled": true + }, + "minipass": { + "version": "2.2.4", + "bundled": true, + "requires": { + "safe-buffer": "^5.1.1", + "yallist": "^3.0.0" + } + }, + "minizlib": { + "version": "1.1.0", + "bundled": true, + "optional": true, + "requires": { + "minipass": "^2.2.1" + } + }, + "mkdirp": { + "version": "0.5.1", + "bundled": true, + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "2.0.0", + "bundled": true, + "optional": true + }, + "nan": { + "version": "2.10.0", + "bundled": true, + "optional": true + }, + "needle": { + "version": "2.2.0", + "bundled": true, + "optional": true, + "requires": { + "debug": "^2.1.2", + "iconv-lite": "^0.4.4", + "sax": "^1.2.4" + } + }, + "node-pre-gyp": { + "version": "0.10.0", + "bundled": true, + "optional": true, + "requires": { + "detect-libc": "^1.0.2", + "mkdirp": "^0.5.1", + "needle": "^2.2.0", + "nopt": "^4.0.1", + "npm-packlist": "^1.1.6", + "npmlog": "^4.0.2", + "rc": "^1.1.7", + "rimraf": "^2.6.1", + "semver": "^5.3.0", + "tar": "^4" + } + }, + "nopt": { + "version": "4.0.1", + "bundled": true, + "optional": true, + "requires": { + "abbrev": "1", + "osenv": "^0.1.4" + } + }, + "npm-bundled": { + "version": "1.0.3", + "bundled": true, + "optional": true + }, + "npm-packlist": { + "version": "1.1.10", + "bundled": true, + "optional": true, + "requires": { + "ignore-walk": "^3.0.1", + "npm-bundled": "^1.0.1" + } + }, + "npmlog": { + "version": "4.1.2", + "bundled": 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", + "bundled": true + }, + "object-assign": { + "version": "4.1.1", + "bundled": true, + "optional": true + }, + "once": { + "version": "1.4.0", + "bundled": true, + "requires": { + "wrappy": "1" + } + }, + "os-homedir": { + "version": "1.0.2", + "bundled": true, + "optional": true + }, + "os-tmpdir": { + "version": "1.0.2", + "bundled": true, + "optional": true + }, + "osenv": { + "version": "0.1.5", + "bundled": true, + "optional": true, + "requires": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true, + "optional": true + }, + "process-nextick-args": { + "version": "2.0.0", + "bundled": true, + "optional": true + }, + "rc": { + "version": "1.2.7", + "bundled": true, + "optional": true, + "requires": { + "deep-extend": "^0.5.1", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "bundled": true, + "optional": true + } + } + }, + "readable-stream": { + "version": "2.3.6", + "bundled": 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.6.2", + "bundled": true, + "optional": true, + "requires": { + "glob": "^7.0.5" + } + }, + "safe-buffer": { + "version": "5.1.1", + "bundled": true + }, + "safer-buffer": { + "version": "2.1.2", + "bundled": true, + "optional": true + }, + "sax": { + "version": "1.2.4", + "bundled": true, + "optional": true + }, + "semver": { + "version": "5.5.0", + "bundled": true, + "optional": true + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true, + "optional": true + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true, + "optional": true + }, + "string-width": { + "version": "1.0.2", + "bundled": 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", + "bundled": true, + "optional": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "bundled": true, + "optional": true + }, + "tar": { + "version": "4.4.1", + "bundled": true, + "optional": true, + "requires": { + "chownr": "^1.0.1", + "fs-minipass": "^1.2.5", + "minipass": "^2.2.4", + "minizlib": "^1.1.0", + "mkdirp": "^0.5.0", + "safe-buffer": "^5.1.1", + "yallist": "^3.0.2" + } + }, + "util-deprecate": { + "version": "1.0.2", + "bundled": true, + "optional": true + }, + "wide-align": { + "version": "1.1.2", + "bundled": true, + "optional": true, + "requires": { + "string-width": "^1.0.2" + } + }, + "wrappy": { + "version": "1.0.2", + "bundled": true + }, + "yallist": { + "version": "3.0.2", + "bundled": true + } + } + }, + "fstream": { + "version": "1.0.11", + "bundled": true, + "requires": { + "graceful-fs": "^4.1.2", + "inherits": "~2.0.0", + "mkdirp": ">=0.5 0", + "rimraf": "2" + } + }, + "function-name-support": { + "version": "0.2.0", + "bundled": true + }, + "functional-red-black-tree": { + "version": "1.0.1", + "bundled": true + }, + "gauge": { + "version": "2.7.4", + "bundled": 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" + }, + "dependencies": { + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "string-width": { + "version": "1.0.2", + "bundled": 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", + "bundled": true, + "requires": { + "ansi-regex": "^2.0.0" + } + } + } + }, + "get-port": { + "version": "3.2.0", + "bundled": true + }, + "get-stdin": { + "version": "4.0.1", + "bundled": true + }, + "get-stream": { + "version": "3.0.0", + "bundled": true + }, + "getpass": { + "version": "0.1.7", + "bundled": true, + "requires": { + "assert-plus": "^1.0.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true + } + } + }, + "glob": { + "version": "7.1.2", + "bundled": 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" + } + }, + "glob-base": { + "version": "0.3.0", + "bundled": true, + "requires": { + "glob-parent": "^2.0.0", + "is-glob": "^2.0.0" + } + }, + "glob-parent": { + "version": "2.0.0", + "bundled": true, + "requires": { + "is-glob": "^2.0.0" + } + }, + "global-dirs": { + "version": "0.1.1", + "bundled": true, + "requires": { + "ini": "^1.3.4" + } + }, + "globals": { + "version": "9.18.0", + "bundled": true + }, + "globby": { + "version": "6.1.0", + "bundled": true, + "requires": { + "array-union": "^1.0.1", + "glob": "^7.0.3", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + }, + "dependencies": { + "pinkie": { + "version": "2.0.4", + "bundled": true + }, + "pinkie-promise": { + "version": "2.0.1", + "bundled": true, + "requires": { + "pinkie": "^2.0.0" + } + } + } + }, + "got": { + "version": "6.7.1", + "bundled": true, + "requires": { + "create-error-class": "^3.0.0", + "duplexer3": "^0.1.4", + "get-stream": "^3.0.0", + "is-redirect": "^1.0.0", + "is-retry-allowed": "^1.0.0", + "is-stream": "^1.0.0", + "lowercase-keys": "^1.0.0", + "safe-buffer": "^5.0.1", + "timed-out": "^4.0.0", + "unzip-response": "^2.0.1", + "url-parse-lax": "^1.0.0" + } + }, + "graceful-fs": { + "version": "4.1.11", + "bundled": true + }, + "har-schema": { + "version": "1.0.5", + "bundled": true + }, + "har-validator": { + "version": "4.2.1", + "bundled": true, + "requires": { + "ajv": "^4.9.1", + "har-schema": "^1.0.5" + }, + "dependencies": { + "ajv": { + "version": "4.11.8", + "bundled": true, + "requires": { + "co": "^4.6.0", + "json-stable-stringify": "^1.0.1" + } + } + } + }, + "has-ansi": { + "version": "2.0.0", + "bundled": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "has-color": { + "version": "0.1.7", + "bundled": true + }, + "has-flag": { + "version": "2.0.0", + "bundled": true + }, + "has-unicode": { + "version": "2.0.1", + "bundled": true + }, + "has-yarn": { + "version": "1.0.0", + "bundled": true + }, + "hawk": { + "version": "3.1.3", + "bundled": true, + "requires": { + "boom": "2.x.x", + "cryptiles": "2.x.x", + "hoek": "2.x.x", + "sntp": "1.x.x" + } + }, + "hoek": { + "version": "2.16.3", + "bundled": true + }, + "home-or-tmp": { + "version": "2.0.0", + "bundled": true, + "requires": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.1" + } + }, + "hosted-git-info": { + "version": "2.6.0", + "bundled": true + }, + "http-signature": { + "version": "1.1.1", + "bundled": true, + "requires": { + "assert-plus": "^0.2.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + } + }, + "hullabaloo-config-manager": { + "version": "1.1.1", + "bundled": true, + "requires": { + "dot-prop": "^4.1.0", + "es6-error": "^4.0.2", + "graceful-fs": "^4.1.11", + "indent-string": "^3.1.0", + "json5": "^0.5.1", + "lodash.clonedeep": "^4.5.0", + "lodash.clonedeepwith": "^4.5.0", + "lodash.isequal": "^4.5.0", + "lodash.merge": "^4.6.0", + "md5-hex": "^2.0.0", + "package-hash": "^2.0.0", + "pkg-dir": "^2.0.0", + "resolve-from": "^3.0.0", + "safe-buffer": "^5.0.1" + } + }, + "iconv-lite": { + "version": "0.4.23", + "bundled": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ignore": { + "version": "3.3.8", + "bundled": true + }, + "ignore-by-default": { + "version": "1.0.1", + "bundled": true + }, + "import-lazy": { + "version": "2.1.0", + "bundled": true + }, + "import-local": { + "version": "0.1.1", + "bundled": true, + "requires": { + "pkg-dir": "^2.0.0", + "resolve-cwd": "^2.0.0" + } + }, + "imurmurhash": { + "version": "0.1.4", + "bundled": true + }, + "indent-string": { + "version": "3.2.0", + "bundled": true + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.3", + "bundled": true + }, + "ini": { + "version": "1.3.5", + "bundled": true + }, + "inquirer": { + "version": "3.3.0", + "bundled": true, + "requires": { + "ansi-escapes": "^3.0.0", + "chalk": "^2.0.0", + "cli-cursor": "^2.1.0", + "cli-width": "^2.0.0", + "external-editor": "^2.0.4", + "figures": "^2.0.0", + "lodash": "^4.3.0", + "mute-stream": "0.0.7", + "run-async": "^2.2.0", + "rx-lite": "^4.0.8", + "rx-lite-aggregates": "^4.0.8", + "string-width": "^2.1.0", + "strip-ansi": "^4.0.0", + "through": "^2.3.6" + } + }, + "invariant": { + "version": "2.2.4", + "bundled": true, + "requires": { + "loose-envify": "^1.0.0" + } + }, + "irregular-plurals": { + "version": "1.4.0", + "bundled": true + }, + "is-arrayish": { + "version": "0.2.1", + "bundled": true + }, + "is-binary-path": { + "version": "1.0.1", + "bundled": true, + "requires": { + "binary-extensions": "^1.0.0" + } + }, + "is-buffer": { + "version": "1.1.6", + "bundled": true + }, + "is-builtin-module": { + "version": "1.0.0", + "bundled": true, + "requires": { + "builtin-modules": "^1.0.0" + } + }, + "is-ci": { + "version": "1.1.0", + "bundled": true, + "requires": { + "ci-info": "^1.0.0" + } + }, + "is-dotfile": { + "version": "1.0.3", + "bundled": true + }, + "is-equal-shallow": { + "version": "0.1.3", + "bundled": true, + "requires": { + "is-primitive": "^2.0.0" + } + }, + "is-error": { + "version": "2.2.1", + "bundled": true + }, + "is-extendable": { + "version": "0.1.1", + "bundled": true + }, + "is-extglob": { + "version": "1.0.0", + "bundled": true + }, + "is-finite": { + "version": "1.0.2", + "bundled": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "bundled": true + }, + "is-generator-fn": { + "version": "1.0.0", + "bundled": true + }, + "is-glob": { + "version": "2.0.1", + "bundled": true, + "requires": { + "is-extglob": "^1.0.0" + } + }, + "is-installed-globally": { + "version": "0.1.0", + "bundled": true, + "requires": { + "global-dirs": "^0.1.0", + "is-path-inside": "^1.0.0" + } + }, + "is-npm": { + "version": "1.0.0", + "bundled": true + }, + "is-number": { + "version": "2.1.0", + "bundled": true, + "requires": { + "kind-of": "^3.0.2" + } + }, + "is-obj": { + "version": "1.0.1", + "bundled": true + }, + "is-observable": { + "version": "1.1.0", + "bundled": true, + "requires": { + "symbol-observable": "^1.1.0" + } + }, + "is-path-cwd": { + "version": "1.0.0", + "bundled": true + }, + "is-path-in-cwd": { + "version": "1.0.1", + "bundled": true, + "requires": { + "is-path-inside": "^1.0.0" + } + }, + "is-path-inside": { + "version": "1.0.1", + "bundled": true, + "requires": { + "path-is-inside": "^1.0.1" + } + }, + "is-plain-obj": { + "version": "1.1.0", + "bundled": true + }, + "is-posix-bracket": { + "version": "0.1.1", + "bundled": true + }, + "is-primitive": { + "version": "2.0.0", + "bundled": true + }, + "is-promise": { + "version": "2.1.0", + "bundled": true + }, + "is-redirect": { + "version": "1.0.0", + "bundled": true + }, + "is-resolvable": { + "version": "1.1.0", + "bundled": true + }, + "is-retry-allowed": { + "version": "1.1.0", + "bundled": true + }, + "is-stream": { + "version": "1.1.0", + "bundled": true + }, + "is-typedarray": { + "version": "1.0.0", + "bundled": true + }, + "is-url": { + "version": "1.2.4", + "bundled": true + }, + "is-utf8": { + "version": "0.2.1", + "bundled": true + }, + "isarray": { + "version": "1.0.0", + "bundled": true + }, + "isexe": { + "version": "2.0.0", + "bundled": true + }, + "isobject": { + "version": "2.1.0", + "bundled": true, + "requires": { + "isarray": "1.0.0" + } + }, + "isstream": { + "version": "0.1.2", + "bundled": true + }, + "js-string-escape": { + "version": "1.0.1", + "bundled": true + }, + "js-tokens": { + "version": "3.0.2", + "bundled": true + }, + "js-yaml": { + "version": "3.11.0", + "bundled": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "js2xmlparser": { + "version": "3.0.0", + "bundled": true, + "requires": { + "xmlcreate": "^1.0.1" + } + }, + "jsbn": { + "version": "0.1.1", + "bundled": true, + "optional": true + }, + "jsdoc": { + "version": "3.5.5", + "bundled": true, + "requires": { + "babylon": "7.0.0-beta.19", + "bluebird": "~3.5.0", + "catharsis": "~0.8.9", + "escape-string-regexp": "~1.0.5", + "js2xmlparser": "~3.0.0", + "klaw": "~2.0.0", + "marked": "~0.3.6", + "mkdirp": "~0.5.1", + "requizzle": "~0.2.1", + "strip-json-comments": "~2.0.1", + "taffydb": "2.6.2", + "underscore": "~1.8.3" + }, + "dependencies": { + "babylon": { + "version": "7.0.0-beta.19", + "bundled": true + } + } + }, + "jsesc": { + "version": "0.5.0", + "bundled": true + }, + "json-parse-better-errors": { + "version": "1.0.2", + "bundled": true + }, + "json-schema": { + "version": "0.2.3", + "bundled": true + }, + "json-schema-traverse": { + "version": "0.3.1", + "bundled": true + }, + "json-stable-stringify": { + "version": "1.0.1", + "bundled": true, + "requires": { + "jsonify": "~0.0.0" + } + }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "bundled": true + }, + "json-stringify-safe": { + "version": "5.0.1", + "bundled": true + }, + "json5": { + "version": "0.5.1", + "bundled": true + }, + "jsonify": { + "version": "0.0.0", + "bundled": true + }, + "jsprim": { + "version": "1.4.1", + "bundled": true, + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true + } + } + }, + "kind-of": { + "version": "3.2.2", + "bundled": true, + "requires": { + "is-buffer": "^1.1.5" + } + }, + "klaw": { + "version": "2.0.0", + "bundled": true, + "requires": { + "graceful-fs": "^4.1.9" + } + }, + "last-line-stream": { + "version": "1.0.0", + "bundled": true, + "requires": { + "through2": "^2.0.0" + } + }, + "latest-version": { + "version": "3.1.0", + "bundled": true, + "requires": { + "package-json": "^4.0.0" + } + }, + "levn": { + "version": "0.3.0", + "bundled": true, + "requires": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + } + }, + "load-json-file": { + "version": "2.0.0", + "bundled": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "strip-bom": "^3.0.0" + } + }, + "locate-path": { + "version": "2.0.0", + "bundled": true, + "requires": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + } + }, + "lodash": { + "version": "4.17.10", + "bundled": true + }, + "lodash.clonedeep": { + "version": "4.5.0", + "bundled": true + }, + "lodash.clonedeepwith": { + "version": "4.5.0", + "bundled": true + }, + "lodash.debounce": { + "version": "4.0.8", + "bundled": true + }, + "lodash.difference": { + "version": "4.5.0", + "bundled": true + }, + "lodash.flatten": { + "version": "4.4.0", + "bundled": true + }, + "lodash.flattendeep": { + "version": "4.4.0", + "bundled": true + }, + "lodash.isequal": { + "version": "4.5.0", + "bundled": true + }, + "lodash.merge": { + "version": "4.6.1", + "bundled": true + }, + "loose-envify": { + "version": "1.3.1", + "bundled": true, + "requires": { + "js-tokens": "^3.0.0" + } + }, + "loud-rejection": { + "version": "1.6.0", + "bundled": true, + "requires": { + "currently-unhandled": "^0.4.1", + "signal-exit": "^3.0.0" + } + }, + "lowercase-keys": { + "version": "1.0.1", + "bundled": true + }, + "lru-cache": { + "version": "4.1.3", + "bundled": true, + "requires": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "make-dir": { + "version": "1.3.0", + "bundled": true, + "requires": { + "pify": "^3.0.0" + }, + "dependencies": { + "pify": { + "version": "3.0.0", + "bundled": true + } + } + }, + "map-obj": { + "version": "1.0.1", + "bundled": true + }, + "marked": { + "version": "0.3.19", + "bundled": true + }, + "matcher": { + "version": "1.1.1", + "bundled": true, + "requires": { + "escape-string-regexp": "^1.0.4" + } + }, + "math-random": { + "version": "1.0.1", + "bundled": true + }, + "md5-hex": { + "version": "2.0.0", + "bundled": true, + "requires": { + "md5-o-matic": "^0.1.1" + } + }, + "md5-o-matic": { + "version": "0.1.1", + "bundled": true + }, + "mdns": { + "version": "2.4.0", + "bundled": true, + "requires": { + "bindings": "~1.2.1", + "nan": "^2.10.0" + }, + "dependencies": { + "nan": { + "version": "2.10.0", + "bundled": true + } + } + }, + "meow": { + "version": "3.7.0", + "bundled": true, + "requires": { + "camelcase-keys": "^2.0.0", + "decamelize": "^1.1.2", + "loud-rejection": "^1.0.0", + "map-obj": "^1.0.1", + "minimist": "^1.1.3", + "normalize-package-data": "^2.3.4", + "object-assign": "^4.0.1", + "read-pkg-up": "^1.0.1", + "redent": "^1.0.0", + "trim-newlines": "^1.0.0" + }, + "dependencies": { + "find-up": { + "version": "1.1.2", + "bundled": true, + "requires": { + "path-exists": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "load-json-file": { + "version": "1.1.0", + "bundled": 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" + } + }, + "path-exists": { + "version": "2.1.0", + "bundled": true, + "requires": { + "pinkie-promise": "^2.0.0" + } + }, + "path-type": { + "version": "1.1.0", + "bundled": true, + "requires": { + "graceful-fs": "^4.1.2", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "pinkie": { + "version": "2.0.4", + "bundled": true + }, + "pinkie-promise": { + "version": "2.0.1", + "bundled": true, + "requires": { + "pinkie": "^2.0.0" + } + }, + "read-pkg": { + "version": "1.1.0", + "bundled": true, + "requires": { + "load-json-file": "^1.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^1.0.0" + } + }, + "read-pkg-up": { + "version": "1.0.1", + "bundled": true, + "requires": { + "find-up": "^1.0.0", + "read-pkg": "^1.0.0" + } + }, + "strip-bom": { + "version": "2.0.0", + "bundled": true, + "requires": { + "is-utf8": "^0.2.0" + } + } + } + }, + "micromatch": { + "version": "2.3.11", + "bundled": true, + "requires": { + "arr-diff": "^2.0.0", + "array-unique": "^0.2.1", + "braces": "^1.8.2", + "expand-brackets": "^0.1.4", + "extglob": "^0.3.1", + "filename-regex": "^2.0.0", + "is-extglob": "^1.0.0", + "is-glob": "^2.0.1", + "kind-of": "^3.0.2", + "normalize-path": "^2.0.1", + "object.omit": "^2.0.0", + "parse-glob": "^3.0.4", + "regex-cache": "^0.4.2" + } + }, + "mime-db": { + "version": "1.33.0", + "bundled": true + }, + "mime-types": { + "version": "2.1.18", + "bundled": true, + "requires": { + "mime-db": "~1.33.0" + } + }, + "mimic-fn": { + "version": "1.2.0", + "bundled": true + }, + "minami-compat": { + "version": "1.2.4", + "bundled": true + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.0", + "bundled": true + }, + "mkdirp": { + "version": "0.5.1", + "bundled": true, + "requires": { + "minimist": "0.0.8" + }, + "dependencies": { + "minimist": { + "version": "0.0.8", + "bundled": true + } + } + }, + "ms": { + "version": "2.0.0", + "bundled": true + }, + "multimatch": { + "version": "2.1.0", + "bundled": true, + "requires": { + "array-differ": "^1.0.0", + "array-union": "^1.0.1", + "arrify": "^1.0.0", + "minimatch": "^3.0.0" + } + }, + "mute-stream": { + "version": "0.0.7", + "bundled": true + }, + "nan": { + "version": "2.8.0", + "bundled": true, + "optional": true + }, + "natural-compare": { + "version": "1.4.0", + "bundled": true + }, + "net": { + "version": "1.0.2", + "bundled": true + }, + "noble": { + "version": "1.8.1", + "from": "git://github.com/jacobrosenthal/noble.git#highsierra", + "bundled": true, + "requires": { + "bluetooth-hci-socket": "^0.5.1", + "bplist-parser": "0.0.6", + "debug": "~2.2.0", + "xpc-connection": "~0.1.4" + }, + "dependencies": { + "debug": { + "version": "2.2.0", + "bundled": true, + "requires": { + "ms": "0.7.1" + } + }, + "ms": { + "version": "0.7.1", + "bundled": true + } + } + }, + "node-gyp": { + "version": "3.6.2", + "bundled": true, + "requires": { + "fstream": "^1.0.0", + "glob": "^7.0.3", + "graceful-fs": "^4.1.2", + "minimatch": "^3.0.2", + "mkdirp": "^0.5.0", + "nopt": "2 || 3", + "npmlog": "0 || 1 || 2 || 3 || 4", + "osenv": "0", + "request": "2", + "rimraf": "2", + "semver": "~5.3.0", + "tar": "^2.0.0", + "which": "1" + }, + "dependencies": { + "nopt": { + "version": "3.0.6", + "bundled": true, + "requires": { + "abbrev": "1" + } + }, + "semver": { + "version": "5.3.0", + "bundled": true + } + } + }, + "normalize-package-data": { + "version": "2.4.0", + "bundled": true, + "requires": { + "hosted-git-info": "^2.1.4", + "is-builtin-module": "^1.0.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "normalize-path": { + "version": "2.1.1", + "bundled": true, + "requires": { + "remove-trailing-separator": "^1.0.1" + } + }, + "npm-run-path": { + "version": "2.0.2", + "bundled": true, + "requires": { + "path-key": "^2.0.0" + } + }, + "npmlog": { + "version": "4.1.2", + "bundled": 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", + "bundled": true + }, + "oauth-sign": { + "version": "0.8.2", + "bundled": true + }, + "object-assign": { + "version": "4.1.1", + "bundled": true + }, + "object.omit": { + "version": "2.0.1", + "bundled": true, + "requires": { + "for-own": "^0.1.4", + "is-extendable": "^0.1.1" + } + }, + "observable-to-promise": { + "version": "0.5.0", + "bundled": true, + "requires": { + "is-observable": "^0.2.0", + "symbol-observable": "^1.0.4" + }, + "dependencies": { + "is-observable": { + "version": "0.2.0", + "bundled": true, + "requires": { + "symbol-observable": "^0.2.2" + }, + "dependencies": { + "symbol-observable": { + "version": "0.2.4", + "bundled": true + } + } + } + } + }, + "once": { + "version": "1.4.0", + "bundled": true, + "requires": { + "wrappy": "1" + } + }, + "onetime": { + "version": "2.0.1", + "bundled": true, + "requires": { + "mimic-fn": "^1.0.0" + } + }, + "option-chain": { + "version": "1.0.0", + "bundled": true + }, + "optionator": { + "version": "0.8.2", + "bundled": 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", + "bundled": true + }, + "os-tmpdir": { + "version": "1.0.2", + "bundled": true + }, + "osenv": { + "version": "0.1.5", + "bundled": true, + "requires": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" + } + }, + "p-finally": { + "version": "1.0.0", + "bundled": true + }, + "p-limit": { + "version": "1.2.0", + "bundled": true, + "requires": { + "p-try": "^1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "bundled": true, + "requires": { + "p-limit": "^1.1.0" + } + }, + "p-try": { + "version": "1.0.0", + "bundled": true + }, + "package-hash": { + "version": "2.0.0", + "bundled": true, + "requires": { + "graceful-fs": "^4.1.11", + "lodash.flattendeep": "^4.4.0", + "md5-hex": "^2.0.0", + "release-zalgo": "^1.0.0" + } + }, + "package-json": { + "version": "4.0.1", + "bundled": true, + "requires": { + "got": "^6.7.1", + "registry-auth-token": "^3.0.1", + "registry-url": "^3.0.3", + "semver": "^5.1.0" + } + }, + "parse-glob": { + "version": "3.0.4", + "bundled": true, + "requires": { + "glob-base": "^0.3.0", + "is-dotfile": "^1.0.0", + "is-extglob": "^1.0.0", + "is-glob": "^2.0.0" + } + }, + "parse-json": { + "version": "2.2.0", + "bundled": true, + "requires": { + "error-ex": "^1.2.0" + } + }, + "parse-ms": { + "version": "0.1.2", + "bundled": true + }, + "path-exists": { + "version": "3.0.0", + "bundled": true + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true + }, + "path-is-inside": { + "version": "1.0.2", + "bundled": true + }, + "path-key": { + "version": "2.0.1", + "bundled": true + }, + "path-parse": { + "version": "1.0.5", + "bundled": true + }, + "path-type": { + "version": "2.0.0", + "bundled": true, + "requires": { + "pify": "^2.0.0" + } + }, + "performance-now": { + "version": "0.2.0", + "bundled": true + }, + "pify": { + "version": "2.3.0", + "bundled": true + }, + "pinkie": { + "version": "1.0.0", + "bundled": true + }, + "pinkie-promise": { + "version": "1.0.0", + "bundled": true, + "requires": { + "pinkie": "^1.0.0" + } + }, + "pkg-conf": { + "version": "2.1.0", + "bundled": true, + "requires": { + "find-up": "^2.0.0", + "load-json-file": "^4.0.0" + }, + "dependencies": { + "load-json-file": { + "version": "4.0.0", + "bundled": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" + } + }, + "parse-json": { + "version": "4.0.0", + "bundled": true, + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + }, + "pify": { + "version": "3.0.0", + "bundled": true + } + } + }, + "pkg-dir": { + "version": "2.0.0", + "bundled": true, + "requires": { + "find-up": "^2.1.0" + } + }, + "plur": { + "version": "2.1.2", + "bundled": true, + "requires": { + "irregular-plurals": "^1.0.0" + } + }, + "pluralize": { + "version": "7.0.0", + "bundled": true + }, + "prelude-ls": { + "version": "1.1.2", + "bundled": true + }, + "prepend-http": { + "version": "1.0.4", + "bundled": true + }, + "preserve": { + "version": "0.2.0", + "bundled": true + }, + "pretty-ms": { + "version": "3.2.0", + "bundled": true, + "requires": { + "parse-ms": "^1.0.0" + }, + "dependencies": { + "parse-ms": { + "version": "1.0.1", + "bundled": true + } + } + }, + "private": { + "version": "0.1.8", + "bundled": true + }, + "process-nextick-args": { + "version": "2.0.0", + "bundled": true + }, + "progress": { + "version": "2.0.0", + "bundled": true + }, + "pseudomap": { + "version": "1.0.2", + "bundled": true + }, + "punycode": { + "version": "1.4.1", + "bundled": true + }, + "qs": { + "version": "6.4.0", + "bundled": true + }, + "randomatic": { + "version": "3.0.0", + "bundled": true, + "requires": { + "is-number": "^4.0.0", + "kind-of": "^6.0.0", + "math-random": "^1.0.1" + }, + "dependencies": { + "is-number": { + "version": "4.0.0", + "bundled": true + }, + "kind-of": { + "version": "6.0.2", + "bundled": true + } + } + }, + "rc": { + "version": "1.2.5", + "bundled": true, + "requires": { + "deep-extend": "~0.4.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + } + }, + "read-pkg": { + "version": "2.0.0", + "bundled": true, + "requires": { + "load-json-file": "^2.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^2.0.0" + } + }, + "read-pkg-up": { + "version": "2.0.0", + "bundled": true, + "requires": { + "find-up": "^2.0.0", + "read-pkg": "^2.0.0" + } + }, + "readable-stream": { + "version": "2.3.4", + "bundled": 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.0.3", + "util-deprecate": "~1.0.1" + } + }, + "readdirp": { + "version": "2.1.0", + "bundled": true, + "requires": { + "graceful-fs": "^4.1.2", + "minimatch": "^3.0.2", + "readable-stream": "^2.0.2", + "set-immediate-shim": "^1.0.1" + } + }, + "redent": { + "version": "1.0.0", + "bundled": true, + "requires": { + "indent-string": "^2.1.0", + "strip-indent": "^1.0.1" + }, + "dependencies": { + "indent-string": { + "version": "2.1.0", + "bundled": true, + "requires": { + "repeating": "^2.0.0" + } + } + } + }, + "regenerate": { + "version": "1.4.0", + "bundled": true + }, + "regenerator-runtime": { + "version": "0.11.1", + "bundled": true + }, + "regex-cache": { + "version": "0.4.4", + "bundled": true, + "requires": { + "is-equal-shallow": "^0.1.3" + } + }, + "regexpp": { + "version": "1.1.0", + "bundled": true + }, + "regexpu-core": { + "version": "2.0.0", + "bundled": true, + "requires": { + "regenerate": "^1.2.1", + "regjsgen": "^0.2.0", + "regjsparser": "^0.1.4" + } + }, + "registry-auth-token": { + "version": "3.3.2", + "bundled": true, + "requires": { + "rc": "^1.1.6", + "safe-buffer": "^5.0.1" + } + }, + "registry-url": { + "version": "3.1.0", + "bundled": true, + "requires": { + "rc": "^1.0.1" + } + }, + "regjsgen": { + "version": "0.2.0", + "bundled": true + }, + "regjsparser": { + "version": "0.1.5", + "bundled": true, + "requires": { + "jsesc": "~0.5.0" + } + }, + "release-zalgo": { + "version": "1.0.0", + "bundled": true, + "requires": { + "es6-error": "^4.0.1" + } + }, + "remove-trailing-separator": { + "version": "1.1.0", + "bundled": true + }, + "repeat-element": { + "version": "1.1.2", + "bundled": true + }, + "repeat-string": { + "version": "1.6.1", + "bundled": true + }, + "repeating": { + "version": "2.0.1", + "bundled": true, + "requires": { + "is-finite": "^1.0.0" + } + }, + "request": { + "version": "2.81.0", + "bundled": true, + "requires": { + "aws-sign2": "~0.6.0", + "aws4": "^1.2.1", + "caseless": "~0.12.0", + "combined-stream": "~1.0.5", + "extend": "~3.0.0", + "forever-agent": "~0.6.1", + "form-data": "~2.1.1", + "har-validator": "~4.2.1", + "hawk": "~3.1.3", + "http-signature": "~1.1.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.7", + "oauth-sign": "~0.8.1", + "performance-now": "^0.2.0", + "qs": "~6.4.0", + "safe-buffer": "^5.0.1", + "stringstream": "~0.0.4", + "tough-cookie": "~2.3.0", + "tunnel-agent": "^0.6.0", + "uuid": "^3.0.0" + } + }, + "require-precompiled": { + "version": "0.1.0", + "bundled": true + }, + "require-uncached": { + "version": "1.0.3", + "bundled": true, + "requires": { + "caller-path": "^0.1.0", + "resolve-from": "^1.0.0" + }, + "dependencies": { + "resolve-from": { + "version": "1.0.1", + "bundled": true + } + } + }, + "requizzle": { + "version": "0.2.1", + "bundled": true, + "requires": { + "underscore": "~1.6.0" + }, + "dependencies": { + "underscore": { + "version": "1.6.0", + "bundled": true + } + } + }, + "resolve": { + "version": "1.6.0", + "bundled": true, + "requires": { + "path-parse": "^1.0.5" + } + }, + "resolve-cwd": { + "version": "2.0.0", + "bundled": true, + "requires": { + "resolve-from": "^3.0.0" + } + }, + "resolve-from": { + "version": "3.0.0", + "bundled": true + }, + "restore-cursor": { + "version": "2.0.0", + "bundled": true, + "requires": { + "onetime": "^2.0.0", + "signal-exit": "^3.0.2" + } + }, + "rimraf": { + "version": "2.6.2", + "bundled": true, + "requires": { + "glob": "^7.0.5" + } + }, + "run-async": { + "version": "2.3.0", + "bundled": true, + "requires": { + "is-promise": "^2.1.0" + } + }, + "rx-lite": { + "version": "4.0.8", + "bundled": true + }, + "rx-lite-aggregates": { + "version": "4.0.8", + "bundled": true, + "requires": { + "rx-lite": "*" + } + }, + "safe-buffer": { + "version": "5.1.1", + "bundled": true + }, + "safer-buffer": { + "version": "2.1.2", + "bundled": true + }, + "sax": { + "version": "1.2.4", + "bundled": true + }, + "semver": { + "version": "5.5.0", + "bundled": true + }, + "semver-diff": { + "version": "2.1.0", + "bundled": true, + "requires": { + "semver": "^5.0.3" + } + }, + "serialize-error": { + "version": "2.1.0", + "bundled": true + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true + }, + "set-immediate-shim": { + "version": "1.0.1", + "bundled": true + }, + "shebang-command": { + "version": "1.2.0", + "bundled": true, + "requires": { + "shebang-regex": "^1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "bundled": true + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true + }, + "slash": { + "version": "1.0.0", + "bundled": true + }, + "slice-ansi": { + "version": "1.0.0", + "bundled": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0" + } + }, + "slide": { + "version": "1.1.6", + "bundled": true + }, + "sntp": { + "version": "1.0.9", + "bundled": true, + "requires": { + "hoek": "2.x.x" + } + }, + "sort-keys": { + "version": "2.0.0", + "bundled": true, + "requires": { + "is-plain-obj": "^1.0.0" + } + }, + "source-map": { + "version": "0.5.7", + "bundled": true + }, + "source-map-support": { + "version": "0.5.6", + "bundled": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "bundled": true + } + } + }, + "spdx-correct": { + "version": "3.0.0", + "bundled": true, + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.1.0", + "bundled": true + }, + "spdx-expression-parse": { + "version": "3.0.0", + "bundled": true, + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.0", + "bundled": true + }, + "sprintf-js": { + "version": "1.0.3", + "bundled": true + }, + "sshpk": { + "version": "1.14.1", + "bundled": true, + "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", + "tweetnacl": "~0.14.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true + } + } + }, + "stack-trace": { + "version": "0.0.10", + "bundled": true + }, + "stack-utils": { + "version": "1.0.1", + "bundled": true + }, + "string-width": { + "version": "2.1.1", + "bundled": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + } + }, + "string_decoder": { + "version": "1.0.3", + "bundled": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "stringstream": { + "version": "0.0.6", + "bundled": true + }, + "strip-ansi": { + "version": "4.0.0", + "bundled": true, + "requires": { + "ansi-regex": "^3.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "bundled": true + } + } + }, + "strip-bom": { + "version": "3.0.0", + "bundled": true + }, + "strip-bom-buf": { + "version": "1.0.0", + "bundled": true, + "requires": { + "is-utf8": "^0.2.1" + } + }, + "strip-eof": { + "version": "1.0.0", + "bundled": true + }, + "strip-indent": { + "version": "1.0.1", + "bundled": true, + "requires": { + "get-stdin": "^4.0.1" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "bundled": true + }, + "supertap": { + "version": "1.0.0", + "bundled": true, + "requires": { + "arrify": "^1.0.1", + "indent-string": "^3.2.0", + "js-yaml": "^3.10.0", + "serialize-error": "^2.1.0", + "strip-ansi": "^4.0.0" + } + }, + "supports-color": { + "version": "5.4.0", + "bundled": true, + "requires": { + "has-flag": "^3.0.0" + }, + "dependencies": { + "has-flag": { + "version": "3.0.0", + "bundled": true + } + } + }, + "symbol-observable": { + "version": "1.2.0", + "bundled": true + }, + "table": { + "version": "4.0.2", + "bundled": true, + "requires": { + "ajv": "^5.2.3", + "ajv-keywords": "^2.1.0", + "chalk": "^2.1.0", + "lodash": "^4.17.4", + "slice-ansi": "1.0.0", + "string-width": "^2.1.1" + } + }, + "taffydb": { + "version": "2.6.2", + "bundled": true + }, + "tar": { + "version": "2.2.1", + "bundled": true, + "requires": { + "block-stream": "*", + "fstream": "^1.0.2", + "inherits": "2" + } + }, + "term-size": { + "version": "1.2.0", + "bundled": true, + "requires": { + "execa": "^0.7.0" + } + }, + "text-table": { + "version": "0.2.0", + "bundled": true + }, + "through": { + "version": "2.3.8", + "bundled": true + }, + "through2": { + "version": "2.0.3", + "bundled": true, + "requires": { + "readable-stream": "^2.1.5", + "xtend": "~4.0.1" + } + }, + "time-zone": { + "version": "1.0.0", + "bundled": true + }, + "timed-out": { + "version": "4.0.1", + "bundled": true + }, + "tmp": { + "version": "0.0.33", + "bundled": true, + "requires": { + "os-tmpdir": "~1.0.2" + } + }, + "to-fast-properties": { + "version": "1.0.3", + "bundled": true + }, + "tough-cookie": { + "version": "2.3.4", + "bundled": true, + "requires": { + "punycode": "^1.4.1" + } + }, + "trim-newlines": { + "version": "1.0.0", + "bundled": true + }, + "trim-off-newlines": { + "version": "1.0.1", + "bundled": true + }, + "trim-right": { + "version": "1.0.1", + "bundled": true + }, + "tunnel-agent": { + "version": "0.6.0", + "bundled": true, + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "bundled": true, + "optional": true + }, + "type-check": { + "version": "0.3.2", + "bundled": true, + "requires": { + "prelude-ls": "~1.1.2" + } + }, + "typedarray": { + "version": "0.0.6", + "bundled": true + }, + "uid2": { + "version": "0.0.3", + "bundled": true + }, + "underscore": { + "version": "1.8.3", + "bundled": true + }, + "underscore-contrib": { + "version": "0.3.0", + "bundled": true, + "requires": { + "underscore": "1.6.0" + }, + "dependencies": { + "underscore": { + "version": "1.6.0", + "bundled": true + } + } + }, + "unique-string": { + "version": "1.0.0", + "bundled": true, + "requires": { + "crypto-random-string": "^1.0.0" + } + }, + "unique-temp-dir": { + "version": "1.0.0", + "bundled": true, + "requires": { + "mkdirp": "^0.5.1", + "os-tmpdir": "^1.0.1", + "uid2": "0.0.3" + } + }, + "unzip-response": { + "version": "2.0.1", + "bundled": true + }, + "update-notifier": { + "version": "2.5.0", + "bundled": true, + "requires": { + "boxen": "^1.2.1", + "chalk": "^2.0.1", + "configstore": "^3.0.0", + "import-lazy": "^2.1.0", + "is-ci": "^1.0.10", + "is-installed-globally": "^0.1.0", + "is-npm": "^1.0.0", + "latest-version": "^3.0.0", + "semver-diff": "^2.0.0", + "xdg-basedir": "^3.0.0" + } + }, + "url-parse-lax": { + "version": "1.0.0", + "bundled": true, + "requires": { + "prepend-http": "^1.0.1" + } + }, + "util-deprecate": { + "version": "1.0.2", + "bundled": true + }, + "uuid": { + "version": "3.2.1", + "bundled": true + }, + "validate-npm-package-license": { + "version": "3.0.3", + "bundled": true, + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "verror": { + "version": "1.10.0", + "bundled": true, + "requires": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true + } + } + }, + "well-known-symbols": { + "version": "1.0.0", + "bundled": true + }, + "which": { + "version": "1.3.0", + "bundled": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "wide-align": { + "version": "1.1.3", + "bundled": true, + "requires": { + "string-width": "^1.0.2 || 2" + } + }, + "widest-line": { + "version": "2.0.0", + "bundled": true, + "requires": { + "string-width": "^2.1.1" + } + }, + "winston": { + "version": "2.4.0", + "bundled": true, + "requires": { + "async": "~1.0.0", + "colors": "1.0.x", + "cycle": "1.0.x", + "eyes": "0.1.x", + "isstream": "0.1.x", + "stack-trace": "0.0.x" + } + }, + "wordwrap": { + "version": "1.0.0", + "bundled": true + }, + "wrappy": { + "version": "1.0.2", + "bundled": true + }, + "write": { + "version": "0.2.1", + "bundled": true, + "requires": { + "mkdirp": "^0.5.1" + } + }, + "write-file-atomic": { + "version": "2.3.0", + "bundled": true, + "requires": { + "graceful-fs": "^4.1.11", + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.2" + } + }, + "write-json-file": { + "version": "2.3.0", + "bundled": true, + "requires": { + "detect-indent": "^5.0.0", + "graceful-fs": "^4.1.2", + "make-dir": "^1.0.0", + "pify": "^3.0.0", + "sort-keys": "^2.0.0", + "write-file-atomic": "^2.0.0" + }, + "dependencies": { + "detect-indent": { + "version": "5.0.0", + "bundled": true + }, + "pify": { + "version": "3.0.0", + "bundled": true + } + } + }, + "write-pkg": { + "version": "3.1.0", + "bundled": true, + "requires": { + "sort-keys": "^2.0.0", + "write-json-file": "^2.2.0" + } + }, + "xdg-basedir": { + "version": "3.0.0", + "bundled": true + }, + "xml2js": { + "version": "0.4.19", + "bundled": true, + "requires": { + "sax": ">=0.6.0", + "xmlbuilder": "~9.0.1" + } + }, + "xmlbuilder": { + "version": "9.0.7", + "bundled": true + }, + "xmlcreate": { + "version": "1.0.2", + "bundled": true + }, + "xpc-connection": { + "version": "0.1.4", + "bundled": true, + "optional": true, + "requires": { + "nan": "^2.0.5" + } + }, + "xtend": { + "version": "4.0.1", + "bundled": true + }, + "yallist": { + "version": "2.1.2", + "bundled": true + } + } + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "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=" + }, + "minipass": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.3.3.tgz", + "integrity": "sha512-/jAn9/tEX4gnpyRATxgHEOV6xbcyxgT7iUnxo9Y3+OB0zX00TgKIv/2FZCf5brBbICcwbLqVv2ImjvWWrQMSYw==", + "requires": { + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" + } + }, + "minizlib": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.1.0.tgz", + "integrity": "sha512-4T6Ur/GctZ27nHfpt9THOdRZNgyJ9FZchYO1ceg5S8Q3DNLCKYy44nCZzgCJgcvx2UM8czmqak5BCxJMrq37lA==", + "optional": true, + "requires": { + "minipass": "^2.2.1" + } + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "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=" + } + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "optional": true + }, + "nan": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.10.0.tgz", + "integrity": "sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA==" + }, + "needle": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/needle/-/needle-2.2.1.tgz", + "integrity": "sha512-t/ZswCM9JTWjAdXS9VpvqhI2Ct2sL2MdY4fUXqGJaGBk13ge99ObqRksRTbBE56K+wxUXwwfZYOuZHifFW9q+Q==", + "optional": true, + "requires": { + "debug": "^2.1.2", + "iconv-lite": "^0.4.4", + "sax": "^1.2.4" + } + }, + "node-abi": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.4.1.tgz", + "integrity": "sha512-pUlswqpHQ7zGPI9lGjZ4XDNIEUDbHxsltfIRb7dTnYdhgHWHOcB0MLZKLoCz6UMcGzSPG5wGl1HODZVQAUsH6w==", + "requires": { + "semver": "^5.4.1" + } + }, + "node-hid": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/node-hid/-/node-hid-0.5.7.tgz", + "integrity": "sha512-dwwpOetL2+MGYgivbO22ML+45ieCGbueWv1rYxRgBoEc2QMp6UF6ZucEkYts1IA3YPWJNkmpGh6dqQ85n19szw==", + "requires": { + "bindings": "^1.3.0", + "nan": "^2.6.2", + "prebuild-install": "^2.2.2" + } + }, + "node-pre-gyp": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.10.0.tgz", + "integrity": "sha512-G7kEonQLRbcA/mOoFoxvlMrw6Q6dPf92+t/l0DFSMuSlDoWaI9JWIyPwK0jyE1bph//CUEL65/Fz1m2vJbmjQQ==", + "optional": true, + "requires": { + "detect-libc": "^1.0.2", + "mkdirp": "^0.5.1", + "needle": "^2.2.0", + "nopt": "^4.0.1", + "npm-packlist": "^1.1.6", + "npmlog": "^4.0.2", + "rc": "^1.1.7", + "rimraf": "^2.6.1", + "semver": "^5.3.0", + "tar": "^4" + } + }, + "noop-logger": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/noop-logger/-/noop-logger-0.1.1.tgz", + "integrity": "sha1-lKKxYzxPExdVMAfYlm/Q6EG2pMI=" + }, + "nopt": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.1.tgz", + "integrity": "sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=", + "optional": true, + "requires": { + "abbrev": "1", + "osenv": "^0.1.4" + } + }, + "npm-bundled": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.0.3.tgz", + "integrity": "sha512-ByQ3oJ/5ETLyglU2+8dBObvhfWXX8dtPZDMePCahptliFX2iIuhyEszyFk401PZUNQH20vvdW5MLjJxkwU80Ow==", + "optional": true + }, + "npm-packlist": { + "version": "1.1.10", + "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.1.10.tgz", + "integrity": "sha512-AQC0Dyhzn4EiYEfIUjCdMl0JJ61I2ER9ukf/sLxJUcZHfo+VyEfz2rMJgLZSS1v30OxPQe1cN0LZA1xbcaVfWA==", + "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==", + "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=" + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "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=" + }, + "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=", + "optional": true + }, + "osenv": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", + "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", + "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=", + "optional": true + }, + "prebuild-install": { + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-2.5.3.tgz", + "integrity": "sha512-/rI36cN2g7vDQnKWN8Uzupi++KjyqS9iS+/fpwG4Ea8d0Pip0PQ5bshUNzVwt+/D2MRfhVAplYMMvWLqWrCF/g==", + "requires": { + "detect-libc": "^1.0.3", + "expand-template": "^1.0.2", + "github-from-package": "0.0.0", + "minimist": "^1.2.0", + "mkdirp": "^0.5.1", + "node-abi": "^2.2.0", + "noop-logger": "^0.1.1", + "npmlog": "^4.0.1", + "os-homedir": "^1.0.1", + "pump": "^2.0.1", + "rc": "^1.1.6", + "simple-get": "^2.7.0", + "tar-fs": "^1.13.0", + "tunnel-agent": "^0.6.0", + "which-pm-runs": "^1.0.0" + } + }, + "process-nextick-args": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==" + }, + "pump": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", + "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "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.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "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.6.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", + "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", + "optional": true, + "requires": { + "glob": "^7.0.5" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "optional": true + }, + "sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", + "optional": true + }, + "semver": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", + "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==" + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" + }, + "simple-concat": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.0.tgz", + "integrity": "sha1-c0TLuLbib7J9ZrL8hvn21Zl1IcY=" + }, + "simple-get": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-2.8.1.tgz", + "integrity": "sha512-lSSHRSw3mQNUGPAYRqo7xy9dhKmxFXIjLjp4KHpf99GEH2VH7C3AM+Qfx6du6jhfUi6Vm7XnbEVEf7Wb6N8jRw==", + "requires": { + "decompress-response": "^3.3.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "stack-trace": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", + "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=" + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "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==", + "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=", + "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=" + }, + "tar": { + "version": "4.4.4", + "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.4.tgz", + "integrity": "sha512-mq9ixIYfNF9SK0IS/h2HKMu8Q2iaCuhDDsZhdEag/FHv8fOaYld4vN7ouMgcSSt5WKZzPs8atclTcJm36OTh4w==", + "optional": true, + "requires": { + "chownr": "^1.0.1", + "fs-minipass": "^1.2.5", + "minipass": "^2.3.3", + "minizlib": "^1.1.0", + "mkdirp": "^0.5.0", + "safe-buffer": "^5.1.2", + "yallist": "^3.0.2" + } + }, + "tar-fs": { + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-1.16.2.tgz", + "integrity": "sha512-LdknWjPEiZC1nOBwhv0JBzfJBGPJar08dZg2rwZe0ZTLQoRGEzgrl7vF3qUEkCHpI/wN9e7RyCuDhMsJUCLPPQ==", + "requires": { + "chownr": "^1.0.1", + "mkdirp": "^0.5.1", + "pump": "^1.0.0", + "tar-stream": "^1.1.2" + }, + "dependencies": { + "pump": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/pump/-/pump-1.0.3.tgz", + "integrity": "sha512-8k0JupWme55+9tCVE+FS5ULT3K6AbgqrGa58lTT49RpyfwwcGedHqaC5LlQNdEAumn/wFsu6aPwkuPMioy8kqw==", + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + } + } + }, + "tar-stream": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.6.1.tgz", + "integrity": "sha512-IFLM5wp3QrJODQFPm6/to3LJZrONdBY/otxcvDIQzu217zKye6yVR3hhi9lAjrC2Z+m/j5oDxMPb1qcd8cIvpA==", + "requires": { + "bl": "^1.0.0", + "buffer-alloc": "^1.1.0", + "end-of-stream": "^1.0.0", + "fs-constants": "^1.0.0", + "readable-stream": "^2.3.0", + "to-buffer": "^1.1.0", + "xtend": "^4.0.0" + } + }, + "to-buffer": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.1.1.tgz", + "integrity": "sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg==" + }, + "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" + } + }, + "usb": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/usb/-/usb-1.3.2.tgz", + "integrity": "sha512-FhyDAkccL2ycJw3SDEwuMVYwrwo6+wJOqeImwBcZwrK0fIPzg9eWR3vFWDzXLOtMq/06mXyQb122UgbsE/Qhcg==", + "optional": true, + "requires": { + "nan": "^2.8.0", + "node-pre-gyp": "^0.10.0" + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "which-pm-runs": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/which-pm-runs/-/which-pm-runs-1.0.0.tgz", + "integrity": "sha1-Zws6+8VS4LVd9rd4DKdGFfI60cs=" + }, + "wide-align": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", + "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", + "requires": { + "string-width": "^1.0.2 || 2" + } + }, + "winston": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/winston/-/winston-2.4.2.tgz", + "integrity": "sha512-4S/Ad4ZfSNl8OccCLxnJmNISWcm2joa6Q0YGDxlxMzH0fgSwWsjMt+SmlNwCqdpaPg3ev1HKkMBsIiXeSUwpbA==", + "requires": { + "async": "~1.0.0", + "colors": "1.0.x", + "cycle": "1.0.x", + "eyes": "0.1.x", + "isstream": "0.1.x", + "stack-trace": "0.0.x" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" + }, + "yallist": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.2.tgz", + "integrity": "sha1-hFK0u36Dx8GI2AQcGoN8dz1ti7k=" + } + } +} diff --git a/examples/package.json b/examples/package.json index 3b859a42..32f822bf 100644 --- a/examples/package.json +++ b/examples/package.json @@ -3,13 +3,8 @@ "main": "index.js", "license": "MIT", "dependencies": { - "arsdk-xml": "git://github.com/Parrot-Developers/arsdk-xml", - "case": "^1.5.4", + "minidrone-js": "file:../", "dualshock-controller": "^1.1.1", - "events": "^1.1.1", - "noble": "git://github.com/jacobrosenthal/noble.git#highsierra", - "node-gyp": "^3.6.2", - "winston": "^2.4.0", - "xml2js": "^0.4.19" + "winston": "^2.4.0" } } diff --git a/examples/toggleAutoTakeOff.js b/examples/toggleAutoTakeOff.js index 2e4cbef7..600083a0 100644 --- a/examples/toggleAutoTakeOff.js +++ b/examples/toggleAutoTakeOff.js @@ -1,12 +1,12 @@ -const { DroneConnection, CommandParser, WifiConnector, BLEConnector } = require('../src'); +const { CommandParser, WifiConnector } = require('minidrone-js'); const Logger = require('winston'); Logger.level = 'debug'; const parser = new CommandParser(); -const connector = new WifiConnector(); -const drone = new DroneConnection(connector); -connector.connect(); +const drone = new WifiConnector(); + +drone.connect(); const autoTakeOffOn = parser.getCommand('minidrone', 'Piloting', 'AutoTakeOffMode', { state: 1 }); const autoTakeOffOff = parser.getCommand('minidrone', 'Piloting', 'AutoTakeOffMode', { state: 0 }); @@ -18,13 +18,14 @@ function sleep(ms) { drone.on('connected', async () => { await sleep(200); - await drone.runCommand(allState); - await drone.runCommand(autoTakeOffOn); + await drone.sendCommand(allState); + + await drone.sendCommand(autoTakeOffOn); await sleep(2000); - await drone.runCommand(autoTakeOffOff); + await drone.sendCommand(autoTakeOffOff); Logger.debug('values: '); @@ -32,5 +33,10 @@ drone.on('connected', async () => { Logger.debug(command.toString(true)); } + while (true) { + await sleep(2000); + + drone.sendCommand(allState); + } // process.exit(); }); diff --git a/examples/wifi/directFlight.js b/examples/wifi/directFlight.js new file mode 100644 index 00000000..0797254a --- /dev/null +++ b/examples/wifi/directFlight.js @@ -0,0 +1,84 @@ +const dualShock = require('dualshock-controller'); +const { WifiConnector, CommandParser } = require('minidrone-js'); + +const controller = dualShock({ config: 'dualShock4-alternate-driver' }); +const parser = new CommandParser(); +const drone = new WifiConnector(); +const takeoff = parser.getCommand('minidrone', 'Piloting', 'TakeOff'); +const landing = parser.getCommand('minidrone', 'Piloting', 'Landing'); +const flatTrim = parser.getCommand('minidrone', 'Piloting', 'FlatTrim'); +const takePicture = parser.getCommand('minidrone', 'MediaRecord', 'PictureV2'); +const fireGun = parser.getCommand('minidrone', 'UsbAccessory', 'GunControl', { id: 0, action: 'FIRE' }); +const clawOpen = parser.getCommand('minidrone', 'UsbAccessory', 'ClawControl', { id: 0, action: 'OPEN' }); +const clawClose = parser.getCommand('minidrone', 'UsbAccessory', 'ClawControl', { id: 0, action: 'CLOSE' }); +const allState = parser.getCommand('common', 'Common', 'AllStates'); +const autoTakeOff = parser.getCommand('minidrone', 'Piloting', 'AutoTakeOffMode', { state: 1 }); + +let startTime; +let flightParams = { + roll: 0, pitch: 0, yaw: 0, gaz: 0, flag: true, +}; + +function setFlightParams(data) { + flightParams = Object.assign({}, flightParams, data); +} + + +function writeFlightParams() { + if (typeof startTime === 'undefined') { + startTime = Date.now(); + } + + const params = Object.assign({}, flightParams, { + timestamp: Date.now() - startTime, + }); + + const command = parser.getCommand('minidrone', 'Piloting', 'PCMD', params); + + drone.sendCommand(command); +} + +function joyToFlightParam(value) { + const deadZone = 10; // both ways + const center = 255 / 2; + + if (value > center - deadZone && value < center + deadZone) { + return 0; + } + + return (value / center) * 100 - 100; +} + +drone.on('connected', () => { + console.log('Registering controller'); + + setInterval(writeFlightParams, 100); // Event loop + + // Bind controls + controller.on('connected', () => console.log('Controller connected!')); + controller.on('disconnecting', () => { + console.log('Controller disconnected!'); + setFlightParams({ + roll: 0, pitch: 0, yaw: 0, gaz: -10, + }); + }); + + controller.on('circle:press', () => { + console.log(Object.values(drone._sensorStore).map(x => x.toString()).join('\n')); + drone.sendCommand(allState); + }); + controller.on('x:press', () => drone.sendCommand(takeoff)); + controller.on('square:press', () => drone.sendCommand(landing)); + controller.on('triangle:press', () => drone.sendCommand(autoTakeOff)); + + controller.on('right:move', data => setFlightParams({ + yaw: joyToFlightParam(data.x), + gaz: -joyToFlightParam(data.y), + })); + controller.on('left:move', data => setFlightParams({ + roll: joyToFlightParam(data.x), + pitch: -joyToFlightParam(data.y), + })); +}); + +drone.connect(); diff --git a/package-lock.json b/package-lock.json index 2f102220..ac0ca5e7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -925,6 +925,12 @@ "integrity": "sha1-RqoXUftqL5PuXmibsQh9SxTGwgU=", "dev": true }, + "bindings": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.2.1.tgz", + "integrity": "sha1-FK1hE4EtLTfXLme0ystLtyZQXxE=", + "dev": true + }, "block-stream": { "version": "0.0.9", "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz", @@ -1565,6 +1571,11 @@ "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=", "optional": true }, + "dgram": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dgram/-/dgram-1.0.1.tgz", + "integrity": "sha1-N/OyAPgDOl/3WTAwicgc42G2UcM=" + }, "doctrine": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", @@ -2030,14 +2041,12 @@ "balanced-match": { "version": "1.0.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, "dev": true, - "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -2052,20 +2061,17 @@ "code-point-at": { "version": "1.1.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "concat-map": { "version": "0.0.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "console-control-strings": { "version": "1.1.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "core-util-is": { "version": "1.0.2", @@ -2182,8 +2188,7 @@ "inherits": { "version": "2.0.3", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "ini": { "version": "1.3.5", @@ -2195,7 +2200,6 @@ "version": "1.0.0", "bundled": true, "dev": true, - "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -2210,7 +2214,6 @@ "version": "3.0.4", "bundled": true, "dev": true, - "optional": true, "requires": { "brace-expansion": "^1.1.7" } @@ -2218,14 +2221,12 @@ "minimist": { "version": "0.0.8", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "minipass": { "version": "2.2.4", "bundled": true, "dev": true, - "optional": true, "requires": { "safe-buffer": "^5.1.1", "yallist": "^3.0.0" @@ -2244,7 +2245,6 @@ "version": "0.5.1", "bundled": true, "dev": true, - "optional": true, "requires": { "minimist": "0.0.8" } @@ -2332,8 +2332,7 @@ "number-is-nan": { "version": "1.0.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "object-assign": { "version": "4.1.1", @@ -2345,7 +2344,6 @@ "version": "1.4.0", "bundled": true, "dev": true, - "optional": true, "requires": { "wrappy": "1" } @@ -2467,7 +2465,6 @@ "version": "1.0.2", "bundled": true, "dev": true, - "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -3582,6 +3579,24 @@ "integrity": "sha1-givM1l4RfFFPqxdrJZRdVBAKA8M=", "dev": true }, + "mdns": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/mdns/-/mdns-2.4.0.tgz", + "integrity": "sha512-t58BWOyagGpATg8LlALpnqjfT7VHBq6/HCLfU/SK0Ox+enx3Cut7voWB9DPwjrdoccql6Z6ZY1rwuBX93t0Vpw==", + "dev": true, + "requires": { + "bindings": "~1.2.1", + "nan": "^2.10.0" + }, + "dependencies": { + "nan": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.10.0.tgz", + "integrity": "sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA==", + "dev": true + } + } + }, "meow": { "version": "3.7.0", "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", @@ -3799,6 +3814,11 @@ "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", "dev": true }, + "net": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/net/-/net-1.0.2.tgz", + "integrity": "sha1-0XV+yaf7I3HYPPR1XOPifhCCk4g=" + }, "noble": { "version": "git://github.com/jacobrosenthal/noble.git#15179890f7dd39ed8b40c0c5b11a5538498d03fd", "from": "git://github.com/jacobrosenthal/noble.git#highsierra", diff --git a/src/connectors/BaseConnector.js b/src/connectors/BaseConnector.js index 08a9501c..1f8a3e8d 100644 --- a/src/connectors/BaseConnector.js +++ b/src/connectors/BaseConnector.js @@ -17,7 +17,7 @@ class BaseConnector extends EventEmitter { super(); this._stepStore = {}; - this.parser = new CommandParser(); + this._parser = new CommandParser(); this._commandCallback = {}; this._sensorStore = {}; @@ -25,6 +25,14 @@ class BaseConnector extends EventEmitter { this.on('incoming', command => Logger.debug(`RECV ${command.bufferType}:`, command.toString())); } + /** + * Accessor for getting the {@link CommandParser} instance + * @returns {CommandParser} - {@link CommandParser} instance + */ + get parser() { + return this._parser; + } + /** * used to count the drone command steps * @param {string} id - Step store id @@ -61,7 +69,7 @@ class BaseConnector extends EventEmitter { } // For if the command times out - const timeout = setTimeout(reject, 10 * 1000, new Error('Command timed out after 10 seconds')); + const timeout = setTimeout(reject, 5 * 1000, new Error('Command timed out after 5 seconds')); const accept = () => { clearTimeout(timeout); @@ -107,14 +115,16 @@ class BaseConnector extends EventEmitter { let command = this._sensorStore[token]; if (command) { - command = command.copy(); + return command.clone(); } - - return command; } setSensor(command) { - this._sensorStore[command.getToken()] = command; + const token = command.getToken(); + + this._sensorStore[token] = command; + + Logger.debug('EMIT: sensor:' + token); /** * Fires when a new sensor reading has been received diff --git a/src/connectors/WifiConnector.js b/src/connectors/WifiConnector.js index d3e0479f..9e486c7e 100644 --- a/src/connectors/WifiConnector.js +++ b/src/connectors/WifiConnector.js @@ -218,7 +218,7 @@ class WifiConnector extends BaseConnector { * @param {DroneCommand} command - Command to send * @returns {Promise} - Resolves when the command has been acknowledged or rejects if it times out */ - sendCommand(command) { + async sendCommand(command) { const commandBuffer = command.toBuffer(); const buffer = Buffer.concat([new Buffer(7), commandBuffer]); const bufferId = command.bufferId; @@ -231,7 +231,15 @@ class WifiConnector extends BaseConnector { this.write(buffer, command.sendCharacteristicUuid); - return this._setAckCallback(command, packetId); + try { + return await this._setAckCallback(command, packetId); + } catch (e) { + if (e.message.startsWith('Command timed out')) { + this.disconnect(); + } + + throw e; + } } _handleIncoming(buffer) { @@ -282,7 +290,7 @@ class WifiConnector extends BaseConnector { * @returns {string} - stream uri */ get rtspStreamUri() { - return `rtsp://${this.ip}/media/stream2`; + return 'rtsp://192.168.99.1/media/stream2'; } } From b332e2992c5ece76cc579a227b1a3fdcf9b47e2a Mon Sep 17 00:00:00 2001 From: Bas Date: Tue, 12 Jun 2018 16:49:19 +0200 Subject: [PATCH 09/17] rm test-wifi.js --- test-wifi.js | 54 ---------------------------------------------------- 1 file changed, 54 deletions(-) delete mode 100644 test-wifi.js diff --git a/test-wifi.js b/test-wifi.js deleted file mode 100644 index 0ba95326..00000000 --- a/test-wifi.js +++ /dev/null @@ -1,54 +0,0 @@ -const mdns = require('mdns'); -const Logger = require('winston'); -const net = require('net'); - -Logger.level = 'debug'; - -let mambo; - -function _onMdnsServiceDiscovery(service) { - if (service.type.name.startsWith('arsdk-') && service.type.protocol === 'udp') { - browser.stop(); - - Logger.info('Found service ' + service.type.toString()); - - mambo = service; - console.log(service); - - const ip = service.addresses[0]; - const port = service.port; - - const config = { - 'd2c_port': 43210, - 'controller_type': 'minidrone-js', - 'controller_name': 'com.example.arsdkapp' - }; - - var client = new net.Socket(); - client.connect(port, ip, function() { - console.log('Connected'); - console.log('Sending: ' + JSON.stringify(config)); - client.write(JSON.stringify(config)); - }); - - client.on('data', function(data) { - console.log('Received: ' + data); - client.destroy(); // kill client after server's response - }); - - client.on('close', function() { - console.log('Connection closed'); - }); - } -} - -var sequence = [ - mdns.rst.DNSServiceResolve() - , mdns.rst.DNSServiceGetAddrInfo({ families: [4] }), -]; - -let browser = mdns.createBrowser(mdns.udp('_arsdk-090b'), { resolverSequence: sequence }); // createBrowser(mdns.udp('arsdk-090b')); - -browser.on('serviceUp', _onMdnsServiceDiscovery); - -browser.start(); From 234837a8de6eeee7cb6d40591665989f517252c2 Mon Sep 17 00:00:00 2001 From: Bas Date: Wed, 22 Aug 2018 10:53:11 +0200 Subject: [PATCH 10/17] Add Symbol.toPrimitive support --- src/DroneCommandArgument.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/DroneCommandArgument.js b/src/DroneCommandArgument.js index df9e173b..d5527dbc 100644 --- a/src/DroneCommandArgument.js +++ b/src/DroneCommandArgument.js @@ -97,6 +97,10 @@ class DroneCommandArgument { this._value = this._parseValue(value); } + [Symbol.toPrimitive]() { + return this.value; + } + /** * If it has the enum property set * @returns {boolean} - has enum From f3fd7d710c29dc9cbf272d895d5c3cf4bbba69e7 Mon Sep 17 00:00:00 2001 From: Bas Date: Wed, 22 Aug 2018 10:53:35 +0200 Subject: [PATCH 11/17] Better hasKey --- src/util/Enum.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/util/Enum.js b/src/util/Enum.js index cf28a8a6..723f435d 100644 --- a/src/util/Enum.js +++ b/src/util/Enum.js @@ -90,7 +90,7 @@ class Enum { * @returns {boolean} - key exists */ hasKey(name) { - return this.keys().includes(name); + return name in this; } /** From a3e1129b2eb281d57d0142436f3509dfe9ba256a Mon Sep 17 00:00:00 2001 From: shodan Date: Sun, 26 Nov 2023 22:01:15 +0100 Subject: [PATCH 12/17] fixes --- examples/doAFlip.js | 8 +- examples/package-lock.json | 4232 +++++++++++++++++++++++++++++++ examples/package.json | 4 +- src/CharacteristicEnums.js | 2 +- src/DroneCommand.js | 2 +- src/connectors/BLEConnector.js | 2 +- src/connectors/WifiConnector.js | 22 +- 7 files changed, 4254 insertions(+), 18 deletions(-) create mode 100644 examples/package-lock.json diff --git a/examples/doAFlip.js b/examples/doAFlip.js index 7a5f98be..885bd879 100644 --- a/examples/doAFlip.js +++ b/examples/doAFlip.js @@ -1,13 +1,15 @@ const {DroneConnection, CommandParser, BLEConnector} = require('minidrone-js'); +const {WifiConnector} = require("../src"); -const connector = new BLEConnector(); +// const connector = new BLEConnector(); +const connector = new WifiConnector(); const parser = new CommandParser(); const drone = new DroneConnection(connector); const takeoff = parser.getCommand('minidrone', 'Piloting', 'TakeOff'); const landing = parser.getCommand('minidrone', 'Piloting', 'Landing'); const backFlip = parser.getCommand('minidrone', 'Animations', 'Flip', {direction: 'back'}); -connector.connect(); +connector.connect('192.168.99.3', 44444); drone.on('connected', () => { console.log('Connected!') @@ -18,6 +20,6 @@ drone.on('connected', () => { // runCommand(takeoff); // setTimeout(runCommand, 2000, backFlip); - // setTimeout(runCommand, 2000, landing); + setTimeout(runCommand, 2000, landing); setTimeout(process.exit, 5000); }); diff --git a/examples/package-lock.json b/examples/package-lock.json new file mode 100644 index 00000000..1342eff4 --- /dev/null +++ b/examples/package-lock.json @@ -0,0 +1,4232 @@ +{ + "name": "direct-flight", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "direct-flight", + "license": "MIT", + "dependencies": { + "minidrone-js": "file:../", + "winston": "^2.4.0" + } + }, + "..": { + "version": "0.6.1", + "license": "MIT", + "dependencies": { + "@abandonware/noble": "^1.9.2-23", + "arsdk-xml": "1.0.0", + "case": "^1.5.4", + "dgram": "^1.0.1", + "events": "^3.0.0", + "net": "^1.0.2", + "node-gyp": "^10.0.0", + "resolve": "^1.6.0", + "winston": "^3.0.0", + "xml2js": "^0.6.2" + }, + "devDependencies": { + "ava": "5.3.1", + "eslint": "^8.54.0", + "jsdoc": "^4.0.2", + "mdns": "^2.4.0", + "minami-compat": "1.2.4" + } + }, + "../node_modules/@aashutoshrathi/word-wrap": { + "version": "1.2.6", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "../node_modules/@abandonware/bluetooth-hci-socket": { + "version": "0.5.3-10", + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "linux", + "android", + "freebsd", + "win32" + ], + "dependencies": { + "@mapbox/node-pre-gyp": "^1.0.10", + "debug": "^4.3.4", + "nan": "^2.17.0" + }, + "optionalDependencies": { + "usb": "^1.9.2" + } + }, + "../node_modules/@abandonware/noble": { + "version": "1.9.2-23", + "hasInstallScript": true, + "license": "MIT", + "os": [ + "darwin", + "linux", + "freebsd", + "win32" + ], + "dependencies": { + "debug": "^4.3.4", + "napi-thread-safe-callback": "^0.0.6", + "node-addon-api": "^4.3.0", + "node-gyp-build": "^4.5.0" + }, + "engines": { + "node": ">=6" + }, + "optionalDependencies": { + "@abandonware/bluetooth-hci-socket": "^0.5.3-10" + } + }, + "../node_modules/@babel/parser": { + "version": "7.23.4", + "dev": true, + "license": "MIT", + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "../node_modules/@colors/colors": { + "version": "1.6.0", + "license": "MIT", + "engines": { + "node": ">=0.1.90" + } + }, + "../node_modules/@dabh/diagnostics": { + "version": "2.0.3", + "license": "MIT", + "dependencies": { + "colorspace": "1.1.x", + "enabled": "2.0.x", + "kuler": "^2.0.0" + } + }, + "../node_modules/@eslint-community/eslint-utils": { + "version": "4.4.0", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "../node_modules/@eslint-community/regexpp": { + "version": "4.10.0", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "../node_modules/@eslint/eslintrc": { + "version": "2.1.3", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "../node_modules/@eslint/js": { + "version": "8.54.0", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "../node_modules/@humanwhocodes/config-array": { + "version": "0.11.13", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanwhocodes/object-schema": "^2.0.1", + "debug": "^4.1.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "../node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "../node_modules/@humanwhocodes/object-schema": { + "version": "2.0.1", + "dev": true, + "license": "BSD-3-Clause" + }, + "../node_modules/@isaacs/cliui": { + "version": "8.0.2", + "license": "ISC", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "../node_modules/@jsdoc/salty": { + "version": "0.2.6", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "lodash": "^4.17.21" + }, + "engines": { + "node": ">=v12.0.0" + } + }, + "../node_modules/@mapbox/node-pre-gyp": { + "version": "1.0.11", + "license": "BSD-3-Clause", + "optional": true, + "dependencies": { + "detect-libc": "^2.0.0", + "https-proxy-agent": "^5.0.0", + "make-dir": "^3.1.0", + "node-fetch": "^2.6.7", + "nopt": "^5.0.0", + "npmlog": "^5.0.1", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.11" + }, + "bin": { + "node-pre-gyp": "bin/node-pre-gyp" + } + }, + "../node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "../node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "../node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "../node_modules/@npmcli/agent": { + "version": "2.2.0", + "license": "ISC", + "dependencies": { + "agent-base": "^7.1.0", + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.1", + "lru-cache": "^10.0.1", + "socks-proxy-agent": "^8.0.1" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "../node_modules/@npmcli/agent/node_modules/agent-base": { + "version": "7.1.0", + "license": "MIT", + "dependencies": { + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "../node_modules/@npmcli/agent/node_modules/https-proxy-agent": { + "version": "7.0.2", + "license": "MIT", + "dependencies": { + "agent-base": "^7.0.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "../node_modules/@npmcli/fs": { + "version": "3.1.0", + "license": "ISC", + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "../node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=14" + } + }, + "../node_modules/@types/linkify-it": { + "version": "3.0.5", + "dev": true, + "license": "MIT" + }, + "../node_modules/@types/markdown-it": { + "version": "12.2.3", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/linkify-it": "*", + "@types/mdurl": "*" + } + }, + "../node_modules/@types/mdurl": { + "version": "1.0.5", + "dev": true, + "license": "MIT" + }, + "../node_modules/@types/triple-beam": { + "version": "1.3.5", + "license": "MIT" + }, + "../node_modules/@ungap/structured-clone": { + "version": "1.2.0", + "dev": true, + "license": "ISC" + }, + "../node_modules/abbrev": { + "version": "1.1.1", + "license": "ISC", + "optional": true + }, + "../node_modules/acorn": { + "version": "8.11.2", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "../node_modules/acorn-jsx": { + "version": "5.3.2", + "dev": true, + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "../node_modules/acorn-walk": { + "version": "8.3.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "../node_modules/agent-base": { + "version": "6.0.2", + "license": "MIT", + "optional": true, + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "../node_modules/aggregate-error": { + "version": "4.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "clean-stack": "^4.0.0", + "indent-string": "^5.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "../node_modules/ajv": { + "version": "6.12.6", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "../node_modules/ansi-regex": { + "version": "6.0.1", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "../node_modules/ansi-styles": { + "version": "6.2.1", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "../node_modules/anymatch": { + "version": "3.1.3", + "dev": true, + "license": "ISC", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "../node_modules/aproba": { + "version": "2.0.0", + "license": "ISC", + "optional": true + }, + "../node_modules/are-we-there-yet": { + "version": "2.0.0", + "license": "ISC", + "optional": true, + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">=10" + } + }, + "../node_modules/argparse": { + "version": "2.0.1", + "dev": true, + "license": "Python-2.0" + }, + "../node_modules/array-find-index": { + "version": "1.0.2", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "../node_modules/arrgv": { + "version": "1.0.2", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.0.0" + } + }, + "../node_modules/arrify": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "../node_modules/arsdk-xml": { + "version": "1.0.0" + }, + "../node_modules/async": { + "version": "3.2.5", + "license": "MIT" + }, + "../node_modules/ava": { + "version": "5.3.1", + "dev": true, + "license": "MIT", + "dependencies": { + "acorn": "^8.8.2", + "acorn-walk": "^8.2.0", + "ansi-styles": "^6.2.1", + "arrgv": "^1.0.2", + "arrify": "^3.0.0", + "callsites": "^4.0.0", + "cbor": "^8.1.0", + "chalk": "^5.2.0", + "chokidar": "^3.5.3", + "chunkd": "^2.0.1", + "ci-info": "^3.8.0", + "ci-parallel-vars": "^1.0.1", + "clean-yaml-object": "^0.1.0", + "cli-truncate": "^3.1.0", + "code-excerpt": "^4.0.0", + "common-path-prefix": "^3.0.0", + "concordance": "^5.0.4", + "currently-unhandled": "^0.4.1", + "debug": "^4.3.4", + "emittery": "^1.0.1", + "figures": "^5.0.0", + "globby": "^13.1.4", + "ignore-by-default": "^2.1.0", + "indent-string": "^5.0.0", + "is-error": "^2.2.2", + "is-plain-object": "^5.0.0", + "is-promise": "^4.0.0", + "matcher": "^5.0.0", + "mem": "^9.0.2", + "ms": "^2.1.3", + "p-event": "^5.0.1", + "p-map": "^5.5.0", + "picomatch": "^2.3.1", + "pkg-conf": "^4.0.0", + "plur": "^5.1.0", + "pretty-ms": "^8.0.0", + "resolve-cwd": "^3.0.0", + "stack-utils": "^2.0.6", + "strip-ansi": "^7.0.1", + "supertap": "^3.0.1", + "temp-dir": "^3.0.0", + "write-file-atomic": "^5.0.1", + "yargs": "^17.7.2" + }, + "bin": { + "ava": "entrypoints/cli.mjs" + }, + "engines": { + "node": ">=14.19 <15 || >=16.15 <17 || >=18" + }, + "peerDependencies": { + "@ava/typescript": "*" + }, + "peerDependenciesMeta": { + "@ava/typescript": { + "optional": true + } + } + }, + "../node_modules/balanced-match": { + "version": "1.0.2", + "license": "MIT" + }, + "../node_modules/binary-extensions": { + "version": "2.2.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "../node_modules/bindings": { + "version": "1.2.1", + "dev": true, + "license": "MIT" + }, + "../node_modules/bluebird": { + "version": "3.7.2", + "dev": true, + "license": "MIT" + }, + "../node_modules/blueimp-md5": { + "version": "2.19.0", + "dev": true, + "license": "MIT" + }, + "../node_modules/brace-expansion": { + "version": "1.1.11", + "devOptional": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "../node_modules/braces": { + "version": "3.0.2", + "dev": true, + "license": "MIT", + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "../node_modules/cacache": { + "version": "18.0.0", + "license": "ISC", + "dependencies": { + "@npmcli/fs": "^3.1.0", + "fs-minipass": "^3.0.0", + "glob": "^10.2.2", + "lru-cache": "^10.0.1", + "minipass": "^7.0.3", + "minipass-collect": "^1.0.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "p-map": "^4.0.0", + "ssri": "^10.0.0", + "tar": "^6.1.11", + "unique-filename": "^3.0.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "../node_modules/cacache/node_modules/aggregate-error": { + "version": "3.1.0", + "license": "MIT", + "dependencies": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "../node_modules/cacache/node_modules/clean-stack": { + "version": "2.2.0", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "../node_modules/cacache/node_modules/indent-string": { + "version": "4.0.0", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "../node_modules/cacache/node_modules/p-map": { + "version": "4.0.0", + "license": "MIT", + "dependencies": { + "aggregate-error": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "../node_modules/callsites": { + "version": "4.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "../node_modules/case": { + "version": "1.6.3", + "license": "(MIT OR GPL-3.0-or-later)", + "engines": { + "node": ">= 0.8.0" + } + }, + "../node_modules/catharsis": { + "version": "0.9.0", + "dev": true, + "license": "MIT", + "dependencies": { + "lodash": "^4.17.15" + }, + "engines": { + "node": ">= 10" + } + }, + "../node_modules/cbor": { + "version": "8.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "nofilter": "^3.1.0" + }, + "engines": { + "node": ">=12.19" + } + }, + "../node_modules/chalk": { + "version": "5.3.0", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "../node_modules/chokidar": { + "version": "3.5.3", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "license": "MIT", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "../node_modules/chownr": { + "version": "2.0.0", + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "../node_modules/chunkd": { + "version": "2.0.1", + "dev": true, + "license": "MIT" + }, + "../node_modules/ci-info": { + "version": "3.9.0", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "../node_modules/ci-parallel-vars": { + "version": "1.0.1", + "dev": true, + "license": "MIT" + }, + "../node_modules/clean-stack": { + "version": "4.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "escape-string-regexp": "5.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "../node_modules/clean-stack/node_modules/escape-string-regexp": { + "version": "5.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "../node_modules/clean-yaml-object": { + "version": "0.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "../node_modules/cli-truncate": { + "version": "3.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "slice-ansi": "^5.0.0", + "string-width": "^5.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "../node_modules/cliui": { + "version": "8.0.1", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "../node_modules/cliui/node_modules/ansi-regex": { + "version": "5.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "../node_modules/cliui/node_modules/ansi-styles": { + "version": "4.3.0", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "../node_modules/cliui/node_modules/color-convert": { + "version": "2.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "../node_modules/cliui/node_modules/color-name": { + "version": "1.1.4", + "dev": true, + "license": "MIT" + }, + "../node_modules/cliui/node_modules/emoji-regex": { + "version": "8.0.0", + "dev": true, + "license": "MIT" + }, + "../node_modules/cliui/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "../node_modules/cliui/node_modules/string-width": { + "version": "4.2.3", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "../node_modules/cliui/node_modules/strip-ansi": { + "version": "6.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "../node_modules/cliui/node_modules/wrap-ansi": { + "version": "7.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "../node_modules/code-excerpt": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "convert-to-spaces": "^2.0.1" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + } + }, + "../node_modules/color": { + "version": "3.2.1", + "license": "MIT", + "dependencies": { + "color-convert": "^1.9.3", + "color-string": "^1.6.0" + } + }, + "../node_modules/color-convert": { + "version": "1.9.3", + "license": "MIT", + "dependencies": { + "color-name": "1.1.3" + } + }, + "../node_modules/color-name": { + "version": "1.1.3", + "license": "MIT" + }, + "../node_modules/color-string": { + "version": "1.9.1", + "license": "MIT", + "dependencies": { + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" + } + }, + "../node_modules/color-support": { + "version": "1.1.3", + "license": "ISC", + "optional": true, + "bin": { + "color-support": "bin.js" + } + }, + "../node_modules/colorspace": { + "version": "1.1.4", + "license": "MIT", + "dependencies": { + "color": "^3.1.3", + "text-hex": "1.0.x" + } + }, + "../node_modules/common-path-prefix": { + "version": "3.0.0", + "dev": true, + "license": "ISC" + }, + "../node_modules/concat-map": { + "version": "0.0.1", + "devOptional": true, + "license": "MIT" + }, + "../node_modules/concordance": { + "version": "5.0.4", + "dev": true, + "license": "ISC", + "dependencies": { + "date-time": "^3.1.0", + "esutils": "^2.0.3", + "fast-diff": "^1.2.0", + "js-string-escape": "^1.0.1", + "lodash": "^4.17.15", + "md5-hex": "^3.0.1", + "semver": "^7.3.2", + "well-known-symbols": "^2.0.0" + }, + "engines": { + "node": ">=10.18.0 <11 || >=12.14.0 <13 || >=14" + } + }, + "../node_modules/console-control-strings": { + "version": "1.1.0", + "license": "ISC", + "optional": true + }, + "../node_modules/convert-to-spaces": { + "version": "2.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + } + }, + "../node_modules/cross-spawn": { + "version": "7.0.3", + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "../node_modules/currently-unhandled": { + "version": "0.4.1", + "dev": true, + "license": "MIT", + "dependencies": { + "array-find-index": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "../node_modules/date-time": { + "version": "3.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "time-zone": "^1.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "../node_modules/debug": { + "version": "4.3.4", + "license": "MIT", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "../node_modules/debug/node_modules/ms": { + "version": "2.1.2", + "license": "MIT" + }, + "../node_modules/deep-is": { + "version": "0.1.4", + "dev": true, + "license": "MIT" + }, + "../node_modules/delegates": { + "version": "1.0.0", + "license": "MIT", + "optional": true + }, + "../node_modules/detect-libc": { + "version": "2.0.2", + "license": "Apache-2.0", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "../node_modules/dgram": { + "version": "1.0.1", + "license": "ISC" + }, + "../node_modules/dir-glob": { + "version": "3.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "../node_modules/doctrine": { + "version": "3.0.0", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "../node_modules/eastasianwidth": { + "version": "0.2.0", + "license": "MIT" + }, + "../node_modules/emittery": { + "version": "1.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sindresorhus/emittery?sponsor=1" + } + }, + "../node_modules/emoji-regex": { + "version": "9.2.2", + "license": "MIT" + }, + "../node_modules/enabled": { + "version": "2.0.0", + "license": "MIT" + }, + "../node_modules/encoding": { + "version": "0.1.13", + "license": "MIT", + "optional": true, + "dependencies": { + "iconv-lite": "^0.6.2" + } + }, + "../node_modules/entities": { + "version": "2.1.0", + "dev": true, + "license": "BSD-2-Clause", + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "../node_modules/env-paths": { + "version": "2.2.1", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "../node_modules/err-code": { + "version": "2.0.3", + "license": "MIT" + }, + "../node_modules/escalade": { + "version": "3.1.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "../node_modules/escape-string-regexp": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "../node_modules/eslint": { + "version": "8.54.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.3", + "@eslint/js": "8.54.0", + "@humanwhocodes/config-array": "^0.11.13", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "../node_modules/eslint-scope": { + "version": "7.2.2", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "../node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "../node_modules/eslint/node_modules/ansi-regex": { + "version": "5.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "../node_modules/eslint/node_modules/ansi-styles": { + "version": "4.3.0", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "../node_modules/eslint/node_modules/chalk": { + "version": "4.1.2", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "../node_modules/eslint/node_modules/color-convert": { + "version": "2.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "../node_modules/eslint/node_modules/color-name": { + "version": "1.1.4", + "dev": true, + "license": "MIT" + }, + "../node_modules/eslint/node_modules/glob-parent": { + "version": "6.0.2", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "../node_modules/eslint/node_modules/strip-ansi": { + "version": "6.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "../node_modules/espree": { + "version": "9.6.1", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "../node_modules/esprima": { + "version": "4.0.1", + "dev": true, + "license": "BSD-2-Clause", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "../node_modules/esquery": { + "version": "1.5.0", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "../node_modules/esrecurse": { + "version": "4.3.0", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "../node_modules/estraverse": { + "version": "5.3.0", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "../node_modules/esutils": { + "version": "2.0.3", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "../node_modules/events": { + "version": "3.3.0", + "license": "MIT", + "engines": { + "node": ">=0.8.x" + } + }, + "../node_modules/exponential-backoff": { + "version": "3.1.1", + "license": "Apache-2.0" + }, + "../node_modules/fast-deep-equal": { + "version": "3.1.3", + "dev": true, + "license": "MIT" + }, + "../node_modules/fast-diff": { + "version": "1.3.0", + "dev": true, + "license": "Apache-2.0" + }, + "../node_modules/fast-glob": { + "version": "3.3.2", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "../node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "dev": true, + "license": "MIT" + }, + "../node_modules/fast-levenshtein": { + "version": "2.0.6", + "dev": true, + "license": "MIT" + }, + "../node_modules/fastq": { + "version": "1.15.0", + "dev": true, + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "../node_modules/fecha": { + "version": "4.2.3", + "license": "MIT" + }, + "../node_modules/figures": { + "version": "5.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "escape-string-regexp": "^5.0.0", + "is-unicode-supported": "^1.2.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "../node_modules/figures/node_modules/escape-string-regexp": { + "version": "5.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "../node_modules/file-entry-cache": { + "version": "6.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "../node_modules/fill-range": { + "version": "7.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "../node_modules/find-up": { + "version": "5.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "../node_modules/flat-cache": { + "version": "3.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "../node_modules/flatted": { + "version": "3.2.9", + "dev": true, + "license": "ISC" + }, + "../node_modules/fn.name": { + "version": "1.1.0", + "license": "MIT" + }, + "../node_modules/foreground-child": { + "version": "3.1.1", + "license": "ISC", + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "../node_modules/fs-minipass": { + "version": "3.0.3", + "license": "ISC", + "dependencies": { + "minipass": "^7.0.3" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "../node_modules/fs.realpath": { + "version": "1.0.0", + "devOptional": true, + "license": "ISC" + }, + "../node_modules/function-bind": { + "version": "1.1.2", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "../node_modules/gauge": { + "version": "3.0.2", + "license": "ISC", + "optional": true, + "dependencies": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.2", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.1", + "object-assign": "^4.1.1", + "signal-exit": "^3.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.2" + }, + "engines": { + "node": ">=10" + } + }, + "../node_modules/gauge/node_modules/ansi-regex": { + "version": "5.0.1", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "../node_modules/gauge/node_modules/emoji-regex": { + "version": "8.0.0", + "license": "MIT", + "optional": true + }, + "../node_modules/gauge/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "../node_modules/gauge/node_modules/signal-exit": { + "version": "3.0.7", + "license": "ISC", + "optional": true + }, + "../node_modules/gauge/node_modules/string-width": { + "version": "4.2.3", + "license": "MIT", + "optional": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "../node_modules/gauge/node_modules/strip-ansi": { + "version": "6.0.1", + "license": "MIT", + "optional": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "../node_modules/get-caller-file": { + "version": "2.0.5", + "dev": true, + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "../node_modules/glob": { + "version": "10.3.10", + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^2.3.5", + "minimatch": "^9.0.1", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", + "path-scurry": "^1.10.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "../node_modules/glob-parent": { + "version": "5.1.2", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "../node_modules/glob/node_modules/brace-expansion": { + "version": "2.0.1", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "../node_modules/glob/node_modules/minimatch": { + "version": "9.0.3", + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "../node_modules/globals": { + "version": "13.23.0", + "dev": true, + "license": "MIT", + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "../node_modules/globby": { + "version": "13.2.2", + "dev": true, + "license": "MIT", + "dependencies": { + "dir-glob": "^3.0.1", + "fast-glob": "^3.3.0", + "ignore": "^5.2.4", + "merge2": "^1.4.1", + "slash": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "../node_modules/graceful-fs": { + "version": "4.2.11", + "license": "ISC" + }, + "../node_modules/graphemer": { + "version": "1.4.0", + "dev": true, + "license": "MIT" + }, + "../node_modules/has-flag": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "../node_modules/has-unicode": { + "version": "2.0.1", + "license": "ISC", + "optional": true + }, + "../node_modules/hasown": { + "version": "2.0.0", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "../node_modules/http-cache-semantics": { + "version": "4.1.1", + "license": "BSD-2-Clause" + }, + "../node_modules/http-proxy-agent": { + "version": "7.0.0", + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "../node_modules/http-proxy-agent/node_modules/agent-base": { + "version": "7.1.0", + "license": "MIT", + "dependencies": { + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "../node_modules/https-proxy-agent": { + "version": "5.0.1", + "license": "MIT", + "optional": true, + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "../node_modules/iconv-lite": { + "version": "0.6.3", + "license": "MIT", + "optional": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "../node_modules/ignore": { + "version": "5.3.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "../node_modules/ignore-by-default": { + "version": "2.1.0", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10 <11 || >=12 <13 || >=14" + } + }, + "../node_modules/import-fresh": { + "version": "3.3.0", + "dev": true, + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "../node_modules/imurmurhash": { + "version": "0.1.4", + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "../node_modules/indent-string": { + "version": "5.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "../node_modules/inflight": { + "version": "1.0.6", + "devOptional": true, + "license": "ISC", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "../node_modules/inherits": { + "version": "2.0.4", + "license": "ISC" + }, + "../node_modules/ip": { + "version": "2.0.0", + "license": "MIT" + }, + "../node_modules/irregular-plurals": { + "version": "3.5.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "../node_modules/is-arrayish": { + "version": "0.3.2", + "license": "MIT" + }, + "../node_modules/is-binary-path": { + "version": "2.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "../node_modules/is-core-module": { + "version": "2.13.1", + "license": "MIT", + "dependencies": { + "hasown": "^2.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "../node_modules/is-error": { + "version": "2.2.2", + "dev": true, + "license": "MIT" + }, + "../node_modules/is-extglob": { + "version": "2.1.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "../node_modules/is-fullwidth-code-point": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "../node_modules/is-glob": { + "version": "4.0.3", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "../node_modules/is-lambda": { + "version": "1.0.1", + "license": "MIT" + }, + "../node_modules/is-number": { + "version": "7.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "../node_modules/is-path-inside": { + "version": "3.0.3", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "../node_modules/is-plain-object": { + "version": "5.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "../node_modules/is-promise": { + "version": "4.0.0", + "dev": true, + "license": "MIT" + }, + "../node_modules/is-stream": { + "version": "2.0.1", + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "../node_modules/is-unicode-supported": { + "version": "1.3.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "../node_modules/isexe": { + "version": "2.0.0", + "license": "ISC" + }, + "../node_modules/jackspeak": { + "version": "2.3.6", + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "../node_modules/js-string-escape": { + "version": "1.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "../node_modules/js-yaml": { + "version": "4.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "../node_modules/js2xmlparser": { + "version": "4.0.2", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "xmlcreate": "^2.0.4" + } + }, + "../node_modules/jsdoc": { + "version": "4.0.2", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@babel/parser": "^7.20.15", + "@jsdoc/salty": "^0.2.1", + "@types/markdown-it": "^12.2.3", + "bluebird": "^3.7.2", + "catharsis": "^0.9.0", + "escape-string-regexp": "^2.0.0", + "js2xmlparser": "^4.0.2", + "klaw": "^3.0.0", + "markdown-it": "^12.3.2", + "markdown-it-anchor": "^8.4.1", + "marked": "^4.0.10", + "mkdirp": "^1.0.4", + "requizzle": "^0.2.3", + "strip-json-comments": "^3.1.0", + "underscore": "~1.13.2" + }, + "bin": { + "jsdoc": "jsdoc.js" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "../node_modules/jsdoc/node_modules/escape-string-regexp": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "../node_modules/json-buffer": { + "version": "3.0.1", + "dev": true, + "license": "MIT" + }, + "../node_modules/json-schema-traverse": { + "version": "0.4.1", + "dev": true, + "license": "MIT" + }, + "../node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "dev": true, + "license": "MIT" + }, + "../node_modules/keyv": { + "version": "4.5.4", + "dev": true, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "../node_modules/klaw": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.1.9" + } + }, + "../node_modules/kuler": { + "version": "2.0.0", + "license": "MIT" + }, + "../node_modules/levn": { + "version": "0.4.1", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "../node_modules/linkify-it": { + "version": "3.0.3", + "dev": true, + "license": "MIT", + "dependencies": { + "uc.micro": "^1.0.1" + } + }, + "../node_modules/load-json-file": { + "version": "7.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "../node_modules/locate-path": { + "version": "6.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "../node_modules/lodash": { + "version": "4.17.21", + "dev": true, + "license": "MIT" + }, + "../node_modules/lodash.merge": { + "version": "4.6.2", + "dev": true, + "license": "MIT" + }, + "../node_modules/logform": { + "version": "2.6.0", + "license": "MIT", + "dependencies": { + "@colors/colors": "1.6.0", + "@types/triple-beam": "^1.3.2", + "fecha": "^4.2.0", + "ms": "^2.1.1", + "safe-stable-stringify": "^2.3.1", + "triple-beam": "^1.3.0" + }, + "engines": { + "node": ">= 12.0.0" + } + }, + "../node_modules/lru-cache": { + "version": "10.1.0", + "license": "ISC", + "engines": { + "node": "14 || >=16.14" + } + }, + "../node_modules/make-dir": { + "version": "3.1.0", + "license": "MIT", + "optional": true, + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "../node_modules/make-dir/node_modules/semver": { + "version": "6.3.1", + "license": "ISC", + "optional": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "../node_modules/make-fetch-happen": { + "version": "13.0.0", + "license": "ISC", + "dependencies": { + "@npmcli/agent": "^2.0.0", + "cacache": "^18.0.0", + "http-cache-semantics": "^4.1.1", + "is-lambda": "^1.0.1", + "minipass": "^7.0.2", + "minipass-fetch": "^3.0.0", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^0.6.3", + "promise-retry": "^2.0.1", + "ssri": "^10.0.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "../node_modules/map-age-cleaner": { + "version": "0.1.3", + "dev": true, + "license": "MIT", + "dependencies": { + "p-defer": "^1.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "../node_modules/markdown-it": { + "version": "12.3.2", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1", + "entities": "~2.1.0", + "linkify-it": "^3.0.1", + "mdurl": "^1.0.1", + "uc.micro": "^1.0.5" + }, + "bin": { + "markdown-it": "bin/markdown-it.js" + } + }, + "../node_modules/markdown-it-anchor": { + "version": "8.6.7", + "dev": true, + "license": "Unlicense", + "peerDependencies": { + "@types/markdown-it": "*", + "markdown-it": "*" + } + }, + "../node_modules/marked": { + "version": "4.3.0", + "dev": true, + "license": "MIT", + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 12" + } + }, + "../node_modules/matcher": { + "version": "5.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "escape-string-regexp": "^5.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "../node_modules/matcher/node_modules/escape-string-regexp": { + "version": "5.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "../node_modules/md5-hex": { + "version": "3.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "blueimp-md5": "^2.10.0" + }, + "engines": { + "node": ">=8" + } + }, + "../node_modules/mdns": { + "version": "2.7.2", + "dev": true, + "dependencies": { + "bindings": "~1.2.1", + "nan": "^2.14.0" + } + }, + "../node_modules/mdurl": { + "version": "1.0.1", + "dev": true, + "license": "MIT" + }, + "../node_modules/mem": { + "version": "9.0.2", + "dev": true, + "license": "MIT", + "dependencies": { + "map-age-cleaner": "^0.1.3", + "mimic-fn": "^4.0.0" + }, + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sindresorhus/mem?sponsor=1" + } + }, + "../node_modules/merge2": { + "version": "1.4.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "../node_modules/micromatch": { + "version": "4.0.5", + "dev": true, + "license": "MIT", + "dependencies": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "../node_modules/mimic-fn": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "../node_modules/minami-compat": { + "version": "1.2.4", + "dev": true + }, + "../node_modules/minimatch": { + "version": "3.1.2", + "devOptional": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "../node_modules/minipass": { + "version": "7.0.4", + "license": "ISC", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "../node_modules/minipass-collect": { + "version": "1.0.2", + "license": "ISC", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "../node_modules/minipass-collect/node_modules/minipass": { + "version": "3.3.6", + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "../node_modules/minipass-fetch": { + "version": "3.0.4", + "license": "MIT", + "dependencies": { + "minipass": "^7.0.3", + "minipass-sized": "^1.0.3", + "minizlib": "^2.1.2" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + }, + "optionalDependencies": { + "encoding": "^0.1.13" + } + }, + "../node_modules/minipass-flush": { + "version": "1.0.5", + "license": "ISC", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "../node_modules/minipass-flush/node_modules/minipass": { + "version": "3.3.6", + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "../node_modules/minipass-pipeline": { + "version": "1.2.4", + "license": "ISC", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "../node_modules/minipass-pipeline/node_modules/minipass": { + "version": "3.3.6", + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "../node_modules/minipass-sized": { + "version": "1.0.3", + "license": "ISC", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "../node_modules/minipass-sized/node_modules/minipass": { + "version": "3.3.6", + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "../node_modules/minizlib": { + "version": "2.1.2", + "license": "MIT", + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "../node_modules/minizlib/node_modules/minipass": { + "version": "3.3.6", + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "../node_modules/mkdirp": { + "version": "1.0.4", + "license": "MIT", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "../node_modules/ms": { + "version": "2.1.3", + "license": "MIT" + }, + "../node_modules/nan": { + "version": "2.18.0", + "devOptional": true, + "license": "MIT" + }, + "../node_modules/napi-thread-safe-callback": { + "version": "0.0.6", + "license": "ISC" + }, + "../node_modules/natural-compare": { + "version": "1.4.0", + "dev": true, + "license": "MIT" + }, + "../node_modules/negotiator": { + "version": "0.6.3", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "../node_modules/net": { + "version": "1.0.2", + "license": "MIT" + }, + "../node_modules/node-addon-api": { + "version": "4.3.0", + "license": "MIT" + }, + "../node_modules/node-fetch": { + "version": "2.7.0", + "license": "MIT", + "optional": true, + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "../node_modules/node-gyp": { + "version": "10.0.1", + "license": "MIT", + "dependencies": { + "env-paths": "^2.2.0", + "exponential-backoff": "^3.1.1", + "glob": "^10.3.10", + "graceful-fs": "^4.2.6", + "make-fetch-happen": "^13.0.0", + "nopt": "^7.0.0", + "proc-log": "^3.0.0", + "semver": "^7.3.5", + "tar": "^6.1.2", + "which": "^4.0.0" + }, + "bin": { + "node-gyp": "bin/node-gyp.js" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "../node_modules/node-gyp-build": { + "version": "4.7.1", + "license": "MIT", + "bin": { + "node-gyp-build": "bin.js", + "node-gyp-build-optional": "optional.js", + "node-gyp-build-test": "build-test.js" + } + }, + "../node_modules/node-gyp/node_modules/abbrev": { + "version": "2.0.0", + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "../node_modules/node-gyp/node_modules/isexe": { + "version": "3.1.1", + "license": "ISC", + "engines": { + "node": ">=16" + } + }, + "../node_modules/node-gyp/node_modules/nopt": { + "version": "7.2.0", + "license": "ISC", + "dependencies": { + "abbrev": "^2.0.0" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "../node_modules/node-gyp/node_modules/which": { + "version": "4.0.0", + "license": "ISC", + "dependencies": { + "isexe": "^3.1.1" + }, + "bin": { + "node-which": "bin/which.js" + }, + "engines": { + "node": "^16.13.0 || >=18.0.0" + } + }, + "../node_modules/nofilter": { + "version": "3.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.19" + } + }, + "../node_modules/nopt": { + "version": "5.0.0", + "license": "ISC", + "optional": true, + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": ">=6" + } + }, + "../node_modules/normalize-path": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "../node_modules/npmlog": { + "version": "5.0.1", + "license": "ISC", + "optional": true, + "dependencies": { + "are-we-there-yet": "^2.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^3.0.0", + "set-blocking": "^2.0.0" + } + }, + "../node_modules/object-assign": { + "version": "4.1.1", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "../node_modules/once": { + "version": "1.4.0", + "devOptional": true, + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "../node_modules/one-time": { + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "fn.name": "1.x.x" + } + }, + "../node_modules/optionator": { + "version": "0.9.3", + "dev": true, + "license": "MIT", + "dependencies": { + "@aashutoshrathi/word-wrap": "^1.2.3", + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "../node_modules/p-defer": { + "version": "1.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "../node_modules/p-event": { + "version": "5.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "p-timeout": "^5.0.2" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "../node_modules/p-limit": { + "version": "3.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "../node_modules/p-locate": { + "version": "5.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "../node_modules/p-map": { + "version": "5.5.0", + "dev": true, + "license": "MIT", + "dependencies": { + "aggregate-error": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "../node_modules/p-timeout": { + "version": "5.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "../node_modules/parent-module": { + "version": "1.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "../node_modules/parent-module/node_modules/callsites": { + "version": "3.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "../node_modules/parse-ms": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "../node_modules/path-exists": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "../node_modules/path-is-absolute": { + "version": "1.0.1", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "../node_modules/path-key": { + "version": "3.1.1", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "../node_modules/path-parse": { + "version": "1.0.7", + "license": "MIT" + }, + "../node_modules/path-scurry": { + "version": "1.10.1", + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^9.1.1 || ^10.0.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "../node_modules/path-type": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "../node_modules/picomatch": { + "version": "2.3.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "../node_modules/pkg-conf": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "find-up": "^6.0.0", + "load-json-file": "^7.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "../node_modules/pkg-conf/node_modules/find-up": { + "version": "6.3.0", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^7.1.0", + "path-exists": "^5.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "../node_modules/pkg-conf/node_modules/locate-path": { + "version": "7.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^6.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "../node_modules/pkg-conf/node_modules/p-limit": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^1.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "../node_modules/pkg-conf/node_modules/p-locate": { + "version": "6.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "../node_modules/pkg-conf/node_modules/path-exists": { + "version": "5.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + } + }, + "../node_modules/pkg-conf/node_modules/yocto-queue": { + "version": "1.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "../node_modules/plur": { + "version": "5.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "irregular-plurals": "^3.3.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "../node_modules/prelude-ls": { + "version": "1.2.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, + "../node_modules/pretty-ms": { + "version": "8.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "parse-ms": "^3.0.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "../node_modules/proc-log": { + "version": "3.0.0", + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "../node_modules/promise-retry": { + "version": "2.0.1", + "license": "MIT", + "dependencies": { + "err-code": "^2.0.2", + "retry": "^0.12.0" + }, + "engines": { + "node": ">=10" + } + }, + "../node_modules/punycode": { + "version": "2.3.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "../node_modules/queue-microtask": { + "version": "1.2.3", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "../node_modules/readable-stream": { + "version": "3.6.2", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "../node_modules/readdirp": { + "version": "3.6.0", + "dev": true, + "license": "MIT", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "../node_modules/require-directory": { + "version": "2.1.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "../node_modules/requizzle": { + "version": "0.2.4", + "dev": true, + "license": "MIT", + "dependencies": { + "lodash": "^4.17.21" + } + }, + "../node_modules/resolve": { + "version": "1.22.8", + "license": "MIT", + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "../node_modules/resolve-cwd": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "../node_modules/resolve-cwd/node_modules/resolve-from": { + "version": "5.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "../node_modules/resolve-from": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "../node_modules/retry": { + "version": "0.12.0", + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "../node_modules/reusify": { + "version": "1.0.4", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "../node_modules/rimraf": { + "version": "3.0.2", + "devOptional": true, + "license": "ISC", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "../node_modules/rimraf/node_modules/glob": { + "version": "7.2.3", + "devOptional": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "../node_modules/run-parallel": { + "version": "1.2.0", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "../node_modules/safe-buffer": { + "version": "5.2.1", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "../node_modules/safe-stable-stringify": { + "version": "2.4.3", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "../node_modules/safer-buffer": { + "version": "2.1.2", + "license": "MIT", + "optional": true + }, + "../node_modules/sax": { + "version": "1.3.0", + "license": "ISC" + }, + "../node_modules/semver": { + "version": "7.5.4", + "license": "ISC", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "../node_modules/semver/node_modules/lru-cache": { + "version": "6.0.0", + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "../node_modules/serialize-error": { + "version": "7.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "type-fest": "^0.13.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "../node_modules/serialize-error/node_modules/type-fest": { + "version": "0.13.1", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "../node_modules/set-blocking": { + "version": "2.0.0", + "license": "ISC", + "optional": true + }, + "../node_modules/shebang-command": { + "version": "2.0.0", + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "../node_modules/shebang-regex": { + "version": "3.0.0", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "../node_modules/signal-exit": { + "version": "4.1.0", + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "../node_modules/simple-swizzle": { + "version": "0.2.2", + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.3.1" + } + }, + "../node_modules/slash": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "../node_modules/slice-ansi": { + "version": "5.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.0.0", + "is-fullwidth-code-point": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "../node_modules/smart-buffer": { + "version": "4.2.0", + "license": "MIT", + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" + } + }, + "../node_modules/socks": { + "version": "2.7.1", + "license": "MIT", + "dependencies": { + "ip": "^2.0.0", + "smart-buffer": "^4.2.0" + }, + "engines": { + "node": ">= 10.13.0", + "npm": ">= 3.0.0" + } + }, + "../node_modules/socks-proxy-agent": { + "version": "8.0.2", + "license": "MIT", + "dependencies": { + "agent-base": "^7.0.2", + "debug": "^4.3.4", + "socks": "^2.7.1" + }, + "engines": { + "node": ">= 14" + } + }, + "../node_modules/socks-proxy-agent/node_modules/agent-base": { + "version": "7.1.0", + "license": "MIT", + "dependencies": { + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "../node_modules/sprintf-js": { + "version": "1.0.3", + "dev": true, + "license": "BSD-3-Clause" + }, + "../node_modules/ssri": { + "version": "10.0.5", + "license": "ISC", + "dependencies": { + "minipass": "^7.0.3" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "../node_modules/stack-trace": { + "version": "0.0.10", + "license": "MIT", + "engines": { + "node": "*" + } + }, + "../node_modules/stack-utils": { + "version": "2.0.6", + "dev": true, + "license": "MIT", + "dependencies": { + "escape-string-regexp": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "../node_modules/stack-utils/node_modules/escape-string-regexp": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "../node_modules/string_decoder": { + "version": "1.3.0", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "../node_modules/string-width": { + "version": "5.1.2", + "license": "MIT", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "../node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "../node_modules/string-width-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "../node_modules/string-width-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "license": "MIT" + }, + "../node_modules/string-width-cjs/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "../node_modules/string-width-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "../node_modules/strip-ansi": { + "version": "7.1.0", + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "../node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "../node_modules/strip-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "../node_modules/strip-json-comments": { + "version": "3.1.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "../node_modules/supertap": { + "version": "3.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "indent-string": "^5.0.0", + "js-yaml": "^3.14.1", + "serialize-error": "^7.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + } + }, + "../node_modules/supertap/node_modules/argparse": { + "version": "1.0.10", + "dev": true, + "license": "MIT", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "../node_modules/supertap/node_modules/js-yaml": { + "version": "3.14.1", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "../node_modules/supports-color": { + "version": "7.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "../node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "../node_modules/tar": { + "version": "6.2.0", + "license": "ISC", + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "../node_modules/tar/node_modules/fs-minipass": { + "version": "2.1.0", + "license": "ISC", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "../node_modules/tar/node_modules/fs-minipass/node_modules/minipass": { + "version": "3.3.6", + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "../node_modules/tar/node_modules/minipass": { + "version": "5.0.0", + "license": "ISC", + "engines": { + "node": ">=8" + } + }, + "../node_modules/temp-dir": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.16" + } + }, + "../node_modules/text-hex": { + "version": "1.0.0", + "license": "MIT" + }, + "../node_modules/text-table": { + "version": "0.2.0", + "dev": true, + "license": "MIT" + }, + "../node_modules/time-zone": { + "version": "1.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "../node_modules/to-regex-range": { + "version": "5.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "../node_modules/tr46": { + "version": "0.0.3", + "license": "MIT", + "optional": true + }, + "../node_modules/triple-beam": { + "version": "1.4.1", + "license": "MIT", + "engines": { + "node": ">= 14.0.0" + } + }, + "../node_modules/type-check": { + "version": "0.4.0", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "../node_modules/type-fest": { + "version": "0.20.2", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "../node_modules/uc.micro": { + "version": "1.0.6", + "dev": true, + "license": "MIT" + }, + "../node_modules/underscore": { + "version": "1.13.6", + "dev": true, + "license": "MIT" + }, + "../node_modules/unique-filename": { + "version": "3.0.0", + "license": "ISC", + "dependencies": { + "unique-slug": "^4.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "../node_modules/unique-slug": { + "version": "4.0.0", + "license": "ISC", + "dependencies": { + "imurmurhash": "^0.1.4" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "../node_modules/uri-js": { + "version": "4.4.1", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "../node_modules/usb": { + "version": "1.9.2", + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "dependencies": { + "node-addon-api": "^4.2.0", + "node-gyp-build": "^4.3.0" + }, + "engines": { + "node": ">=10.16.0" + } + }, + "../node_modules/util-deprecate": { + "version": "1.0.2", + "license": "MIT" + }, + "../node_modules/webidl-conversions": { + "version": "3.0.1", + "license": "BSD-2-Clause", + "optional": true + }, + "../node_modules/well-known-symbols": { + "version": "2.0.0", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=6" + } + }, + "../node_modules/whatwg-url": { + "version": "5.0.0", + "license": "MIT", + "optional": true, + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "../node_modules/which": { + "version": "2.0.2", + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "../node_modules/wide-align": { + "version": "1.1.5", + "license": "ISC", + "optional": true, + "dependencies": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "../node_modules/wide-align/node_modules/ansi-regex": { + "version": "5.0.1", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "../node_modules/wide-align/node_modules/emoji-regex": { + "version": "8.0.0", + "license": "MIT", + "optional": true + }, + "../node_modules/wide-align/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "../node_modules/wide-align/node_modules/string-width": { + "version": "4.2.3", + "license": "MIT", + "optional": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "../node_modules/wide-align/node_modules/strip-ansi": { + "version": "6.0.1", + "license": "MIT", + "optional": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "../node_modules/winston": { + "version": "3.11.0", + "license": "MIT", + "dependencies": { + "@colors/colors": "^1.6.0", + "@dabh/diagnostics": "^2.0.2", + "async": "^3.2.3", + "is-stream": "^2.0.0", + "logform": "^2.4.0", + "one-time": "^1.0.0", + "readable-stream": "^3.4.0", + "safe-stable-stringify": "^2.3.1", + "stack-trace": "0.0.x", + "triple-beam": "^1.3.0", + "winston-transport": "^4.5.0" + }, + "engines": { + "node": ">= 12.0.0" + } + }, + "../node_modules/winston-transport": { + "version": "4.6.0", + "license": "MIT", + "dependencies": { + "logform": "^2.3.2", + "readable-stream": "^3.6.0", + "triple-beam": "^1.3.0" + }, + "engines": { + "node": ">= 12.0.0" + } + }, + "../node_modules/wrap-ansi": { + "version": "8.1.0", + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "../node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "../node_modules/wrap-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "../node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { + "version": "4.3.0", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "../node_modules/wrap-ansi-cjs/node_modules/color-convert": { + "version": "2.0.1", + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "../node_modules/wrap-ansi-cjs/node_modules/color-name": { + "version": "1.1.4", + "license": "MIT" + }, + "../node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "license": "MIT" + }, + "../node_modules/wrap-ansi-cjs/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "../node_modules/wrap-ansi-cjs/node_modules/string-width": { + "version": "4.2.3", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "../node_modules/wrap-ansi-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "../node_modules/wrappy": { + "version": "1.0.2", + "devOptional": true, + "license": "ISC" + }, + "../node_modules/write-file-atomic": { + "version": "5.0.1", + "dev": true, + "license": "ISC", + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "../node_modules/xml2js": { + "version": "0.6.2", + "license": "MIT", + "dependencies": { + "sax": ">=0.6.0", + "xmlbuilder": "~11.0.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "../node_modules/xmlbuilder": { + "version": "11.0.1", + "license": "MIT", + "engines": { + "node": ">=4.0" + } + }, + "../node_modules/xmlcreate": { + "version": "2.0.4", + "dev": true, + "license": "Apache-2.0" + }, + "../node_modules/y18n": { + "version": "5.0.8", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "../node_modules/yallist": { + "version": "4.0.0", + "license": "ISC" + }, + "../node_modules/yargs": { + "version": "17.7.2", + "dev": true, + "license": "MIT", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "../node_modules/yargs-parser": { + "version": "21.1.1", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "../node_modules/yargs/node_modules/ansi-regex": { + "version": "5.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "../node_modules/yargs/node_modules/emoji-regex": { + "version": "8.0.0", + "dev": true, + "license": "MIT" + }, + "../node_modules/yargs/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "../node_modules/yargs/node_modules/string-width": { + "version": "4.2.3", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "../node_modules/yargs/node_modules/strip-ansi": { + "version": "6.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "../node_modules/yocto-queue": { + "version": "0.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/async": { + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", + "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", + "dependencies": { + "lodash": "^4.17.14" + } + }, + "node_modules/colors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz", + "integrity": "sha512-pFGrxThWcWQ2MsAz6RtgeWe4NK2kUE1WfsrvvlctdII745EW9I0yflqhe7++M5LEc7bV2c/9/5zc8sFcpL0Drw==", + "engines": { + "node": ">=0.1.90" + } + }, + "node_modules/cycle": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/cycle/-/cycle-1.0.3.tgz", + "integrity": "sha512-TVF6svNzeQCOpjCqsy0/CSy8VgObG3wXusJ73xW2GbG5rGx7lC8zxDSURicsXI2UsGdi2L0QNRCi745/wUDvsA==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/eyes": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/eyes/-/eyes-0.1.8.tgz", + "integrity": "sha512-GipyPsXO1anza0AOZdy69Im7hGFCNB7Y/NGjDlZGJ3GJJLtwNSb2vrzYrTYJRrRloVx7pl+bhUaTB8yiccPvFQ==", + "engines": { + "node": "> 0.1.90" + } + }, + "node_modules/isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==" + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "node_modules/minidrone-js": { + "resolved": "..", + "link": true + }, + "node_modules/stack-trace": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", + "integrity": "sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==", + "engines": { + "node": "*" + } + }, + "node_modules/winston": { + "version": "2.4.7", + "resolved": "https://registry.npmjs.org/winston/-/winston-2.4.7.tgz", + "integrity": "sha512-vLB4BqzCKDnnZH9PHGoS2ycawueX4HLqENXQitvFHczhgW2vFpSOn31LZtVr1KU8YTw7DS4tM+cqyovxo8taVg==", + "dependencies": { + "async": "^2.6.4", + "colors": "1.0.x", + "cycle": "1.0.x", + "eyes": "0.1.x", + "isstream": "0.1.x", + "stack-trace": "0.0.x" + }, + "engines": { + "node": ">= 0.10.0" + } + } + } +} diff --git a/examples/package.json b/examples/package.json index 32f822bf..4a166749 100644 --- a/examples/package.json +++ b/examples/package.json @@ -4,7 +4,7 @@ "license": "MIT", "dependencies": { "minidrone-js": "file:../", - "dualshock-controller": "^1.1.1", - "winston": "^2.4.0" + "winston": "^2.4.0", + "dualshock-controller": "^1.1.1" } } diff --git a/src/CharacteristicEnums.js b/src/CharacteristicEnums.js index 486ab1f1..0d39f2ad 100644 --- a/src/CharacteristicEnums.js +++ b/src/CharacteristicEnums.js @@ -54,7 +54,7 @@ const receiveUuids = new Enum({ * * @type {Enum} */ -const characteristicUuids = new Enum(Object.assign({}, characteristicSendUuids, characteristicReceiveUuids)); +const characteristicUuids = new Enum(Object.assign({}, sendUuids, receiveUuids)); /** * @see http://forum.developer.parrot.com/t/minidrone-characteristics-uuid/4686/3 diff --git a/src/DroneCommand.js b/src/DroneCommand.js index 38a26d61..28e0330b 100644 --- a/src/DroneCommand.js +++ b/src/DroneCommand.js @@ -154,7 +154,7 @@ class DroneCommand { * @returns {string} - uuid as a string */ get sendCharacteristicUuid() { - return characteristicSendUuids[this.sendCharacteristic]; + return sendUuids[this.sendCharacteristic]; } /** diff --git a/src/connectors/BLEConnector.js b/src/connectors/BLEConnector.js index 87a094ba..488690d6 100644 --- a/src/connectors/BLEConnector.js +++ b/src/connectors/BLEConnector.js @@ -1,4 +1,4 @@ -const noble = require('noble'); +const noble = require('@abandonware/noble'); const BaseConnector = require('./BaseConnector'); const Logger = require('winston'); const Enum = require('../util/Enum'); diff --git a/src/connectors/WifiConnector.js b/src/connectors/WifiConnector.js index 9e486c7e..a9298f9f 100644 --- a/src/connectors/WifiConnector.js +++ b/src/connectors/WifiConnector.js @@ -28,18 +28,22 @@ class WifiConnector extends BaseConnector { /** * @inheritDoc */ - connect() { - if (!this.browser && !this.server && !this.client) { + connect(host = null, port = null) { + if (!(!this.browser && !this.server && !this.client)) { + return new Promise(accept => accept()); + } else if (host && port) { + return this._connect(host, port); + } else { Logger.debug('Starting mDNS browser'); const resolverSequence = [ // eslint-disable-next-line new-cap mdns.rst.DNSServiceResolve(), // eslint-disable-next-line new-cap - mdns.rst.DNSServiceGetAddrInfo({ families: [4] }), + mdns.rst.DNSServiceGetAddrInfo({families: [4]}), ]; - this.browser = mdns.createBrowser(mdns.udp('_arsdk-090b'), { resolverSequence }); // @todo browse all + this.browser = mdns.createBrowser(mdns.udp('_arsdk-090b'), {resolverSequence}); // @todo browse all return new Promise(accept => { this.browser.on('serviceUp', service => this._onMdnsServiceDiscovery(service).then(c => !c || accept())); @@ -47,8 +51,6 @@ class WifiConnector extends BaseConnector { this.browser.start(); }); } - - return new Promise(accept => accept()); } /** @@ -85,14 +87,14 @@ class WifiConnector extends BaseConnector { return true; } - async _connect(service) { - Logger.info(`Doing Wifi handshake with ${service.addresses[0]} [${service.addresses.join(', ')}]`); + async _connect(host, port) { + Logger.info(`Doing Wifi handshake with ${host}`); await this._startServer(); - this.ip = service.addresses[0]; + this.ip = host; - let data = await this._sendHandshake(this.ip, service.port); + let data = await this._sendHandshake(this.ip, port); data = data.toString(); data = data.replace('\0', ''); // Remove trailing nullbyte From 430d678bdf69626d54623ef5ac97111f42ad6b5f Mon Sep 17 00:00:00 2001 From: shodan Date: Sun, 26 Nov 2023 22:45:10 +0100 Subject: [PATCH 13/17] Remove broken package --- package-lock.json | 10 +--------- package.json | 1 - 2 files changed, 1 insertion(+), 10 deletions(-) diff --git a/package-lock.json b/package-lock.json index 78d989f6..87421b4a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -24,8 +24,7 @@ "ava": "5.3.1", "eslint": "^8.54.0", "jsdoc": "^4.0.2", - "mdns": "^2.4.0", - "minami-compat": "1.2.4" + "mdns": "^2.4.0" } }, "node_modules/@aashutoshrathi/word-wrap": { @@ -2660,13 +2659,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/minami-compat": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/minami-compat/-/minami-compat-1.2.4.tgz", - "integrity": "sha512-9UGVRkvRm1OhnxJ1dXnC4UdA+RuOZUYIsauDVC0bHoqqiqURuBnf17syuvdp1b+uDJ31Yy4Y5IifwqK4v79+EQ==", - "deprecated": "MODIFICATIONS ARE NOT SUPPORTED IN NODE 10, USE ORIGINAL MINAMI THEME", - "dev": true - }, "node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", diff --git a/package.json b/package.json index 8b1fb971..a0a8ae67 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,6 @@ }, "devDependencies": { "mdns": "^2.4.0", - "minami-compat": "1.2.4", "ava": "5.3.1", "eslint": "^8.54.0", "jsdoc": "^4.0.2" From 484778ea554e02ae7931fc4d05861abc914326f1 Mon Sep 17 00:00:00 2001 From: shodan Date: Sun, 26 Nov 2023 23:11:21 +0100 Subject: [PATCH 14/17] Attempt to fix broken example dependency --- examples/package-lock.json | 460 ++++++++++++++++++++++++++++++++++++- examples/package.json | 5 + 2 files changed, 459 insertions(+), 6 deletions(-) diff --git a/examples/package-lock.json b/examples/package-lock.json index 1342eff4..bfec63a7 100644 --- a/examples/package-lock.json +++ b/examples/package-lock.json @@ -7,6 +7,7 @@ "name": "direct-flight", "license": "MIT", "dependencies": { + "dualshock-controller": "^1.1.1", "minidrone-js": "file:../", "winston": "^2.4.0" } @@ -30,8 +31,7 @@ "ava": "5.3.1", "eslint": "^8.54.0", "jsdoc": "^4.0.2", - "mdns": "^2.4.0", - "minami-compat": "1.2.4" + "mdns": "^2.4.0" } }, "../node_modules/@aashutoshrathi/word-wrap": { @@ -2410,10 +2410,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "../node_modules/minami-compat": { - "version": "1.2.4", - "dev": true - }, "../node_modules/minimatch": { "version": "3.1.2", "devOptional": true, @@ -4166,6 +4162,71 @@ "lodash": "^4.17.14" } }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "dependencies": { + "file-uri-to-path": "1.0.0" + } + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + }, "node_modules/colors": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz", @@ -4182,6 +4243,63 @@ "node": ">=0.4.0" } }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/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==", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/detect-libc": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.2.tgz", + "integrity": "sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw==", + "engines": { + "node": ">=8" + } + }, + "node_modules/dualshock-controller": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/dualshock-controller/-/dualshock-controller-1.1.1.tgz", + "integrity": "sha512-CEWhF17Y3ZCcpO2DHwoApoOm/TiLX4E1DHDdj9YLZTS4cYIhKbF3lrRvppKLYf0syrw+zpRaPKvxYbTF+8Vxog==", + "dependencies": { + "node-hid": "^0.5.0" + }, + "engines": { + "node": ">=6.9.2" + } + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", + "engines": { + "node": ">=6" + } + }, "node_modules/eyes": { "version": "0.1.8", "resolved": "https://registry.npmjs.org/eyes/-/eyes-0.1.8.tgz", @@ -4190,6 +4308,50 @@ "node": "> 0.1.90" } }, + "node_modules/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==" + }, + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, + "node_modules/github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==" + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, "node_modules/isstream": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", @@ -4200,10 +4362,228 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/minidrone-js": { "resolved": "..", "link": true }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" + }, + "node_modules/napi-build-utils": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", + "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==" + }, + "node_modules/node-abi": { + "version": "3.51.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.51.0.tgz", + "integrity": "sha512-SQkEP4hmNWjlniS5zdnfIXTk1x7Ome85RDzHlTbBtzE97Gfwz/Ipw4v/Ryk20DWIy3yCNVLVlGKApCnmvYoJbA==", + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/node-addon-api": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.2.1.tgz", + "integrity": "sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A==" + }, + "node_modules/node-hid": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/node-hid/-/node-hid-2.2.0.tgz", + "integrity": "sha512-vj48zh9j555DZzUhMc8tk/qw6xPFrDyPBH1ST1Z/hWaA/juBJw7IuSxPeOgpzNFNU36mGYj+THioRMt1xOdm/g==", + "hasInstallScript": true, + "dependencies": { + "bindings": "^1.5.0", + "node-addon-api": "^3.0.2", + "prebuild-install": "^7.1.1" + }, + "bin": { + "hid-showdevices": "src/show-devices.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/prebuild-install": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.1.tgz", + "integrity": "sha512-jAXscXWMcCK8GgCoHOfIr0ODh5ai8mj63L2nWrjuAgXE6tDyYGnx4/8o/rCgU+B4JSyZBKbeZqzhtwtC3ovxjw==", + "dependencies": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^1.0.1", + "node-abi": "^3.3.0", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + }, + "bin": { + "prebuild-install": "bin.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, "node_modules/stack-trace": { "version": "0.0.10", "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", @@ -4212,6 +4592,64 @@ "node": "*" } }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/tar-fs": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", + "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", + "dependencies": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + }, "node_modules/winston": { "version": "2.4.7", "resolved": "https://registry.npmjs.org/winston/-/winston-2.4.7.tgz", @@ -4227,6 +4665,16 @@ "engines": { "node": ">= 0.10.0" } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" } } } diff --git a/examples/package.json b/examples/package.json index 4a166749..15924563 100644 --- a/examples/package.json +++ b/examples/package.json @@ -6,5 +6,10 @@ "minidrone-js": "file:../", "winston": "^2.4.0", "dualshock-controller": "^1.1.1" + }, + "overrides": { + "dualshock-controller": { + "node-hid": "^2.2.0" + } } } From b814c1313960d2a424649cea9362dfe25098d7c2 Mon Sep 17 00:00:00 2001 From: shodan Date: Sun, 26 Nov 2023 23:26:50 +0100 Subject: [PATCH 15/17] fix ci --- .github/workflows/node.js.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/node.js.yml b/.github/workflows/node.js.yml index 33e214a5..e868bb6c 100644 --- a/.github/workflows/node.js.yml +++ b/.github/workflows/node.js.yml @@ -16,6 +16,8 @@ jobs: uses: actions/setup-node@v2 with: node-version: ${{ matrix.node-version }} + - name: Install OS Packages + run: apt update && apt install libavahi-compat-libdnssd-dev \ - name: Cache node modules id: cache-npm uses: actions/cache@v3 From 39fea20cf51f9f8185ebc4d41c05e779de331299 Mon Sep 17 00:00:00 2001 From: shodan Date: Sun, 26 Nov 2023 23:27:38 +0100 Subject: [PATCH 16/17] fix ci --- .github/workflows/node.js.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/node.js.yml b/.github/workflows/node.js.yml index e868bb6c..16283182 100644 --- a/.github/workflows/node.js.yml +++ b/.github/workflows/node.js.yml @@ -17,7 +17,7 @@ jobs: with: node-version: ${{ matrix.node-version }} - name: Install OS Packages - run: apt update && apt install libavahi-compat-libdnssd-dev \ + run: sudo apt update && sudo apt install libavahi-compat-libdnssd-dev \ - name: Cache node modules id: cache-npm uses: actions/cache@v3 From 2b347ffcf57883cd32965d6b65a0ad9387bf6ce1 Mon Sep 17 00:00:00 2001 From: shodan Date: Sun, 26 Nov 2023 23:29:06 +0100 Subject: [PATCH 17/17] limit ci --- .github/workflows/node.js.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/node.js.yml b/.github/workflows/node.js.yml index 16283182..3c50ed51 100644 --- a/.github/workflows/node.js.yml +++ b/.github/workflows/node.js.yml @@ -1,6 +1,10 @@ name: Node CI -on: [push, pull_request] +on: + pull_request: + push: + branches: + - 'master' jobs: build: