@stoprocent/bluetooth-hci-socket
Advanced tools
Comparing version 1.2.1 to 1.3.0
@@ -149,3 +149,3 @@ const BluetoothHciSocket = require('../index'); | ||
cmd.writeUInt8(0x00, 10); // direct addr type | ||
(Buffer.alloc('000000000000', 'hex')).copy(cmd, 11); // direct addr | ||
(Buffer.from('000000000000', 'hex')).copy(cmd, 11); // direct addr | ||
cmd.writeUInt8(0x07, 17); | ||
@@ -223,4 +223,4 @@ cmd.writeUInt8(0x00, 18); | ||
setAdvertisingParameter(); | ||
setScanResponseData(Buffer.alloc('0909657374696d6f74650e160a182eb8855fb5ddb601000200', 'hex')); | ||
setAdvertisingData(Buffer.alloc('0201061aff4c000215b9407f30f5f8466eaff925556b57fe6d00010002b6', 'hex')); | ||
setScanResponseData(Buffer.from('0909657374696d6f74650e160a182eb8855fb5ddb601000200', 'hex')); | ||
setAdvertisingData(Buffer.from('0201061aff4c000215b9407f30f5f8466eaff925556b57fe6d00010002b6', 'hex')); | ||
setAdvertiseEnable(true); |
@@ -57,3 +57,3 @@ const BluetoothHciSocket = require('../index'); | ||
writeHandle(handle, Buffer.alloc('020001', 'hex')); | ||
writeHandle(handle, Buffer.from('020001', 'hex')); | ||
} | ||
@@ -147,3 +147,3 @@ } | ||
cmd.writeUInt8(addressType === 'random' ? 0x01 : 0x00, 9); // peer address type | ||
(Buffer.alloc(address.split(':').reverse().join(''), 'hex')).copy(cmd, 10); // peer address | ||
(Buffer.from(address.split(':').reverse().join(''), 'hex')).copy(cmd, 10); // peer address | ||
@@ -150,0 +150,0 @@ cmd.writeUInt8(0x00, 16); // own address type |
271
lib/uart.js
@@ -1,4 +0,2 @@ | ||
const events = require('events'); | ||
const util = require('util'); | ||
const EventEmitter = require('events'); | ||
const debug = require('debug')('hci-uart'); | ||
@@ -10,181 +8,178 @@ const { SerialPort } = require('serialport'); | ||
const HCI_COMMAND_PKT = 0x01; | ||
// eslint-disable-next-line no-unused-vars | ||
const HCI_ACLDATA_PKT = 0x02; | ||
// eslint-disable-next-line no-unused-vars | ||
const HCI_EVENT_PKT = 0x04; | ||
const OGF_HOST_CTL = 0x03; | ||
const OCF_RESET = 0x0003; | ||
const OCF_SET_EVENT_FILTER = 0x0005; | ||
const SET_EVENT_FILTER_CMD = OCF_SET_EVENT_FILTER | OGF_HOST_CTL << 10; | ||
const SET_EVENT_FILTER_CMD = OCF_SET_EVENT_FILTER | (OGF_HOST_CTL << 10); | ||
const RESET_CMD = OCF_RESET | (OGF_HOST_CTL << 10); | ||
function BluetoothHciSocket (useFilter = false) { | ||
this._isUp = false; | ||
this._reset = null; | ||
this._useFilter = useFilter; | ||
} | ||
class BluetoothHciSocket extends EventEmitter { | ||
constructor (useFilter = false) { | ||
super(); | ||
this._isUp = false; | ||
this._useFilter = useFilter; | ||
this._mode = null; | ||
this._serialDevice = null; | ||
this._queue = null; | ||
this._parser = null; | ||
} | ||
util.inherits(BluetoothHciSocket, events.EventEmitter); | ||
setFilter (filter) { | ||
if (!this._useFilter) { | ||
return; | ||
} | ||
BluetoothHciSocket.prototype.setFilter = function (filter) { | ||
if (this._useFilter === false) { | ||
return; | ||
const header = Buffer.alloc(4); | ||
header.writeUInt8(HCI_COMMAND_PKT, 0); | ||
header.writeUInt16LE(SET_EVENT_FILTER_CMD, 1); | ||
header.writeUInt8(filter.length, 3); | ||
const cmd = Buffer.concat([header, filter]); | ||
this.write(cmd); | ||
} | ||
// Filter Header | ||
let cmd = Buffer.alloc(4); | ||
cmd.writeUInt8(HCI_COMMAND_PKT, 0); | ||
cmd.writeUInt16LE(SET_EVENT_FILTER_CMD, 1); | ||
// Length | ||
cmd.writeUInt8(filter.length, 3); | ||
bindRaw (devId, params) { | ||
this.bindUser(devId, params); | ||
this._mode = 'raw'; | ||
this.reset(); | ||
} | ||
// Concate Buffers | ||
cmd = Buffer.concat([cmd, filter]); | ||
bindUser (devId, params) { | ||
this._mode = 'user'; | ||
const uartParams = this._getSerialParams(params); | ||
this.write(cmd); | ||
}; | ||
const { port, baudRate } = uartParams.uart; | ||
if (typeof port === 'string' && Number.isInteger(baudRate)) { | ||
debug(`Using UART PORT = ${port}, BAUD RATE = ${baudRate}`); | ||
BluetoothHciSocket.prototype.bindRaw = function (devId, params) { | ||
this.bindUser(devId, params); | ||
this._serialDevice = new SerialPort({ | ||
path: port, | ||
baudRate, | ||
autoOpen: false, | ||
flowControl: true | ||
}); | ||
} else { | ||
throw new Error('Invalid UART parameters'); | ||
} | ||
this._mode = 'raw'; | ||
if (!this._serialDevice) { | ||
throw new Error('No compatible UART device found!'); | ||
} | ||
this.reset(); | ||
}; | ||
this._queue = async.queue((data, callback) => { | ||
this._serialDevice.write(data, callback); | ||
}); | ||
this._queue.pause(); | ||
BluetoothHciSocket.prototype.bindUser = function (devId, params) { | ||
this._mode = 'user'; | ||
this._parser = this._serialDevice.pipe(new HciSerialParser()); | ||
this._parser.on('raw', this.waitForReset.bind(this)); | ||
const uartParams = this._getSerialParams(params); | ||
if ((typeof uartParams.uart.port === 'string' || uartParams.uart.port instanceof String) && Number.isInteger(uartParams.uart.baudRate)) { | ||
debug('using UART PORT = ' + uartParams.uart.port + ', BAUD RATE = ' + uartParams.uart.baudRate); | ||
this._serialDevice = new SerialPort({ | ||
path: uartParams.uart.port, | ||
baudRate: uartParams.uart.baudRate, | ||
autoOpen: false, | ||
flowControl: true | ||
this._serialDevice.on('error', (error) => this.emit('error', error)); | ||
this._serialDevice.on('close', () => { | ||
this._isUp = false; | ||
this.emit('state', this._isUp); | ||
}); | ||
} | ||
if (!this._serialDevice) { | ||
throw new Error('No compatible UART device found!'); | ||
this._serialDevice.open(); | ||
} | ||
// Message Queue | ||
this._queue = async.queue((data, callback) => this._serialDevice.write(data, (a, b) => callback())); | ||
this._queue.pause(); | ||
_getSerialParams (params) { | ||
let port; | ||
let baudRate = 1000000; // Default baud rate | ||
// Serial Port Parser | ||
this._parser = this._serialDevice.pipe(new HciSerialParser()); | ||
this._parser.on('raw', this.waitForReset.bind(this)); | ||
// Check for UART port in environment variables | ||
if (process.env.BLUETOOTH_HCI_SOCKET_UART_PORT) { | ||
port = process.env.BLUETOOTH_HCI_SOCKET_UART_PORT; | ||
} | ||
// Serial Port Event Listeners | ||
this._serialDevice.on('error', error => this.emit('error', error)); | ||
this._serialDevice.on('close', () => { | ||
this.isDevUp = false; | ||
this.emit('state', this._isUp); | ||
}); | ||
// Check for UART baud rate in environment variables | ||
if (process.env.BLUETOOTH_HCI_SOCKET_UART_BAUDRATE) { | ||
const parsedBaudRate = parseInt(process.env.BLUETOOTH_HCI_SOCKET_UART_BAUDRATE, 10); | ||
if (!isNaN(parsedBaudRate)) { | ||
baudRate = parsedBaudRate; | ||
} | ||
} | ||
// Open Serial Port to begin | ||
this._serialDevice.open(); | ||
}; | ||
BluetoothHciSocket.prototype._getSerialParams = function (params) { | ||
const uartParams = { | ||
uart: { | ||
port: undefined, baudRate: 1000000 | ||
// Override with params if provided | ||
if (params && params.uart) { | ||
if (params.uart.port && typeof params.uart.port === 'string') { | ||
port = params.uart.port; | ||
} | ||
if (params.uart.baudRate && typeof params.uart.baudRate === 'number' && isFinite(params.uart.baudRate)) { | ||
baudRate = params.uart.baudRate; | ||
} | ||
} | ||
}; | ||
if (process.env.BLUETOOTH_HCI_SOCKET_UART_PORT) { | ||
uartParams.uart.port = process.env.BLUETOOTH_HCI_SOCKET_UART_PORT; | ||
return { uart: { port, baudRate } }; | ||
} | ||
if (process.env.BLUETOOTH_HCI_SOCKET_UART_BAUDRATE) { | ||
uartParams.uart.baudRate = parseInt(process.env.BLUETOOTH_HCI_SOCKET_UART_BAUDRATE, 10); | ||
bindControl () { | ||
this._mode = 'control'; | ||
} | ||
if (params && params.uart) { | ||
if (params.uart.port instanceof String || typeof params.uart.port === 'string') { | ||
uartParams.uart.port = params.uart.port; | ||
} | ||
if (Number.isInteger(params.uart.baudRate)) { | ||
uartParams.uart.baudRate = params.uart.baudRate; | ||
} | ||
isDevUp () { | ||
return this._isUp; | ||
} | ||
return uartParams; | ||
}; | ||
waitForReset (data) { | ||
const resetPatterns = [ | ||
Buffer.from('040e0401030c00', 'hex'), | ||
Buffer.from('040e0402030c00', 'hex'), | ||
Buffer.from('040e0405030c00', 'hex') | ||
]; | ||
BluetoothHciSocket.prototype.bindControl = function () { | ||
this._mode = 'control'; | ||
}; | ||
BluetoothHciSocket.prototype.isDevUp = function () { | ||
return this._isUp; | ||
}; | ||
BluetoothHciSocket.prototype.waitForReset = function (data) { | ||
// Handle Reset | ||
if (this._isUp === false && this._mode === 'raw' && (data.includes(Buffer.from('040e0401030c00', 'hex')) || data.includes(Buffer.from('040e0402030c00', 'hex')) || data.includes(Buffer.from('040e0405030c00', 'hex')))) { | ||
debug('reset complete'); | ||
// Remove this listener | ||
this._parser.removeAllListeners('raw'); | ||
// Reset parser just in case we have noisy data | ||
this._parser.reset(); | ||
// Resume other writes | ||
this._queue.resume(); | ||
// Mark UP | ||
this._isUp = true; | ||
this.emit('state', this._isUp); | ||
if ( | ||
!this._isUp && | ||
this._mode === 'raw' && | ||
resetPatterns.some((pattern) => data.includes(pattern)) | ||
) { | ||
debug('Reset complete'); | ||
this._parser.removeAllListeners('raw'); | ||
this._parser.reset(); | ||
this._queue.resume(); | ||
this._isUp = true; | ||
this.emit('state', this._isUp); | ||
} | ||
} | ||
}; | ||
BluetoothHciSocket.prototype.start = function () { | ||
if (this._mode === 'raw' || this._mode === 'user') { | ||
// Cleanup | ||
this._parser.removeAllListeners('data'); | ||
// Register | ||
this._parser.on('data', (data) => { | ||
// Skip the first reset | ||
if (this._isUp === true) { | ||
// Emit Data Event on HCI | ||
this.emit('data', data); | ||
} | ||
}); | ||
start () { | ||
if (this._mode === 'raw' || this._mode === 'user') { | ||
this._parser.removeAllListeners('data'); | ||
this._parser.on('data', (data) => { | ||
if (this._isUp) { | ||
this.emit('data', data); | ||
} | ||
}); | ||
} | ||
} | ||
}; | ||
BluetoothHciSocket.prototype.stop = function () { | ||
if (this._mode === 'raw' || this._mode === 'user') { | ||
this._parser.removeAllListeners('data'); | ||
stop () { | ||
if (this._mode === 'raw' || this._mode === 'user') { | ||
this._parser.removeAllListeners('data'); | ||
} | ||
} | ||
}; | ||
BluetoothHciSocket.prototype.write = function (data) { | ||
debug('write: ' + data.toString('hex')); | ||
if (this._mode === 'raw' || this._mode === 'user') { | ||
this._queue.push(data); | ||
write (data) { | ||
debug(`Write: ${data.toString('hex')}`); | ||
if (this._mode === 'raw' || this._mode === 'user') { | ||
this._queue.push(data); | ||
} | ||
} | ||
}; | ||
BluetoothHciSocket.prototype.reset = function () { | ||
const cmd = Buffer.alloc(4); | ||
reset () { | ||
if (!this._serialDevice) { | ||
throw new Error('Serial device is not initialized'); | ||
} | ||
// header | ||
cmd.writeUInt8(HCI_COMMAND_PKT, 0); | ||
cmd.writeUInt16LE(RESET_CMD, 1); | ||
const cmd = Buffer.alloc(4); | ||
cmd.writeUInt8(HCI_COMMAND_PKT, 0); | ||
cmd.writeUInt16LE(RESET_CMD, 1); | ||
cmd.writeUInt8(0x00, 3); | ||
// length | ||
cmd.writeUInt8(0x00, 3); | ||
debug(`Reset: ${cmd.toString('hex')}`); | ||
this._serialDevice.write(cmd); | ||
} | ||
} | ||
debug('reset:', cmd.toString('hex')); | ||
this._serialDevice.write(cmd); | ||
}; | ||
module.exports = BluetoothHciSocket; |
@@ -10,12 +10,11 @@ const debug = require('debug')('hci-serial-parser'); | ||
constructor (options) { | ||
super(); | ||
super(options); | ||
this.reset(); | ||
} | ||
_transform (chunk, encoding, cb) { | ||
_transform (chunk, encoding, callback) { | ||
this.packetData = Buffer.concat([this.packetData, chunk]); | ||
debug('HciPacketParser._transform:', this.packetData.toString('hex')); | ||
debug('HciPacketParser._transform: ', this.packetData.toString('hex')); | ||
if (this.packetType === -1) { | ||
if (this.packetType === -1 && this.packetData.length > 0) { | ||
this.packetType = this.packetData.readUInt8(0); | ||
@@ -28,19 +27,18 @@ } | ||
let skipPacket = false; | ||
while (this.packetData.length >= this.packetSize + this.prePacketSize && !skipPacket) { | ||
if (this.packetSize === 0 && (this.packetType === HCI_EVENT_PKT || this.packetType === HCI_COMMAND_PKT) && this.packetData.length >= 3) { | ||
this.packetSize = this.packetData.readUInt8(2); | ||
this.prePacketSize = 3; | ||
} else if (this.packetSize === 0 && this.packetType === HCI_ACLDATA_PKT && this.packetData.length >= 5) { | ||
this.packetSize = this.packetData.readUInt16LE(3); | ||
this.prePacketSize = 5; | ||
while (this.packetData.length > 0) { | ||
if (this.packetSize === 0) { | ||
if (!this._determinePacketSize()) { | ||
break; | ||
} | ||
} | ||
if (this.packetData.length < this.packetSize + this.prePacketSize || this.packetSize === 0) { | ||
skipPacket = true; continue; | ||
if (this.packetData.length < this.prePacketSize + this.packetSize) { | ||
break; | ||
} | ||
this.push(this.packetData.subarray(0, this.packetSize + this.prePacketSize)); | ||
const packet = this.packetData.slice(0, this.prePacketSize + this.packetSize); | ||
this.push(packet); | ||
this.packetData = this.packetData.subarray(this.packetSize + this.prePacketSize); | ||
this.packetData = this.packetData.slice(this.prePacketSize + this.packetSize); | ||
this.packetType = -1; | ||
this.packetSize = 0; | ||
@@ -55,16 +53,44 @@ this.prePacketSize = 0; | ||
} | ||
cb(); | ||
callback(); | ||
} | ||
_determinePacketSize () { | ||
if (this.packetData.length < 1) { | ||
return false; | ||
} | ||
const packetType = this.packetData.readUInt8(0); | ||
if (packetType === HCI_EVENT_PKT || packetType === HCI_COMMAND_PKT) { | ||
if (this.packetData.length >= 3) { | ||
this.prePacketSize = 3; | ||
this.packetSize = this.packetData.readUInt8(2); | ||
return true; | ||
} | ||
} else if (packetType === HCI_ACLDATA_PKT) { | ||
if (this.packetData.length >= 5) { | ||
this.prePacketSize = 5; | ||
this.packetSize = this.packetData.readUInt16LE(3); | ||
return true; | ||
} | ||
} else { | ||
this.emit('error', new Error(`Unknown packet type: ${packetType}`)); | ||
} | ||
return false; | ||
} | ||
reset () { | ||
this.packetData = Buffer.alloc(0); | ||
this.packetType = -1; | ||
this.packetSize = 0; | ||
this.prePacketSize = 0; | ||
this.packetType = -1; | ||
this.packetData = Buffer.alloc(0); | ||
} | ||
_flush (cb) { | ||
this.emit('raw', this.packetData); | ||
_flush (callback) { | ||
if (this.listenerCount('raw') > 0 && this.packetData.length > 0) { | ||
this.emit('raw', this.packetData); | ||
} | ||
this.reset(); | ||
cb(); | ||
callback(); | ||
} | ||
@@ -71,0 +97,0 @@ } |
{ | ||
"name": "@stoprocent/bluetooth-hci-socket", | ||
"version": "1.2.1", | ||
"version": "1.3.0", | ||
"description": "Bluetooth HCI socket binding for Node.js", | ||
@@ -34,32 +34,37 @@ "main": "index.js", | ||
"dependencies": { | ||
"debug": "^4.3.4", | ||
"nan": "^2.17.0", | ||
"node-addon-api": "^4.3.0", | ||
"node-gyp-build": "^4.6.1", | ||
"async": "^3.2.4", | ||
"serialport": "^12.0.0" | ||
"debug": "^4.3.7", | ||
"node-addon-api": "^8.1.0", | ||
"node-gyp-build": "^4.8.1", | ||
"async": "^3.2.6", | ||
"serialport": "^12.0.0", | ||
"patch-package": "^8.0.0" | ||
}, | ||
"optionalDependencies": { | ||
"usb": "^1.9.2" | ||
"usb": "^2.14.0" | ||
}, | ||
"devDependencies": { | ||
"@semantic-release/exec": "6.0.3", | ||
"eslint": "^8.31.0", | ||
"eslint-config-semistandard": "^17.0.0", | ||
"eslint-config-standard": "^17.0.0", | ||
"eslint-plugin-import": "^2.26.0", | ||
"eslint-plugin-n": "^15.6.0", | ||
"eslint-plugin-promise": "^6.1.1", | ||
"jshint": "^2.13.6", | ||
"node-gyp": "^10.0.0", | ||
"prebuildify": "^5.0.1", | ||
"prebuildify-cross": "5.0.0", | ||
"semantic-release": "21.1.0" | ||
"@commitlint/cli": "^19.5.0", | ||
"@commitlint/config-conventional": "^19.5.0", | ||
"@semantic-release/changelog": "^6.0.3", | ||
"@semantic-release/exec": "^6.0.3", | ||
"@semantic-release/git": "^10.0.1", | ||
"@semantic-release/github": "^10.1.1", | ||
"eslint": "^8.57.1", | ||
"eslint-plugin-import": "^2.30.0", | ||
"eslint-plugin-n": "^17.10.3", | ||
"eslint-plugin-promise": "^7.1.0", | ||
"mocha": "^10.7.0", | ||
"nyc": "^17.0.0", | ||
"prebuildify": "^6.0.1", | ||
"prebuildify-cross": "^5.1.0", | ||
"semantic-release": "^24.1.1", | ||
"jshint": "^2.13.6" | ||
}, | ||
"scripts": { | ||
"install": "node-gyp-build", | ||
"postinstall": "patch-package", | ||
"lint": "eslint \"**/*.js\"", | ||
"lint-fix": "eslint \"**/*.js\" --fix", | ||
"prebuildify": "prebuildify --napi --target 14.0.0 --force --strip --verbose", | ||
"prebuildify-cross": "prebuildify-cross --napi --target 14.0.0 --force --strip --verbose", | ||
"prebuildify": "prebuildify --napi --target 17.0.0 --force --strip --verbose", | ||
"prebuildify-cross": "prebuildify-cross --napi --target 17.0.0 --force --strip --verbose", | ||
"semantic-release": "semantic-release", | ||
@@ -66,0 +71,0 @@ "pretest": "npm run rebuild", |
# node-bluetooth-hci-socket | ||
[![GitHub forks]( | ||
https://img.shields.io/github/forks/abandonware/node-bluetooth-hci-socket.svg?style=social&label=Fork&maxAge=2592000 | ||
https://img.shields.io/github/forks/stoprocent/node-bluetooth-hci-socket.svg?style=social&label=Fork&maxAge=2592000 | ||
)]( | ||
https://GitHub.com/abandonware/node-bluetooth-hci-socket/network/ | ||
https://GitHub.com/stoprocent/node-bluetooth-hci-socket/network/ | ||
) | ||
@@ -12,5 +12,5 @@ [![license]( | ||
[![NPM]( | ||
https://img.shields.io/npm/v/@abandonware/bluetooth-hci-socket.svg | ||
https://img.shields.io/npm/v/@stoprocent/bluetooth-hci-socket.svg | ||
)]( | ||
https://www.npmjs.com/package/@abandonware/bluetooth-hci-socket | ||
https://www.npmjs.com/package/@stoprocent/bluetooth-hci-socket | ||
) | ||
@@ -30,3 +30,3 @@ [![Fediverse]( | ||
__NOTE:__ Currently only supports __Linux__, __FreeBSD__ and __Windows__. | ||
__NOTE:__ Currently only supports __Linux__, __FreeBSD__, __Windows__ or any operating systems when using HCI over uart. | ||
@@ -93,3 +93,3 @@ ## Prerequisites | ||
```sh | ||
npm install @abandonware/bluetooth-hci-socket | ||
npm install @stoprocent/bluetooth-hci-socket | ||
``` | ||
@@ -100,3 +100,3 @@ | ||
```javascript | ||
var BluetoothHciSocket = require('@abandonware/bluetooth-hci-socket'); | ||
var BluetoothHciSocket = require('@stoprocent/bluetooth-hci-socket'); | ||
``` | ||
@@ -207,3 +207,3 @@ | ||
See [examples folder](https://github.com/abandonware/node-bluetooth-hci-socket/blob/master/examples) for code examples. | ||
See [examples folder](https://github.com/stoprocent/node-bluetooth-hci-socket/blob/master/examples) for code examples. | ||
@@ -210,0 +210,0 @@ ## Platform Notes |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Install scripts
Supply chain riskInstall scripts are run when the package is installed. The majority of malware in npm is hidden in install scripts.
Found 1 instance in 1 package
Native code
Supply chain riskContains native code (e.g., compiled binaries or shared libraries). Including native code can obscure malicious behavior.
Found 9 instances in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Native code
Supply chain riskContains native code (e.g., compiled binaries or shared libraries). Including native code can obscure malicious behavior.
Found 2 instances in 1 package
949194
34
1104
16
1
10
+ Addedpatch-package@^8.0.0
+ Added@types/w3c-web-usb@1.0.10(transitive)
+ Added@yarnpkg/lockfile@1.1.0(transitive)
+ Addedansi-styles@4.3.0(transitive)
+ Addedat-least-node@1.0.0(transitive)
+ Addedbalanced-match@1.0.2(transitive)
+ Addedbrace-expansion@1.1.11(transitive)
+ Addedbraces@3.0.3(transitive)
+ Addedcall-bind@1.0.7(transitive)
+ Addedchalk@4.1.2(transitive)
+ Addedci-info@3.9.0(transitive)
+ Addedcolor-convert@2.0.1(transitive)
+ Addedcolor-name@1.1.4(transitive)
+ Addedconcat-map@0.0.1(transitive)
+ Addedcross-spawn@7.0.5(transitive)
+ Addeddefine-data-property@1.1.4(transitive)
+ Addedes-define-property@1.0.0(transitive)
+ Addedes-errors@1.3.0(transitive)
+ Addedfill-range@7.1.1(transitive)
+ Addedfind-yarn-workspace-root@2.0.0(transitive)
+ Addedfs-extra@9.1.0(transitive)
+ Addedfs.realpath@1.0.0(transitive)
+ Addedfunction-bind@1.1.2(transitive)
+ Addedget-intrinsic@1.2.4(transitive)
+ Addedglob@7.2.3(transitive)
+ Addedgopd@1.0.1(transitive)
+ Addedgraceful-fs@4.2.11(transitive)
+ Addedhas-flag@4.0.0(transitive)
+ Addedhas-property-descriptors@1.0.2(transitive)
+ Addedhas-proto@1.0.3(transitive)
+ Addedhas-symbols@1.0.3(transitive)
+ Addedhasown@2.0.2(transitive)
+ Addedinflight@1.0.6(transitive)
+ Addedinherits@2.0.4(transitive)
+ Addedis-docker@2.2.1(transitive)
+ Addedis-number@7.0.0(transitive)
+ Addedis-wsl@2.2.0(transitive)
+ Addedisarray@2.0.5(transitive)
+ Addedisexe@2.0.0(transitive)
+ Addedjson-stable-stringify@1.1.1(transitive)
+ Addedjsonfile@6.1.0(transitive)
+ Addedjsonify@0.0.1(transitive)
+ Addedklaw-sync@6.0.0(transitive)
+ Addedmicromatch@4.0.8(transitive)
+ Addedminimatch@3.1.2(transitive)
+ Addedminimist@1.2.8(transitive)
+ Addednode-addon-api@8.2.2(transitive)
+ Addedobject-keys@1.1.1(transitive)
+ Addedonce@1.4.0(transitive)
+ Addedopen@7.4.2(transitive)
+ Addedos-tmpdir@1.0.2(transitive)
+ Addedpatch-package@8.0.0(transitive)
+ Addedpath-is-absolute@1.0.1(transitive)
+ Addedpath-key@3.1.1(transitive)
+ Addedpicomatch@2.3.1(transitive)
+ Addedrimraf@2.7.1(transitive)
+ Addedsemver@7.6.3(transitive)
+ Addedset-function-length@1.2.2(transitive)
+ Addedshebang-command@2.0.0(transitive)
+ Addedshebang-regex@3.0.0(transitive)
+ Addedslash@2.0.0(transitive)
+ Addedsupports-color@7.2.0(transitive)
+ Addedtmp@0.0.33(transitive)
+ Addedto-regex-range@5.0.1(transitive)
+ Addeduniversalify@2.0.1(transitive)
+ Addedusb@2.14.0(transitive)
+ Addedwhich@2.0.2(transitive)
+ Addedwrappy@1.0.2(transitive)
+ Addedyaml@2.6.0(transitive)
- Removednan@^2.17.0
- Removednan@2.22.0(transitive)
- Removednode-addon-api@4.3.0(transitive)
- Removedusb@1.9.2(transitive)
Updatedasync@^3.2.6
Updateddebug@^4.3.7
Updatednode-addon-api@^8.1.0
Updatednode-gyp-build@^4.8.1