Comparing version 2.0.0-alpha.2 to 2.0.1
@@ -18,2 +18,11 @@ /// <reference types="node" /> | ||
export declare function _disableHotplugEvents(): void; | ||
export declare function _getLibusbCapability(capability: number): number; | ||
/** | ||
* Restore (re-reference) the hotplug events unreferenced by `unrefHotplugEvents()` | ||
*/ | ||
export declare function refHotplugEvents(): void; | ||
/** | ||
* Unreference the hotplug events from the event loop, allowing the process to exit even when listening for the `attach` and `detach` events | ||
*/ | ||
export declare function unrefHotplugEvents(): void; | ||
/** Represents a USB transfer */ | ||
@@ -216,2 +225,6 @@ export declare class Transfer { | ||
export declare const LIBUSB_DT_BOS_SIZE: number; | ||
export declare const LIBUSB_CAP_HAS_CAPABILITY: number; | ||
export declare const LIBUSB_CAP_HAS_HOTPLUG: number; | ||
export declare const LIBUSB_CAP_HAS_HID_ACCESS: number; | ||
export declare const LIBUSB_CAP_SUPPORTS_DETACH_KERNEL_DRIVER: number; | ||
/** Input/output error */ | ||
@@ -218,0 +231,0 @@ export declare const LIBUSB_ERROR_IO: number; |
@@ -6,5 +6,6 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
var path_1 = require("path"); | ||
/* eslint-disable @typescript-eslint/no-var-requires */ | ||
var usb = require('bindings')('usb_bindings'); | ||
var usb = require('node-gyp-build')(path_1.join(__dirname, '..', '..')); | ||
module.exports = usb; | ||
//# sourceMappingURL=bindings.js.map |
"use strict"; | ||
var __values = (this && this.__values) || function(o) { | ||
var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0; | ||
if (m) return m.call(o); | ||
if (o && typeof o.length === "number") return { | ||
next: function () { | ||
if (o && i >= o.length) o = void 0; | ||
return { value: o && o[i++], done: !o }; | ||
} | ||
}; | ||
throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined."); | ||
}; | ||
var events_1 = require("events"); | ||
@@ -13,2 +24,65 @@ var device_1 = require("./device"); | ||
}); | ||
// Polling mechanism for discovering device changes until this is fixed: | ||
// https://github.com/libusb/libusb/issues/86 | ||
var pollTimeout = 500; | ||
var hotplugSupported = usb._getLibusbCapability(usb.LIBUSB_CAP_HAS_HOTPLUG) > 0; | ||
var pollingHotplug = false; | ||
var pollDevices = []; | ||
var pollHotplug = function (start) { | ||
var e_1, _a, e_2, _b; | ||
if (start === void 0) { start = false; } | ||
if (start) { | ||
pollingHotplug = true; | ||
} | ||
else if (!pollingHotplug) { | ||
return; | ||
} | ||
var devices = usb.getDeviceList(); | ||
if (!start) { | ||
var _loop_1 = function (device) { | ||
var found = pollDevices.find(function (item) { return item.deviceAddress === device.deviceAddress; }); | ||
if (!found) { | ||
usb.emit('attach', device); | ||
} | ||
}; | ||
try { | ||
// Find attached devices | ||
for (var devices_1 = __values(devices), devices_1_1 = devices_1.next(); !devices_1_1.done; devices_1_1 = devices_1.next()) { | ||
var device = devices_1_1.value; | ||
_loop_1(device); | ||
} | ||
} | ||
catch (e_1_1) { e_1 = { error: e_1_1 }; } | ||
finally { | ||
try { | ||
if (devices_1_1 && !devices_1_1.done && (_a = devices_1.return)) _a.call(devices_1); | ||
} | ||
finally { if (e_1) throw e_1.error; } | ||
} | ||
var _loop_2 = function (device) { | ||
var found = devices.find(function (item) { return item.deviceAddress === device.deviceAddress; }); | ||
if (!found) { | ||
usb.emit('detach', device); | ||
} | ||
}; | ||
try { | ||
// Find detached devices | ||
for (var pollDevices_1 = __values(pollDevices), pollDevices_1_1 = pollDevices_1.next(); !pollDevices_1_1.done; pollDevices_1_1 = pollDevices_1.next()) { | ||
var device = pollDevices_1_1.value; | ||
_loop_2(device); | ||
} | ||
} | ||
catch (e_2_1) { e_2 = { error: e_2_1 }; } | ||
finally { | ||
try { | ||
if (pollDevices_1_1 && !pollDevices_1_1.done && (_b = pollDevices_1.return)) _b.call(pollDevices_1); | ||
} | ||
finally { if (e_2) throw e_2.error; } | ||
} | ||
} | ||
pollDevices = devices; | ||
setTimeout(function () { | ||
pollHotplug(); | ||
}, pollTimeout); | ||
}; | ||
usb.on('newListener', function (event) { | ||
@@ -20,3 +94,8 @@ if (event !== 'attach' && event !== 'detach') { | ||
if (listenerCount === 0) { | ||
usb._enableHotplugEvents(); | ||
if (hotplugSupported) { | ||
usb._enableHotplugEvents(); | ||
} | ||
else { | ||
pollHotplug(true); | ||
} | ||
} | ||
@@ -30,3 +109,8 @@ }); | ||
if (listenerCount === 0) { | ||
usb._disableHotplugEvents(); | ||
if (hotplugSupported) { | ||
usb._disableHotplugEvents(); | ||
} | ||
else { | ||
pollingHotplug = false; | ||
} | ||
} | ||
@@ -33,0 +117,0 @@ }); |
/// <reference types="w3c-web-usb" /> | ||
import { TypedEventTarget } from './typed-event-target'; | ||
/// <reference types="node" /> | ||
import { EventEmitter } from 'events'; | ||
/** | ||
@@ -8,25 +9,33 @@ * USB Options | ||
/** | ||
* A `device found` callback function to allow the user to select a device | ||
* Optional `device found` callback function to allow the user to select a device | ||
*/ | ||
devicesFound?: (devices: Array<USBDevice>) => Promise<USBDevice | void>; | ||
} | ||
/** | ||
* @hidden | ||
*/ | ||
export declare type USBEvents = { | ||
devicesFound?: (devices: USBDevice[]) => Promise<USBDevice | void>; | ||
/** | ||
* USBDevice connected event | ||
* Optional array of preconfigured allowed devices | ||
*/ | ||
connect: USBConnectionEvent; | ||
allowedDevices?: USBDeviceFilter[]; | ||
/** | ||
* USBDevice disconnected event | ||
* Optional flag to automatically allow all devices | ||
*/ | ||
disconnect: USBConnectionEvent; | ||
}; | ||
export declare class WebUSB extends TypedEventTarget<USBEvents> implements USB { | ||
allowAllDevices?: boolean; | ||
/** | ||
* Optional timeout (in milliseconds) to use for the device control transfers | ||
*/ | ||
deviceTimeout?: number; | ||
} | ||
export declare class WebUSB implements USB { | ||
private options; | ||
private allowedDevices; | ||
protected emitter: EventEmitter; | ||
protected knownDevices: Map<string, USBDevice>; | ||
protected allowedDevices: USBDeviceFilter[]; | ||
constructor(options?: USBOptions); | ||
set onconnect(listener: (event: USBConnectionEvent) => void); | ||
set ondisconnect(listener: (event: USBConnectionEvent) => void); | ||
private _onconnect; | ||
set onconnect(fn: (ev: USBConnectionEvent) => void); | ||
private _ondisconnect; | ||
set ondisconnect(fn: (ev: USBConnectionEvent) => void); | ||
addEventListener(type: 'connect' | 'disconnect', listener: (this: this, ev: USBConnectionEvent) => void): void; | ||
addEventListener(type: 'connect' | 'disconnect', listener: EventListener): void; | ||
removeEventListener(type: 'connect' | 'disconnect', callback: (this: this, ev: USBConnectionEvent) => void): void; | ||
removeEventListener(type: 'connect' | 'disconnect', callback: EventListener): void; | ||
dispatchEvent(_event: Event): boolean; | ||
/** | ||
@@ -45,5 +54,5 @@ * Requests a single Web USB device | ||
private preFilterDevices; | ||
private isSameDevice; | ||
private replaceAllowedDevice; | ||
private filterDevice; | ||
private getDeviceId; | ||
private isAllowedDevice; | ||
} |
"use strict"; | ||
var __extends = (this && this.__extends) || (function () { | ||
var extendStatics = function (d, b) { | ||
extendStatics = Object.setPrototypeOf || | ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || | ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; | ||
return extendStatics(d, b); | ||
}; | ||
return function (d, b) { | ||
if (typeof b !== "function" && b !== null) | ||
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); | ||
extendStatics(d, b); | ||
function __() { this.constructor = d; } | ||
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); | ||
}; | ||
})(); | ||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
@@ -67,16 +52,88 @@ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } | ||
var usb = require("../usb"); | ||
var events_1 = require("events"); | ||
var webusb_device_1 = require("./webusb-device"); | ||
var typed_event_target_1 = require("./typed-event-target"); | ||
var WebUSB = /** @class */ (function (_super) { | ||
__extends(WebUSB, _super); | ||
var WebUSB = /** @class */ (function () { | ||
function WebUSB(options) { | ||
var _this = this; | ||
if (options === void 0) { options = {}; } | ||
var _this = _super.call(this) || this; | ||
_this.options = options; | ||
_this.allowedDevices = []; | ||
return _this; | ||
this.options = options; | ||
this.emitter = new events_1.EventEmitter(); | ||
this.knownDevices = new Map(); | ||
this.allowedDevices = options.allowedDevices || []; | ||
var deviceConnectCallback = function (device) { return __awaiter(_this, void 0, void 0, function () { | ||
var webDevice, deviceId, event_1; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: return [4 /*yield*/, webusb_device_1.WebUSBDevice.createInstance(device)]; | ||
case 1: | ||
webDevice = _a.sent(); | ||
// When connected, emit an event if it is an allowed device | ||
if (webDevice && this.isAllowedDevice(webDevice)) { | ||
deviceId = this.getDeviceId(device); | ||
if (deviceId) { | ||
this.knownDevices.set(deviceId, webDevice); | ||
} | ||
event_1 = { | ||
type: 'connect', | ||
device: webDevice | ||
}; | ||
this.emitter.emit('connect', event_1); | ||
} | ||
return [2 /*return*/]; | ||
} | ||
}); | ||
}); }; | ||
var deviceDisconnectCallback = function (device) { return __awaiter(_this, void 0, void 0, function () { | ||
var deviceId, webDevice, event_2; | ||
return __generator(this, function (_a) { | ||
deviceId = this.getDeviceId(device); | ||
// When disconnected, emit an event if the device was a known allowed device | ||
if (deviceId !== undefined && this.knownDevices.has(deviceId)) { | ||
webDevice = this.knownDevices.get(deviceId); | ||
if (webDevice && this.isAllowedDevice(webDevice)) { | ||
event_2 = { | ||
type: 'disconnect', | ||
device: webDevice | ||
}; | ||
this.emitter.emit('disconnect', event_2); | ||
} | ||
} | ||
return [2 /*return*/]; | ||
}); | ||
}); }; | ||
this.emitter.on('newListener', function (event) { | ||
var listenerCount = _this.emitter.listenerCount(event); | ||
if (listenerCount !== 0) { | ||
return; | ||
} | ||
if (event === 'connect') { | ||
usb.addListener('attach', deviceConnectCallback); | ||
} | ||
else if (event === 'disconnect') { | ||
usb.addListener('detach', deviceDisconnectCallback); | ||
} | ||
}); | ||
this.emitter.on('removeListener', function (event) { | ||
var listenerCount = _this.emitter.listenerCount(event); | ||
if (listenerCount !== 0) { | ||
return; | ||
} | ||
if (event === 'connect') { | ||
usb.removeListener('attach', deviceConnectCallback); | ||
} | ||
else if (event === 'disconnect') { | ||
usb.removeListener('detach', deviceDisconnectCallback); | ||
} | ||
}); | ||
} | ||
Object.defineProperty(WebUSB.prototype, "onconnect", { | ||
set: function (listener) { | ||
this.addEventListener('connect', listener); | ||
set: function (fn) { | ||
if (this._onconnect) { | ||
this.removeEventListener('connect', this._onconnect); | ||
this._onconnect = undefined; | ||
} | ||
if (fn) { | ||
this._onconnect = fn; | ||
this.addEventListener('connect', this._onconnect); | ||
} | ||
}, | ||
@@ -87,4 +144,11 @@ enumerable: false, | ||
Object.defineProperty(WebUSB.prototype, "ondisconnect", { | ||
set: function (listener) { | ||
this.addEventListener('disconnect', listener); | ||
set: function (fn) { | ||
if (this._ondisconnect) { | ||
this.removeEventListener('disconnect', this._ondisconnect); | ||
this._ondisconnect = undefined; | ||
} | ||
if (fn) { | ||
this._ondisconnect = fn; | ||
this.addEventListener('disconnect', this._ondisconnect); | ||
} | ||
}, | ||
@@ -94,2 +158,12 @@ enumerable: false, | ||
}); | ||
WebUSB.prototype.addEventListener = function (type, listener) { | ||
this.emitter.addListener(type, listener); | ||
}; | ||
WebUSB.prototype.removeEventListener = function (type, callback) { | ||
this.emitter.removeListener(type, callback); | ||
}; | ||
WebUSB.prototype.dispatchEvent = function (_event) { | ||
// Don't dispatch from here | ||
return false; | ||
}; | ||
/** | ||
@@ -157,3 +231,3 @@ * Requests a single Web USB device | ||
} | ||
if (!this.replaceAllowedDevice(device)) { | ||
if (!this.isAllowedDevice(device)) { | ||
this.allowedDevices.push({ | ||
@@ -185,19 +259,14 @@ vendorId: device.vendorId, | ||
case 0: | ||
preFilters = this.allowedDevices.map(function (device) { return ({ | ||
vendorId: device.vendorId || undefined, | ||
productId: device.productId || undefined, | ||
serialNumber: device.serialNumber || undefined | ||
}); }); | ||
if (!this.options.allowAllDevices) { | ||
// Create pre-filters | ||
preFilters = this.allowedDevices.map(function (device) { return ({ | ||
vendorId: device.vendorId || undefined, | ||
productId: device.productId || undefined, | ||
serialNumber: device.serialNumber || undefined | ||
}); }); | ||
} | ||
return [4 /*yield*/, this.loadDevices(preFilters)]; | ||
case 1: | ||
devices = _a.sent(); | ||
devices = devices.filter(function (device) { | ||
for (var i in _this.allowedDevices) { | ||
if (_this.isSameDevice(device, _this.allowedDevices[i])) { | ||
return true; | ||
} | ||
} | ||
return false; | ||
}); | ||
return [2 /*return*/, devices]; | ||
return [2 /*return*/, devices.filter(function (device) { return _this.isAllowedDevice(device); })]; | ||
} | ||
@@ -209,3 +278,3 @@ }); | ||
return __awaiter(this, void 0, void 0, function () { | ||
var devices, webDevices, devices_1, devices_1_1, device, webDevice, e_1_1; | ||
var devices, webDevices, devices_1, devices_1_1, device, webDevice, deviceId, e_1_1; | ||
var e_1, _a; | ||
@@ -216,6 +285,4 @@ return __generator(this, function (_b) { | ||
devices = usb.getDeviceList(); | ||
if (preFilters) { | ||
// Pre-filter devices | ||
devices = this.preFilterDevices(devices, preFilters); | ||
} | ||
// Pre-filter devices | ||
devices = this.preFilterDevices(devices, preFilters); | ||
webDevices = []; | ||
@@ -230,6 +297,15 @@ _b.label = 1; | ||
device = devices_1_1.value; | ||
if (this.options.deviceTimeout) { | ||
device.timeout = this.options.deviceTimeout; | ||
} | ||
return [4 /*yield*/, webusb_device_1.WebUSBDevice.createInstance(device)]; | ||
case 3: | ||
webDevice = _b.sent(); | ||
webDevices.push(webDevice); | ||
if (webDevice) { | ||
webDevices.push(webDevice); | ||
deviceId = this.getDeviceId(device); | ||
if (deviceId) { | ||
this.knownDevices.set(deviceId, webDevice); | ||
} | ||
} | ||
_b.label = 4; | ||
@@ -256,2 +332,5 @@ case 4: | ||
WebUSB.prototype.preFilterDevices = function (devices, preFilters) { | ||
if (!preFilters || !preFilters.length) { | ||
return devices; | ||
} | ||
// Just pre-filter on vid/pid | ||
@@ -269,21 +348,6 @@ return devices.filter(function (device) { return preFilters.some(function (filter) { | ||
}; | ||
WebUSB.prototype.isSameDevice = function (device1, device2) { | ||
return (device1.productId === device2.productId | ||
&& device1.vendorId === device2.vendorId | ||
&& device1.serialNumber === device2.serialNumber); | ||
}; | ||
WebUSB.prototype.replaceAllowedDevice = function (device) { | ||
for (var i in this.allowedDevices) { | ||
if (this.isSameDevice(device, this.allowedDevices[i])) { | ||
this.allowedDevices[i] = { | ||
vendorId: device.vendorId, | ||
productId: device.productId, | ||
serialNumber: device.serialNumber | ||
}; | ||
return true; | ||
} | ||
WebUSB.prototype.filterDevice = function (options, device) { | ||
if (!options.filters || !options.filters.length) { | ||
return true; | ||
} | ||
return false; | ||
}; | ||
WebUSB.prototype.filterDevice = function (options, device) { | ||
return options.filters.some(function (filter) { | ||
@@ -333,5 +397,27 @@ // Vendor | ||
}; | ||
WebUSB.prototype.getDeviceId = function (device) { | ||
if (device.busNumber === undefined || device.deviceAddress === undefined) { | ||
return undefined; | ||
} | ||
return device.busNumber + "." + device.deviceAddress; | ||
}; | ||
WebUSB.prototype.isAllowedDevice = function (device) { | ||
if (this.options.allowAllDevices) { | ||
return true; | ||
} | ||
var isSameDevice = function (device1, device2) { | ||
return (device1.productId === device2.productId | ||
&& device1.vendorId === device2.vendorId | ||
&& device1.serialNumber === device2.serialNumber); | ||
}; | ||
for (var i in this.allowedDevices) { | ||
if (isSameDevice(device, this.allowedDevices[i])) { | ||
return true; | ||
} | ||
} | ||
return false; | ||
}; | ||
return WebUSB; | ||
}(typed_event_target_1.TypedEventTarget)); | ||
}()); | ||
exports.WebUSB = WebUSB; | ||
//# sourceMappingURL=index.js.map |
@@ -8,3 +8,3 @@ /// <reference types="w3c-web-usb" /> | ||
private device; | ||
static createInstance(device: usb.Device): Promise<WebUSBDevice>; | ||
static createInstance(device: usb.Device): Promise<WebUSBDevice | undefined>; | ||
readonly usbVersionMajor: number; | ||
@@ -11,0 +11,0 @@ readonly usbVersionMinor: number; |
@@ -82,11 +82,16 @@ "use strict"; | ||
return __awaiter(this, void 0, void 0, function () { | ||
var instance; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
var instance, _a; | ||
return __generator(this, function (_b) { | ||
switch (_b.label) { | ||
case 0: | ||
_b.trys.push([0, 2, , 3]); | ||
instance = new WebUSBDevice(device); | ||
return [4 /*yield*/, instance.initialize()]; | ||
case 1: | ||
_a.sent(); | ||
_b.sent(); | ||
return [2 /*return*/, instance]; | ||
case 2: | ||
_a = _b.sent(); | ||
return [2 /*return*/, undefined]; | ||
case 3: return [2 /*return*/]; | ||
} | ||
@@ -93,0 +98,0 @@ }); |
@@ -5,10 +5,10 @@ { | ||
"license": "MIT", | ||
"version": "2.0.0-alpha.2", | ||
"version": "2.0.1", | ||
"main": "dist/index.js", | ||
"engines": { | ||
"node": ">=10" | ||
"node": ">=10.16.0" | ||
}, | ||
"repository": { | ||
"type": "git", | ||
"url": "https://github.com/tessel/node-usb.git" | ||
"url": "https://github.com/node-usb/node-usb.git" | ||
}, | ||
@@ -41,4 +41,3 @@ "contributors": [ | ||
"prepare": "yarn compile", | ||
"install": "prebuild-install --runtime napi --verbose || node-gyp rebuild", | ||
"prebuild": "prebuild --runtime napi -t 4 --force --strip --verbose", | ||
"install": "node-gyp-build", | ||
"clean": "git clean -dfx", | ||
@@ -50,10 +49,18 @@ "compile": "tsc && yarn lint && yarn docs", | ||
"full-test": "mocha --require coffeescript/register test/*.coffee", | ||
"valgrind": "coffee -c test/usb.coffee; valgrind --leak-check=full --show-possibly-lost=no node --expose-gc --trace-gc node_modules/mocha/bin/_mocha -R spec", | ||
"docs": "typedoc" | ||
"valgrind": "coffee -c test/*.coffee; valgrind --leak-check=full --show-possibly-lost=no node --expose-gc --trace-gc node_modules/mocha/bin/_mocha -R spec", | ||
"docs": "typedoc", | ||
"prebuild": "prebuildify --napi --strip", | ||
"prebuild-darwin": "prebuildify --napi --strip --arch x64+arm64", | ||
"prebuild-win32-x86": "prebuildify --napi --strip", | ||
"prebuild-win32-x64": "prebuildify --napi --strip", | ||
"prebuild-linux-x86": "prebuildify-cross -i ghcr.io/node-usb/linux-x86 --napi --strip", | ||
"prebuild-linux-x64": "prebuildify-cross -i ghcr.io/node-usb/centos7-devtoolset7 -i ghcr.io/node-usb/alpine --napi --strip --tag-libc", | ||
"prebuild-linux-arm": "prebuildify-cross -i ghcr.io/node-usb/linux-arm64 -i ghcr.io/node-usb/linux-armv7 -i ghcr.io/node-usb/linux-armv6 --napi --strip --tag-armv", | ||
"prebuild-android-arm": "prebuildify-cross -i ghcr.io/node-usb/android-arm64 -i ghcr.io/node-usb/android-armv7 --napi --strip --tag-armv", | ||
"prebuild-download": "prebuildify-ci download" | ||
}, | ||
"dependencies": { | ||
"@types/w3c-web-usb": "^1.0.4", | ||
"bindings": "^1.4.0", | ||
"node-addon-api": "^3.1.0", | ||
"prebuild-install": "^6.1.1" | ||
"node-addon-api": "^4.2.0", | ||
"node-gyp-build": "^4.3.0" | ||
}, | ||
@@ -66,5 +73,8 @@ "devDependencies": { | ||
"eslint": "^7.29.0", | ||
"mocha": "^8.3.2", | ||
"prebuild": "^10.0.1", | ||
"typedoc": "^0.20.36", | ||
"mocha": "^9.1.3", | ||
"node-gyp": "^7.1.2", | ||
"prebuildify": "^4.2.1", | ||
"prebuildify-ci": "^1.0.5", | ||
"prebuildify-cross": "^4.0.1", | ||
"typedoc": "^0.22.10", | ||
"typescript": "~4.2.4" | ||
@@ -71,0 +81,0 @@ }, |
@@ -65,4 +65,4 @@ import { promisify } from 'util'; | ||
// WebUSB Device class for turning a core usb.Device into a webusb device | ||
// WebUSB Device class for turning a legacy usb.Device into a webusb device | ||
WebUSBDevice | ||
}; |
@@ -5,6 +5,7 @@ // Definitions from DefinitelyTyped, thanks to: | ||
import { join } from 'path'; | ||
import type { DeviceDescriptor, ConfigDescriptor, BosDescriptor } from './descriptors'; | ||
/* eslint-disable @typescript-eslint/no-var-requires */ | ||
const usb = require('bindings')('usb_bindings'); | ||
const usb = require('node-gyp-build')(join(__dirname, '..', '..')); | ||
module.exports = usb; | ||
@@ -31,3 +32,14 @@ | ||
export declare function _disableHotplugEvents(): void; | ||
export declare function _getLibusbCapability(capability: number): number; | ||
/** | ||
* Restore (re-reference) the hotplug events unreferenced by `unrefHotplugEvents()` | ||
*/ | ||
export declare function refHotplugEvents(): void; | ||
/** | ||
* Unreference the hotplug events from the event loop, allowing the process to exit even when listening for the `attach` and `detach` events | ||
*/ | ||
export declare function unrefHotplugEvents(): void; | ||
/** Represents a USB transfer */ | ||
@@ -262,2 +274,8 @@ export declare class Transfer { | ||
// libusb_capability | ||
export declare const LIBUSB_CAP_HAS_CAPABILITY: number; | ||
export declare const LIBUSB_CAP_HAS_HOTPLUG: number; | ||
export declare const LIBUSB_CAP_HAS_HID_ACCESS: number; | ||
export declare const LIBUSB_CAP_SUPPORTS_DETACH_KERNEL_DRIVER: number; | ||
// libusb_error | ||
@@ -264,0 +282,0 @@ /** Input/output error */ |
@@ -24,21 +24,61 @@ import { EventEmitter } from 'events'; | ||
/* eslint-disable @typescript-eslint/no-empty-interface */ | ||
interface Device extends ExtendedDevice {} | ||
interface Device extends ExtendedDevice { } | ||
interface DeviceEvents extends EventListeners<DeviceEvents> { | ||
attach: Device; | ||
detach: Device; | ||
} | ||
interface DeviceEvents extends EventListeners<DeviceEvents> { | ||
attach: Device; | ||
detach: Device; | ||
} | ||
function addListener<K extends keyof DeviceEvents>(event: K, listener: (arg: DeviceEvents[K]) => void): void; | ||
function removeListener<K extends keyof DeviceEvents>(event: K, listener: (arg: DeviceEvents[K]) => void): void; | ||
function on<K extends keyof DeviceEvents>(event: K, listener: (arg: DeviceEvents[K]) => void): void; | ||
function off<K extends keyof DeviceEvents>(event: K, listener: (arg: DeviceEvents[K]) => void): void; | ||
function once<K extends keyof DeviceEvents>(event: K, listener: (arg: DeviceEvents[K]) => void): void; | ||
function listeners<K extends keyof DeviceEvents>(event: K): ((arg: DeviceEvents[K]) => void)[]; | ||
function rawListeners<K extends keyof DeviceEvents>(event: K): ((arg: DeviceEvents[K]) => void)[]; | ||
function removeAllListeners<K extends keyof DeviceEvents>(event?: K): void; | ||
function emit<K extends keyof DeviceEvents>(event: K, arg: DeviceEvents[K]): boolean; | ||
function listenerCount<K extends keyof DeviceEvents>(event: K): number; | ||
function addListener<K extends keyof DeviceEvents>(event: K, listener: (arg: DeviceEvents[K]) => void): void; | ||
function removeListener<K extends keyof DeviceEvents>(event: K, listener: (arg: DeviceEvents[K]) => void): void; | ||
function on<K extends keyof DeviceEvents>(event: K, listener: (arg: DeviceEvents[K]) => void): void; | ||
function off<K extends keyof DeviceEvents>(event: K, listener: (arg: DeviceEvents[K]) => void): void; | ||
function once<K extends keyof DeviceEvents>(event: K, listener: (arg: DeviceEvents[K]) => void): void; | ||
function listeners<K extends keyof DeviceEvents>(event: K): ((arg: DeviceEvents[K]) => void)[]; | ||
function rawListeners<K extends keyof DeviceEvents>(event: K): ((arg: DeviceEvents[K]) => void)[]; | ||
function removeAllListeners<K extends keyof DeviceEvents>(event?: K): void; | ||
function emit<K extends keyof DeviceEvents>(event: K, arg: DeviceEvents[K]): boolean; | ||
function listenerCount<K extends keyof DeviceEvents>(event: K): number; | ||
} | ||
// Polling mechanism for discovering device changes until this is fixed: | ||
// https://github.com/libusb/libusb/issues/86 | ||
const pollTimeout = 500; | ||
const hotplugSupported = usb._getLibusbCapability(usb.LIBUSB_CAP_HAS_HOTPLUG) > 0; | ||
let pollingHotplug = false; | ||
let pollDevices: usb.Device[] = []; | ||
const pollHotplug = (start = false) => { | ||
if (start) { | ||
pollingHotplug = true; | ||
} else if (!pollingHotplug) { | ||
return; | ||
} | ||
const devices = usb.getDeviceList(); | ||
if (!start) { | ||
// Find attached devices | ||
for (const device of devices) { | ||
const found = pollDevices.find(item => item.deviceAddress === device.deviceAddress); | ||
if (!found) { | ||
usb.emit('attach', device); | ||
} | ||
} | ||
// Find detached devices | ||
for (const device of pollDevices) { | ||
const found = devices.find(item => item.deviceAddress === device.deviceAddress); | ||
if (!found) { | ||
usb.emit('detach', device); | ||
} | ||
} | ||
} | ||
pollDevices = devices; | ||
setTimeout(() => { | ||
pollHotplug(); | ||
}, pollTimeout); | ||
}; | ||
usb.on('newListener', event => { | ||
@@ -50,3 +90,7 @@ if (event !== 'attach' && event !== 'detach') { | ||
if (listenerCount === 0) { | ||
usb._enableHotplugEvents(); | ||
if (hotplugSupported) { | ||
usb._enableHotplugEvents(); | ||
} else { | ||
pollHotplug(true); | ||
} | ||
} | ||
@@ -61,3 +105,7 @@ }); | ||
if (listenerCount === 0) { | ||
usb._disableHotplugEvents(); | ||
if (hotplugSupported) { | ||
usb._disableHotplugEvents(); | ||
} else { | ||
pollingHotplug = false; | ||
} | ||
} | ||
@@ -64,0 +112,0 @@ }); |
@@ -31,3 +31,3 @@ import { LibUSBException, LIBUSB_ENDPOINT_IN, Device } from './bindings'; | ||
const len = this.descriptor.endpoints.length; | ||
for (let i=0; i<len; i++){ | ||
for (let i = 0; i < len; i++) { | ||
const desc = this.descriptor.endpoints[i]; | ||
@@ -149,3 +149,3 @@ const c = (desc.bEndpointAddress & LIBUSB_ENDPOINT_IN) ? InEndpoint : OutEndpoint; | ||
this.device.__setInterface(this.id, altSetting, error => { | ||
if (!error){ | ||
if (!error) { | ||
this.altSetting = altSetting; | ||
@@ -152,0 +152,0 @@ this.refresh(); |
import * as usb from '../usb'; | ||
import { EventEmitter } from 'events'; | ||
import { WebUSBDevice } from './webusb-device'; | ||
import { TypedEventTarget } from './typed-event-target'; | ||
@@ -10,46 +10,140 @@ /** | ||
/** | ||
* A `device found` callback function to allow the user to select a device | ||
* Optional `device found` callback function to allow the user to select a device | ||
*/ | ||
devicesFound?: (devices: Array<USBDevice>) => Promise<USBDevice | void>; | ||
} | ||
devicesFound?: (devices: USBDevice[]) => Promise<USBDevice | void>; | ||
/** | ||
* @hidden | ||
*/ | ||
interface Device { | ||
vendorId?: number; | ||
productId?: number; | ||
serialNumber?: string; | ||
} | ||
/** | ||
* Optional array of preconfigured allowed devices | ||
*/ | ||
allowedDevices?: USBDeviceFilter[]; | ||
/** | ||
* @hidden | ||
*/ | ||
export type USBEvents = { | ||
/** | ||
* USBDevice connected event | ||
* Optional flag to automatically allow all devices | ||
*/ | ||
connect: USBConnectionEvent; | ||
allowAllDevices?: boolean; | ||
/** | ||
* USBDevice disconnected event | ||
* Optional timeout (in milliseconds) to use for the device control transfers | ||
*/ | ||
disconnect: USBConnectionEvent; | ||
}; | ||
deviceTimeout?: number; | ||
} | ||
export class WebUSB extends TypedEventTarget<USBEvents> implements USB { | ||
export class WebUSB implements USB { | ||
private allowedDevices: Array<Device> = []; | ||
protected emitter = new EventEmitter(); | ||
protected knownDevices: Map<string, USBDevice> = new Map(); | ||
protected allowedDevices: USBDeviceFilter[]; | ||
constructor(private options: USBOptions = {}) { | ||
super(); | ||
this.allowedDevices = options.allowedDevices || []; | ||
const deviceConnectCallback = async (device: usb.Device) => { | ||
const webDevice = await WebUSBDevice.createInstance(device); | ||
// When connected, emit an event if it is an allowed device | ||
if (webDevice && this.isAllowedDevice(webDevice)) { | ||
const deviceId = this.getDeviceId(device); | ||
if (deviceId) { | ||
this.knownDevices.set(deviceId, webDevice); | ||
} | ||
const event = { | ||
type: 'connect', | ||
device: webDevice | ||
}; | ||
this.emitter.emit('connect', event); | ||
} | ||
}; | ||
const deviceDisconnectCallback = async (device: usb.Device) => { | ||
const deviceId = this.getDeviceId(device); | ||
// When disconnected, emit an event if the device was a known allowed device | ||
if (deviceId !== undefined && this.knownDevices.has(deviceId)) { | ||
const webDevice = this.knownDevices.get(deviceId); | ||
if (webDevice && this.isAllowedDevice(webDevice)) { | ||
const event = { | ||
type: 'disconnect', | ||
device: webDevice | ||
}; | ||
this.emitter.emit('disconnect', event); | ||
} | ||
} | ||
}; | ||
this.emitter.on('newListener', event => { | ||
const listenerCount = this.emitter.listenerCount(event); | ||
if (listenerCount !== 0) { | ||
return; | ||
} | ||
if (event === 'connect') { | ||
usb.addListener('attach', deviceConnectCallback); | ||
} else if (event === 'disconnect') { | ||
usb.addListener('detach', deviceDisconnectCallback); | ||
} | ||
}); | ||
this.emitter.on('removeListener', event => { | ||
const listenerCount = this.emitter.listenerCount(event); | ||
if (listenerCount !== 0) { | ||
return; | ||
} | ||
if (event === 'connect') { | ||
usb.removeListener('attach', deviceConnectCallback); | ||
} else if (event === 'disconnect') { | ||
usb.removeListener('detach', deviceDisconnectCallback); | ||
} | ||
}); | ||
} | ||
public set onconnect(listener: (event: USBConnectionEvent) => void) { | ||
this.addEventListener('connect', listener); | ||
private _onconnect: ((ev: USBConnectionEvent) => void) | undefined; | ||
public set onconnect(fn: (ev: USBConnectionEvent) => void) { | ||
if (this._onconnect) { | ||
this.removeEventListener('connect', this._onconnect); | ||
this._onconnect = undefined; | ||
} | ||
if (fn) { | ||
this._onconnect = fn; | ||
this.addEventListener('connect', this._onconnect); | ||
} | ||
} | ||
public set ondisconnect(listener: (event: USBConnectionEvent) => void) { | ||
this.addEventListener('disconnect', listener); | ||
private _ondisconnect: ((ev: USBConnectionEvent) => void) | undefined; | ||
public set ondisconnect(fn: (ev: USBConnectionEvent) => void) { | ||
if (this._ondisconnect) { | ||
this.removeEventListener('disconnect', this._ondisconnect); | ||
this._ondisconnect = undefined; | ||
} | ||
if (fn) { | ||
this._ondisconnect = fn; | ||
this.addEventListener('disconnect', this._ondisconnect); | ||
} | ||
} | ||
public addEventListener(type: 'connect' | 'disconnect', listener: (this: this, ev: USBConnectionEvent) => void): void; | ||
public addEventListener(type: 'connect' | 'disconnect', listener: EventListener): void; | ||
public addEventListener(type: string, listener: (ev: USBConnectionEvent) => void): void { | ||
this.emitter.addListener(type, listener); | ||
} | ||
public removeEventListener(type: 'connect' | 'disconnect', callback: (this: this, ev: USBConnectionEvent) => void): void; | ||
public removeEventListener(type: 'connect' | 'disconnect', callback: EventListener): void; | ||
public removeEventListener(type: string, callback: (this: this, ev: USBConnectionEvent) => void): void { | ||
this.emitter.removeListener(type, callback); | ||
} | ||
public dispatchEvent(_event: Event): boolean { | ||
// Don't dispatch from here | ||
return false; | ||
} | ||
/** | ||
@@ -109,3 +203,3 @@ * Requests a single Web USB device | ||
if (!this.replaceAllowedDevice(device)) { | ||
if (!this.isAllowedDevice(device)) { | ||
this.allowedDevices.push({ | ||
@@ -119,3 +213,3 @@ vendorId: device.vendorId, | ||
return device; | ||
} catch(error) { | ||
} catch (error) { | ||
throw new Error(`requestDevice error: ${error}`); | ||
@@ -130,31 +224,23 @@ } | ||
public async getDevices(): Promise<USBDevice[]> { | ||
// Create pre-filters | ||
const preFilters = this.allowedDevices.map(device => ({ | ||
vendorId: device.vendorId || undefined, | ||
productId: device.productId || undefined, | ||
serialNumber: device.serialNumber || undefined | ||
})); | ||
let preFilters: USBDeviceFilter[] | undefined; | ||
if (!this.options.allowAllDevices) { | ||
// Create pre-filters | ||
preFilters = this.allowedDevices.map(device => ({ | ||
vendorId: device.vendorId || undefined, | ||
productId: device.productId || undefined, | ||
serialNumber: device.serialNumber || undefined | ||
})); | ||
} | ||
// Refresh devices and filter for allowed ones | ||
let devices = await this.loadDevices(preFilters); | ||
devices = devices.filter(device => { | ||
for (const i in this.allowedDevices) { | ||
if (this.isSameDevice(device, this.allowedDevices[i])) { | ||
return true; | ||
} | ||
} | ||
return false; | ||
}); | ||
return devices; | ||
const devices = await this.loadDevices(preFilters); | ||
return devices.filter(device => this.isAllowedDevice(device)); | ||
} | ||
private async loadDevices(preFilters?: Array<Device>): Promise<USBDevice[]> { | ||
private async loadDevices(preFilters?: USBDeviceFilter[]): Promise<USBDevice[]> { | ||
let devices = usb.getDeviceList(); | ||
if (preFilters) { | ||
// Pre-filter devices | ||
devices = this.preFilterDevices(devices, preFilters); | ||
} | ||
// Pre-filter devices | ||
devices = this.preFilterDevices(devices, preFilters); | ||
@@ -164,4 +250,15 @@ const webDevices: USBDevice[] = []; | ||
for (const device of devices) { | ||
if (this.options.deviceTimeout) { | ||
device.timeout = this.options.deviceTimeout; | ||
} | ||
const webDevice = await WebUSBDevice.createInstance(device); | ||
webDevices.push(webDevice); | ||
if (webDevice) { | ||
webDevices.push(webDevice); | ||
const deviceId = this.getDeviceId(device); | ||
if (deviceId) { | ||
this.knownDevices.set(deviceId, webDevice); | ||
} | ||
} | ||
} | ||
@@ -172,3 +269,7 @@ | ||
private preFilterDevices(devices: Array<usb.Device>, preFilters: Array<Device>): Array<usb.Device> { | ||
private preFilterDevices(devices: usb.Device[], preFilters?: USBDeviceFilter[]): usb.Device[] { | ||
if (!preFilters || !preFilters.length) { | ||
return devices; | ||
} | ||
// Just pre-filter on vid/pid | ||
@@ -187,24 +288,7 @@ return devices.filter(device => preFilters.some(filter => { | ||
private isSameDevice(device1: Device, device2: Device): boolean { | ||
return (device1.productId === device2.productId | ||
&& device1.vendorId === device2.vendorId | ||
&& device1.serialNumber === device2.serialNumber); | ||
} | ||
private replaceAllowedDevice(device: USBDevice): boolean { | ||
for (const i in this.allowedDevices) { | ||
if (this.isSameDevice(device, this.allowedDevices[i])) { | ||
this.allowedDevices[i] = { | ||
vendorId: device.vendorId, | ||
productId: device.productId, | ||
serialNumber: device.serialNumber | ||
}; | ||
return true; | ||
} | ||
private filterDevice(options: USBDeviceRequestOptions, device: USBDevice): boolean { | ||
if (!options.filters || !options.filters.length) { | ||
return true; | ||
} | ||
return false; | ||
} | ||
private filterDevice(options: USBDeviceRequestOptions, device: USBDevice): boolean { | ||
return options.filters.some(filter => { | ||
@@ -258,2 +342,30 @@ // Vendor | ||
} | ||
private getDeviceId(device: usb.Device): string | undefined { | ||
if (device.busNumber === undefined || device.deviceAddress === undefined) { | ||
return undefined; | ||
} | ||
return `${device.busNumber}.${device.deviceAddress}`; | ||
} | ||
private isAllowedDevice(device: USBDeviceFilter): boolean { | ||
if (this.options.allowAllDevices) { | ||
return true; | ||
} | ||
const isSameDevice = (device1: USBDeviceFilter, device2: USBDeviceFilter): boolean => { | ||
return (device1.productId === device2.productId | ||
&& device1.vendorId === device2.vendorId | ||
&& device1.serialNumber === device2.serialNumber); | ||
}; | ||
for (const i in this.allowedDevices) { | ||
if (isSameDevice(device, this.allowedDevices[i])) { | ||
return true; | ||
} | ||
} | ||
return false; | ||
} | ||
} |
@@ -15,6 +15,10 @@ import * as usb from '../usb'; | ||
export class WebUSBDevice implements USBDevice { | ||
public static async createInstance(device: usb.Device): Promise<WebUSBDevice> { | ||
const instance = new WebUSBDevice(device); | ||
await instance.initialize(); | ||
return instance; | ||
public static async createInstance(device: usb.Device): Promise<WebUSBDevice | undefined> { | ||
try { | ||
const instance = new WebUSBDevice(device); | ||
await instance.initialize(); | ||
return instance; | ||
} catch { | ||
return undefined; | ||
} | ||
} | ||
@@ -102,5 +106,5 @@ | ||
interfaceNumber: iface.interfaceNumber, | ||
alternate : iface.alternate, | ||
alternates : iface.alternates, | ||
claimed : false | ||
alternate: iface.alternate, | ||
alternates: iface.alternates, | ||
claimed: false | ||
}; | ||
@@ -133,3 +137,3 @@ } | ||
const config = this.configurations.find(configuration => configuration.configurationValue === configurationValue); | ||
const config = this.configurations.find(configuration => configuration.configurationValue === configurationValue); | ||
if (!config) { | ||
@@ -177,5 +181,5 @@ throw new Error('selectConfiguration error: configuration not found'); | ||
interfaceNumber, | ||
alternate : iface.alternate, | ||
alternates : iface.alternates, | ||
claimed : true | ||
alternate: iface.alternate, | ||
alternates: iface.alternates, | ||
claimed: true | ||
}; | ||
@@ -201,5 +205,5 @@ } catch (error) { | ||
interfaceNumber, | ||
alternate : iface.alternate, | ||
alternates : iface.alternates, | ||
claimed : false | ||
alternate: iface.alternate, | ||
alternates: iface.alternates, | ||
claimed: false | ||
}; | ||
@@ -283,3 +287,3 @@ } | ||
const buffer = data ? Buffer.from(data) : Buffer.alloc(0); | ||
const bytesWritten = <number> await controlTransfer(type, setup.request, setup.value, setup.index, buffer); | ||
const bytesWritten = <number>await controlTransfer(type, setup.request, setup.value, setup.index, buffer); | ||
@@ -286,0 +290,0 @@ return { |
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
Unidentified License
License(Experimental) Something that seems like a license was found, but its contents could not be matched with a known license.
Found 3 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
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
Unidentified License
License(Experimental) Something that seems like a license was found, but its contents could not be matched with a known license.
Found 1 instance in 1 package
5342721
3
1
571
12
274
9
60
5291
+ Addednode-gyp-build@^4.3.0
+ Addednode-addon-api@4.3.0(transitive)
+ Addednode-gyp-build@4.8.2(transitive)
- Removedbindings@^1.4.0
- Removedprebuild-install@^6.1.1
- Removedansi-regex@2.1.1(transitive)
- Removedaproba@1.2.0(transitive)
- Removedare-we-there-yet@1.1.7(transitive)
- Removedbase64-js@1.5.1(transitive)
- Removedbindings@1.5.0(transitive)
- Removedbl@4.1.0(transitive)
- Removedbuffer@5.7.1(transitive)
- Removedchownr@1.1.4(transitive)
- Removedcode-point-at@1.1.0(transitive)
- Removedconsole-control-strings@1.1.0(transitive)
- Removedcore-util-is@1.0.3(transitive)
- Removeddecompress-response@4.2.1(transitive)
- Removeddeep-extend@0.6.0(transitive)
- Removeddelegates@1.0.0(transitive)
- Removeddetect-libc@1.0.3(transitive)
- Removedend-of-stream@1.4.4(transitive)
- Removedexpand-template@2.0.3(transitive)
- Removedfile-uri-to-path@1.0.0(transitive)
- Removedfs-constants@1.0.0(transitive)
- Removedgauge@2.7.4(transitive)
- Removedgithub-from-package@0.0.0(transitive)
- Removedhas-unicode@2.0.1(transitive)
- Removedieee754@1.2.1(transitive)
- Removedinherits@2.0.4(transitive)
- Removedini@1.3.8(transitive)
- Removedis-fullwidth-code-point@1.0.0(transitive)
- Removedisarray@1.0.0(transitive)
- Removedmimic-response@2.1.0(transitive)
- Removedminimist@1.2.8(transitive)
- Removedmkdirp-classic@0.5.3(transitive)
- Removednapi-build-utils@1.0.2(transitive)
- Removednode-abi@2.30.1(transitive)
- Removednode-addon-api@3.2.1(transitive)
- Removednpmlog@4.1.2(transitive)
- Removednumber-is-nan@1.0.1(transitive)
- Removedobject-assign@4.1.1(transitive)
- Removedonce@1.4.0(transitive)
- Removedprebuild-install@6.1.4(transitive)
- Removedprocess-nextick-args@2.0.1(transitive)
- Removedpump@3.0.2(transitive)
- Removedrc@1.2.8(transitive)
- Removedreadable-stream@2.3.83.6.2(transitive)
- Removedsafe-buffer@5.1.2(transitive)
- Removedsemver@5.7.2(transitive)
- Removedset-blocking@2.0.0(transitive)
- Removedsignal-exit@3.0.7(transitive)
- Removedsimple-concat@1.0.1(transitive)
- Removedsimple-get@3.1.1(transitive)
- Removedstring-width@1.0.2(transitive)
- Removedstring_decoder@1.1.1(transitive)
- Removedstrip-ansi@3.0.1(transitive)
- Removedstrip-json-comments@2.0.1(transitive)
- Removedtar-fs@2.1.1(transitive)
- Removedtar-stream@2.2.0(transitive)
- Removedtunnel-agent@0.6.0(transitive)
- Removedutil-deprecate@1.0.2(transitive)
- Removedwide-align@1.1.5(transitive)
- Removedwrappy@1.0.2(transitive)
Updatednode-addon-api@^4.2.0