@mcesystems/usb-device-listener 1.0.69 → 1.0.70
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +34 -0
- package/dist/index.d.ts +20 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +34 -11
- package/dist/index.js.map +3 -3
- package/dist/index.mjs +34 -11
- package/dist/index.mjs.map +2 -2
- package/dist/types.d.ts +26 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -157,6 +157,40 @@ Stop monitoring and clean up resources. Safe to call multiple times.
|
|
|
157
157
|
usbListener.stopListening();
|
|
158
158
|
```
|
|
159
159
|
|
|
160
|
+
### `updateConfig(config)`
|
|
161
|
+
|
|
162
|
+
Update the listener config at runtime. When listening, subsequent device events and `listDevices()` use the new config. When not listening, only `listDevices()` uses it until the next `startListening()`. Config is fully replaced (use `getCurrentConfig()` to merge).
|
|
163
|
+
|
|
164
|
+
**Parameters:**
|
|
165
|
+
- `config` (Object): Same shape as `startListening(config)` (logicalPortMap, targetDevices, ignoredDevices, listenOnlyDevices)
|
|
166
|
+
|
|
167
|
+
**Throws:**
|
|
168
|
+
- `TypeError` if config is not an object
|
|
169
|
+
|
|
170
|
+
**Example:**
|
|
171
|
+
```javascript
|
|
172
|
+
// Replace config entirely
|
|
173
|
+
usbListener.updateConfig({ logicalPortMap: newMap, targetDevices: [] });
|
|
174
|
+
|
|
175
|
+
// Merge with current config
|
|
176
|
+
usbListener.updateConfig({ ...usbListener.getCurrentConfig(), logicalPortMap: newMap });
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
### `getCurrentConfig()`
|
|
180
|
+
|
|
181
|
+
Return a copy of the current config. Mutating the returned object does not affect the listener's internal config. Use with `updateConfig()` to merge partial changes.
|
|
182
|
+
|
|
183
|
+
**Returns:** Shallow copy of the current config object (ListenerConfig)
|
|
184
|
+
|
|
185
|
+
**Example:**
|
|
186
|
+
```javascript
|
|
187
|
+
const current = usbListener.getCurrentConfig();
|
|
188
|
+
usbListener.updateConfig({
|
|
189
|
+
...current,
|
|
190
|
+
targetDevices: [...(current.targetDevices ?? []), { vid: "04E8", pid: "6860" }]
|
|
191
|
+
});
|
|
192
|
+
```
|
|
193
|
+
|
|
160
194
|
### `onDeviceAdd(callback)`
|
|
161
195
|
|
|
162
196
|
Register callback for device connection events.
|
package/dist/index.d.ts
CHANGED
|
@@ -1,12 +1,21 @@
|
|
|
1
1
|
import type { DeviceAddCallback, DeviceInfo, DeviceRemoveCallback, ListenerConfig, UsbDeviceListenerI } from "./types";
|
|
2
|
+
export interface NativeAddon {
|
|
3
|
+
startListening(): void;
|
|
4
|
+
stopListening(): void;
|
|
5
|
+
onDeviceAdd(callback: DeviceAddCallback): void;
|
|
6
|
+
onDeviceRemove(callback: DeviceRemoveCallback): void;
|
|
7
|
+
listDevices(): DeviceInfo[];
|
|
8
|
+
}
|
|
2
9
|
/**
|
|
3
10
|
* USB Device Listener implementation
|
|
4
11
|
* Provides a type-safe wrapper around the native C++ addon
|
|
5
12
|
*/
|
|
6
13
|
export default class UsbDeviceListener implements UsbDeviceListenerI {
|
|
14
|
+
private readonly addon;
|
|
7
15
|
private config;
|
|
8
16
|
private userAddCallback;
|
|
9
17
|
private userRemoveCallback;
|
|
18
|
+
constructor(addon?: NativeAddon);
|
|
10
19
|
/**
|
|
11
20
|
* Start listening for USB device events
|
|
12
21
|
*/
|
|
@@ -15,6 +24,17 @@ export default class UsbDeviceListener implements UsbDeviceListenerI {
|
|
|
15
24
|
* Stop listening for USB device events
|
|
16
25
|
*/
|
|
17
26
|
stopListening(): void;
|
|
27
|
+
/**
|
|
28
|
+
* Update the listener config at runtime.
|
|
29
|
+
* When listening, subsequent device events and listDevices() use the new config.
|
|
30
|
+
* When not listening, only listDevices() uses it until the next startListening().
|
|
31
|
+
*/
|
|
32
|
+
updateConfig(config: ListenerConfig): void;
|
|
33
|
+
/**
|
|
34
|
+
* Return a shallow copy of the current config.
|
|
35
|
+
* Mutating the returned object does not affect the listener's internal config.
|
|
36
|
+
*/
|
|
37
|
+
getCurrentConfig(): ListenerConfig;
|
|
18
38
|
/**
|
|
19
39
|
* Register callback for device connection events
|
|
20
40
|
*/
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACX,iBAAiB,EACjB,UAAU,EACV,oBAAoB,EACpB,cAAc,EACd,kBAAkB,EAClB,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACX,iBAAiB,EACjB,UAAU,EACV,oBAAoB,EACpB,cAAc,EACd,kBAAkB,EAClB,MAAM,SAAS,CAAC;AAEjB,MAAM,WAAW,WAAW;IAC3B,cAAc,IAAI,IAAI,CAAC;IACvB,aAAa,IAAI,IAAI,CAAC;IACtB,WAAW,CAAC,QAAQ,EAAE,iBAAiB,GAAG,IAAI,CAAC;IAC/C,cAAc,CAAC,QAAQ,EAAE,oBAAoB,GAAG,IAAI,CAAC;IACrD,WAAW,IAAI,UAAU,EAAE,CAAC;CAC5B;AAUD;;;GAGG;AACH,MAAM,CAAC,OAAO,OAAO,iBAAkB,YAAW,kBAAkB;IACnE,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAc;IACpC,OAAO,CAAC,MAAM,CAAsB;IACpC,OAAO,CAAC,eAAe,CAAkC;IACzD,OAAO,CAAC,kBAAkB,CAAqC;gBAEnD,KAAK,CAAC,EAAE,WAAW;IAI/B;;OAEG;IACI,cAAc,CAAC,MAAM,EAAE,cAAc,GAAG,IAAI;IAQnD;;OAEG;IACI,aAAa,IAAI,IAAI;IAI5B;;;;OAIG;IACI,YAAY,CAAC,MAAM,EAAE,cAAc,GAAG,IAAI;IAOjD;;;OAGG;IACI,gBAAgB,IAAI,cAAc;IAIzC;;OAEG;IACI,WAAW,CAAC,QAAQ,EAAE,iBAAiB,GAAG,IAAI;IAerD;;OAEG;IACI,cAAc,CAAC,QAAQ,EAAE,oBAAoB,GAAG,IAAI;IAe3D;;;OAGG;IACI,WAAW,IAAI,UAAU,EAAE;CAKlC;AAED,YAAY,EACX,UAAU,EACV,iBAAiB,EACjB,oBAAoB,EACpB,cAAc,EACd,YAAY,GACZ,MAAM,SAAS,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -86,16 +86,21 @@ function applyLogicalPortMapping(device, config) {
|
|
|
86
86
|
}
|
|
87
87
|
|
|
88
88
|
// src/index.ts
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
89
|
+
function loadDefaultAddon() {
|
|
90
|
+
const require2 = (0, import_node_module.createRequire)(__importMetaUrl);
|
|
91
|
+
const __filename = (0, import_node_url.fileURLToPath)(__importMetaUrl);
|
|
92
|
+
const __dirname = import_node_path.default.dirname(__filename);
|
|
93
|
+
const packageRoot = import_node_path.default.join(__dirname, "..");
|
|
94
|
+
return require2("node-gyp-build")(packageRoot);
|
|
95
|
+
}
|
|
95
96
|
var UsbDeviceListener = class {
|
|
97
|
+
addon;
|
|
96
98
|
config = {};
|
|
97
99
|
userAddCallback = null;
|
|
98
100
|
userRemoveCallback = null;
|
|
101
|
+
constructor(addon) {
|
|
102
|
+
this.addon = addon ?? loadDefaultAddon();
|
|
103
|
+
}
|
|
99
104
|
/**
|
|
100
105
|
* Start listening for USB device events
|
|
101
106
|
*/
|
|
@@ -104,13 +109,31 @@ var UsbDeviceListener = class {
|
|
|
104
109
|
throw new TypeError("Config must be an object");
|
|
105
110
|
}
|
|
106
111
|
this.config = config;
|
|
107
|
-
startListening();
|
|
112
|
+
this.addon.startListening();
|
|
108
113
|
}
|
|
109
114
|
/**
|
|
110
115
|
* Stop listening for USB device events
|
|
111
116
|
*/
|
|
112
117
|
stopListening() {
|
|
113
|
-
stopListening();
|
|
118
|
+
this.addon.stopListening();
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Update the listener config at runtime.
|
|
122
|
+
* When listening, subsequent device events and listDevices() use the new config.
|
|
123
|
+
* When not listening, only listDevices() uses it until the next startListening().
|
|
124
|
+
*/
|
|
125
|
+
updateConfig(config) {
|
|
126
|
+
if (typeof config !== "object" || config === null) {
|
|
127
|
+
throw new TypeError("Config must be an object");
|
|
128
|
+
}
|
|
129
|
+
this.config = config;
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Return a shallow copy of the current config.
|
|
133
|
+
* Mutating the returned object does not affect the listener's internal config.
|
|
134
|
+
*/
|
|
135
|
+
getCurrentConfig() {
|
|
136
|
+
return { ...this.config };
|
|
114
137
|
}
|
|
115
138
|
/**
|
|
116
139
|
* Register callback for device connection events
|
|
@@ -120,7 +143,7 @@ var UsbDeviceListener = class {
|
|
|
120
143
|
throw new TypeError("Callback must be a function");
|
|
121
144
|
}
|
|
122
145
|
this.userAddCallback = callback;
|
|
123
|
-
onDeviceAdd((device) => {
|
|
146
|
+
this.addon.onDeviceAdd((device) => {
|
|
124
147
|
if (shouldNotifyDevice(device, this.config)) {
|
|
125
148
|
const enrichedDevice = applyLogicalPortMapping(device, this.config);
|
|
126
149
|
this.userAddCallback?.(enrichedDevice);
|
|
@@ -135,7 +158,7 @@ var UsbDeviceListener = class {
|
|
|
135
158
|
throw new TypeError("Callback must be a function");
|
|
136
159
|
}
|
|
137
160
|
this.userRemoveCallback = callback;
|
|
138
|
-
onDeviceRemove((device) => {
|
|
161
|
+
this.addon.onDeviceRemove((device) => {
|
|
139
162
|
if (shouldNotifyDevice(device, this.config)) {
|
|
140
163
|
const enrichedDevice = applyLogicalPortMapping(device, this.config);
|
|
141
164
|
this.userRemoveCallback?.(enrichedDevice);
|
|
@@ -147,7 +170,7 @@ var UsbDeviceListener = class {
|
|
|
147
170
|
* Applies logical port mapping from config if set
|
|
148
171
|
*/
|
|
149
172
|
listDevices() {
|
|
150
|
-
const devices = listDevices();
|
|
173
|
+
const devices = this.addon.listDevices();
|
|
151
174
|
return devices.map((device) => applyLogicalPortMapping(device, this.config));
|
|
152
175
|
}
|
|
153
176
|
};
|
package/dist/index.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/index.ts", "../src/device-filter.ts"],
|
|
4
|
-
"sourcesContent": ["import { createRequire } from \"node:module\";\
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,yBAA8B;AAC9B,uBAAiB;AACjB,sBAA8B;;;ACG9B,SAAS,YAAY,OAAuB;AAC3C,SAAO,MAAM,SAAS,EAAE,EAAE,YAAY,EAAE,SAAS,GAAG,GAAG;AACxD;AAKA,SAAS,cAAc,QAAoB,QAA+B;AACzE,QAAM,YAAY,YAAY,OAAO,GAAG;AACxC,QAAM,YAAY,YAAY,OAAO,GAAG;AACxC,QAAM,YAAY,OAAO,IAAI,YAAY;AACzC,QAAM,YAAY,OAAO,IAAI,YAAY;AAEzC,SAAO,cAAc,aAAa,cAAc;AACjD;AAKA,SAAS,iBAAiB,QAAoB,SAAkC;AAC/E,SAAO,QAAQ,KAAK,CAAC,WAAW,cAAc,QAAQ,MAAM,CAAC;AAC9D;AAeO,SAAS,mBAAmB,QAAoB,QAAiC;AAEvF,MAAI,OAAO,kBAAkB,OAAO,eAAe,SAAS,GAAG;AAC9D,QAAI,iBAAiB,QAAQ,OAAO,cAAc,GAAG;AACpD,aAAO;AAAA,IACR;AAAA,EACD;AAGA,MAAI,OAAO,qBAAqB,OAAO,kBAAkB,SAAS,GAAG;AACpE,QAAI,CAAC,iBAAiB,QAAQ,OAAO,iBAAiB,GAAG;AACxD,aAAO;AAAA,IACR;AAAA,EACD;AAGA,MAAI,OAAO,iBAAiB,OAAO,cAAc,SAAS,GAAG;AAC5D,QAAI,CAAC,iBAAiB,QAAQ,OAAO,aAAa,GAAG;AACpD,aAAO;AAAA,IACR;AAAA,EACD;AAGA,MAAI,OAAO,kBAAkB,OAAO,KAAK,OAAO,cAAc,EAAE,SAAS,GAAG;AAC3E,QAAI,EAAE,OAAO,gBAAgB,OAAO,iBAAiB;AACpD,aAAO;AAAA,IACR;AAAA,EACD;AAEA,SAAO;AACR;AASO,SAAS,wBAAwB,QAAoB,QAAoC;AAC/F,MAAI,OAAO,kBAAkB,OAAO,gBAAgB,OAAO,gBAAgB;AAC1E,WAAO;AAAA,MACN,GAAG;AAAA,MACH,aAAa,OAAO,eAAe,OAAO,YAAY;AAAA,IACvD;AAAA,EACD;AACA,SAAO;AACR;;;ADpEA,
|
|
6
|
-
"names": ["
|
|
4
|
+
"sourcesContent": ["import { createRequire } from \"node:module\";\nimport path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { applyLogicalPortMapping, shouldNotifyDevice } from \"./device-filter\";\nimport type {\n\tDeviceAddCallback,\n\tDeviceInfo,\n\tDeviceRemoveCallback,\n\tListenerConfig,\n\tUsbDeviceListenerI,\n} from \"./types\";\n\nexport interface NativeAddon {\n\tstartListening(): void;\n\tstopListening(): void;\n\tonDeviceAdd(callback: DeviceAddCallback): void;\n\tonDeviceRemove(callback: DeviceRemoveCallback): void;\n\tlistDevices(): DeviceInfo[];\n}\n\nfunction loadDefaultAddon(): NativeAddon {\n\tconst require = createRequire(import.meta.url);\n\tconst __filename = fileURLToPath(import.meta.url);\n\tconst __dirname = path.dirname(__filename);\n\tconst packageRoot = path.join(__dirname, \"..\");\n\treturn require(\"node-gyp-build\")(packageRoot);\n}\n\n/**\n * USB Device Listener implementation\n * Provides a type-safe wrapper around the native C++ addon\n */\nexport default class UsbDeviceListener implements UsbDeviceListenerI {\n\tprivate readonly addon: NativeAddon;\n\tprivate config: ListenerConfig = {};\n\tprivate userAddCallback: DeviceAddCallback | null = null;\n\tprivate userRemoveCallback: DeviceRemoveCallback | null = null;\n\n\tconstructor(addon?: NativeAddon) {\n\t\tthis.addon = addon ?? loadDefaultAddon();\n\t}\n\n\t/**\n\t * Start listening for USB device events\n\t */\n\tpublic startListening(config: ListenerConfig): void {\n\t\tif (typeof config !== \"object\" || config === null) {\n\t\t\tthrow new TypeError(\"Config must be an object\");\n\t\t}\n\t\tthis.config = config;\n\t\tthis.addon.startListening();\n\t}\n\n\t/**\n\t * Stop listening for USB device events\n\t */\n\tpublic stopListening(): void {\n\t\tthis.addon.stopListening();\n\t}\n\n\t/**\n\t * Update the listener config at runtime.\n\t * When listening, subsequent device events and listDevices() use the new config.\n\t * When not listening, only listDevices() uses it until the next startListening().\n\t */\n\tpublic updateConfig(config: ListenerConfig): void {\n\t\tif (typeof config !== \"object\" || config === null) {\n\t\t\tthrow new TypeError(\"Config must be an object\");\n\t\t}\n\t\tthis.config = config;\n\t}\n\n\t/**\n\t * Return a shallow copy of the current config.\n\t * Mutating the returned object does not affect the listener's internal config.\n\t */\n\tpublic getCurrentConfig(): ListenerConfig {\n\t\treturn { ...this.config };\n\t}\n\n\t/**\n\t * Register callback for device connection events\n\t */\n\tpublic onDeviceAdd(callback: DeviceAddCallback): void {\n\t\tif (typeof callback !== \"function\") {\n\t\t\tthrow new TypeError(\"Callback must be a function\");\n\t\t}\n\t\tthis.userAddCallback = callback;\n\n\t\t// Set up internal callback that filters devices\n\t\tthis.addon.onDeviceAdd((device: DeviceInfo) => {\n\t\t\tif (shouldNotifyDevice(device, this.config)) {\n\t\t\t\tconst enrichedDevice = applyLogicalPortMapping(device, this.config);\n\t\t\t\tthis.userAddCallback?.(enrichedDevice);\n\t\t\t}\n\t\t});\n\t}\n\n\t/**\n\t * Register callback for device disconnection events\n\t */\n\tpublic onDeviceRemove(callback: DeviceRemoveCallback): void {\n\t\tif (typeof callback !== \"function\") {\n\t\t\tthrow new TypeError(\"Callback must be a function\");\n\t\t}\n\t\tthis.userRemoveCallback = callback;\n\n\t\t// Set up internal callback that filters devices\n\t\tthis.addon.onDeviceRemove((device: DeviceInfo) => {\n\t\t\tif (shouldNotifyDevice(device, this.config)) {\n\t\t\t\tconst enrichedDevice = applyLogicalPortMapping(device, this.config);\n\t\t\t\tthis.userRemoveCallback?.(enrichedDevice);\n\t\t\t}\n\t\t});\n\t}\n\n\t/**\n\t * List all currently connected USB devices\n\t * Applies logical port mapping from config if set\n\t */\n\tpublic listDevices(): DeviceInfo[] {\n\t\tconst devices = this.addon.listDevices();\n\t\t// Apply logical port mapping to each device\n\t\treturn devices.map((device) => applyLogicalPortMapping(device, this.config));\n\t}\n}\n\nexport type {\n\tDeviceInfo,\n\tDeviceAddCallback,\n\tDeviceRemoveCallback,\n\tListenerConfig,\n\tTargetDevice,\n} from \"./types\";\n", "import type { DeviceInfo, ListenerConfig, TargetDevice } from \"./types\";\n\n/**\n * Convert a decimal VID/PID to uppercase hex string for comparison\n */\nfunction toHexString(value: number): string {\n\treturn value.toString(16).toUpperCase().padStart(4, \"0\");\n}\n\n/**\n * Check if a device matches a target device filter by VID/PID\n */\nfunction matchesDevice(device: DeviceInfo, target: TargetDevice): boolean {\n\tconst deviceVid = toHexString(device.vid);\n\tconst devicePid = toHexString(device.pid);\n\tconst targetVid = target.vid.toUpperCase();\n\tconst targetPid = target.pid.toUpperCase();\n\n\treturn deviceVid === targetVid && devicePid === targetPid;\n}\n\n/**\n * Check if a device matches any device in a list of target devices\n */\nfunction matchesAnyDevice(device: DeviceInfo, targets: TargetDevice[]): boolean {\n\treturn targets.some((target) => matchesDevice(device, target));\n}\n\n/**\n * Determine if a device notification should be sent based on the configuration.\n *\n * Filter priority (highest to lowest):\n * 1. ignoredDevices - if device matches, always return false\n * 2. listenOnlyDevices - if specified, device must match at least one\n * 3. targetDevices - if specified, device must match at least one\n * 4. logicalPortMap - if specified, device location must be in the map\n *\n * @param device - The device information from the native addon\n * @param config - The listener configuration\n * @returns true if the device should trigger a notification, false otherwise\n */\nexport function shouldNotifyDevice(device: DeviceInfo, config: ListenerConfig): boolean {\n\t// Priority 1: Check ignoredDevices (highest priority - always blocks)\n\tif (config.ignoredDevices && config.ignoredDevices.length > 0) {\n\t\tif (matchesAnyDevice(device, config.ignoredDevices)) {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t// Priority 2: Check listenOnlyDevices (if specified, device must match)\n\tif (config.listenOnlyDevices && config.listenOnlyDevices.length > 0) {\n\t\tif (!matchesAnyDevice(device, config.listenOnlyDevices)) {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t// Priority 3: Check targetDevices (if specified, device must match)\n\tif (config.targetDevices && config.targetDevices.length > 0) {\n\t\tif (!matchesAnyDevice(device, config.targetDevices)) {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t// Priority 4: Check logicalPortMap (if specified, device must be mapped)\n\tif (config.logicalPortMap && Object.keys(config.logicalPortMap).length > 0) {\n\t\tif (!(device.locationInfo in config.logicalPortMap)) {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\treturn true;\n}\n\n/**\n * Apply logical port mapping to a device if configured\n *\n * @param device - The device information from the native addon\n * @param config - The listener configuration\n * @returns Device info with logicalPort set if mapped, otherwise unchanged\n */\nexport function applyLogicalPortMapping(device: DeviceInfo, config: ListenerConfig): DeviceInfo {\n\tif (config.logicalPortMap && device.locationInfo in config.logicalPortMap) {\n\t\treturn {\n\t\t\t...device,\n\t\t\tlogicalPort: config.logicalPortMap[device.locationInfo],\n\t\t};\n\t}\n\treturn device;\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["require", "path"]
|
|
7
7
|
}
|
package/dist/index.mjs
CHANGED
|
@@ -51,16 +51,21 @@ function applyLogicalPortMapping(device, config) {
|
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
// src/index.ts
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
54
|
+
function loadDefaultAddon() {
|
|
55
|
+
const require2 = createRequire(import.meta.url);
|
|
56
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
57
|
+
const __dirname = path.dirname(__filename);
|
|
58
|
+
const packageRoot = path.join(__dirname, "..");
|
|
59
|
+
return require2("node-gyp-build")(packageRoot);
|
|
60
|
+
}
|
|
60
61
|
var UsbDeviceListener = class {
|
|
62
|
+
addon;
|
|
61
63
|
config = {};
|
|
62
64
|
userAddCallback = null;
|
|
63
65
|
userRemoveCallback = null;
|
|
66
|
+
constructor(addon) {
|
|
67
|
+
this.addon = addon ?? loadDefaultAddon();
|
|
68
|
+
}
|
|
64
69
|
/**
|
|
65
70
|
* Start listening for USB device events
|
|
66
71
|
*/
|
|
@@ -69,13 +74,31 @@ var UsbDeviceListener = class {
|
|
|
69
74
|
throw new TypeError("Config must be an object");
|
|
70
75
|
}
|
|
71
76
|
this.config = config;
|
|
72
|
-
startListening();
|
|
77
|
+
this.addon.startListening();
|
|
73
78
|
}
|
|
74
79
|
/**
|
|
75
80
|
* Stop listening for USB device events
|
|
76
81
|
*/
|
|
77
82
|
stopListening() {
|
|
78
|
-
stopListening();
|
|
83
|
+
this.addon.stopListening();
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Update the listener config at runtime.
|
|
87
|
+
* When listening, subsequent device events and listDevices() use the new config.
|
|
88
|
+
* When not listening, only listDevices() uses it until the next startListening().
|
|
89
|
+
*/
|
|
90
|
+
updateConfig(config) {
|
|
91
|
+
if (typeof config !== "object" || config === null) {
|
|
92
|
+
throw new TypeError("Config must be an object");
|
|
93
|
+
}
|
|
94
|
+
this.config = config;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Return a shallow copy of the current config.
|
|
98
|
+
* Mutating the returned object does not affect the listener's internal config.
|
|
99
|
+
*/
|
|
100
|
+
getCurrentConfig() {
|
|
101
|
+
return { ...this.config };
|
|
79
102
|
}
|
|
80
103
|
/**
|
|
81
104
|
* Register callback for device connection events
|
|
@@ -85,7 +108,7 @@ var UsbDeviceListener = class {
|
|
|
85
108
|
throw new TypeError("Callback must be a function");
|
|
86
109
|
}
|
|
87
110
|
this.userAddCallback = callback;
|
|
88
|
-
onDeviceAdd((device) => {
|
|
111
|
+
this.addon.onDeviceAdd((device) => {
|
|
89
112
|
if (shouldNotifyDevice(device, this.config)) {
|
|
90
113
|
const enrichedDevice = applyLogicalPortMapping(device, this.config);
|
|
91
114
|
this.userAddCallback?.(enrichedDevice);
|
|
@@ -100,7 +123,7 @@ var UsbDeviceListener = class {
|
|
|
100
123
|
throw new TypeError("Callback must be a function");
|
|
101
124
|
}
|
|
102
125
|
this.userRemoveCallback = callback;
|
|
103
|
-
onDeviceRemove((device) => {
|
|
126
|
+
this.addon.onDeviceRemove((device) => {
|
|
104
127
|
if (shouldNotifyDevice(device, this.config)) {
|
|
105
128
|
const enrichedDevice = applyLogicalPortMapping(device, this.config);
|
|
106
129
|
this.userRemoveCallback?.(enrichedDevice);
|
|
@@ -112,7 +135,7 @@ var UsbDeviceListener = class {
|
|
|
112
135
|
* Applies logical port mapping from config if set
|
|
113
136
|
*/
|
|
114
137
|
listDevices() {
|
|
115
|
-
const devices = listDevices();
|
|
138
|
+
const devices = this.addon.listDevices();
|
|
116
139
|
return devices.map((device) => applyLogicalPortMapping(device, this.config));
|
|
117
140
|
}
|
|
118
141
|
};
|
package/dist/index.mjs.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/index.ts", "../src/device-filter.ts"],
|
|
4
|
-
"sourcesContent": ["import { createRequire } from \"node:module\";\
|
|
5
|
-
"mappings": ";AAAA,SAAS,qBAAqB;AAC9B,OAAO,UAAU;AACjB,SAAS,qBAAqB;;;ACG9B,SAAS,YAAY,OAAuB;AAC3C,SAAO,MAAM,SAAS,EAAE,EAAE,YAAY,EAAE,SAAS,GAAG,GAAG;AACxD;AAKA,SAAS,cAAc,QAAoB,QAA+B;AACzE,QAAM,YAAY,YAAY,OAAO,GAAG;AACxC,QAAM,YAAY,YAAY,OAAO,GAAG;AACxC,QAAM,YAAY,OAAO,IAAI,YAAY;AACzC,QAAM,YAAY,OAAO,IAAI,YAAY;AAEzC,SAAO,cAAc,aAAa,cAAc;AACjD;AAKA,SAAS,iBAAiB,QAAoB,SAAkC;AAC/E,SAAO,QAAQ,KAAK,CAAC,WAAW,cAAc,QAAQ,MAAM,CAAC;AAC9D;AAeO,SAAS,mBAAmB,QAAoB,QAAiC;AAEvF,MAAI,OAAO,kBAAkB,OAAO,eAAe,SAAS,GAAG;AAC9D,QAAI,iBAAiB,QAAQ,OAAO,cAAc,GAAG;AACpD,aAAO;AAAA,IACR;AAAA,EACD;AAGA,MAAI,OAAO,qBAAqB,OAAO,kBAAkB,SAAS,GAAG;AACpE,QAAI,CAAC,iBAAiB,QAAQ,OAAO,iBAAiB,GAAG;AACxD,aAAO;AAAA,IACR;AAAA,EACD;AAGA,MAAI,OAAO,iBAAiB,OAAO,cAAc,SAAS,GAAG;AAC5D,QAAI,CAAC,iBAAiB,QAAQ,OAAO,aAAa,GAAG;AACpD,aAAO;AAAA,IACR;AAAA,EACD;AAGA,MAAI,OAAO,kBAAkB,OAAO,KAAK,OAAO,cAAc,EAAE,SAAS,GAAG;AAC3E,QAAI,EAAE,OAAO,gBAAgB,OAAO,iBAAiB;AACpD,aAAO;AAAA,IACR;AAAA,EACD;AAEA,SAAO;AACR;AASO,SAAS,wBAAwB,QAAoB,QAAoC;AAC/F,MAAI,OAAO,kBAAkB,OAAO,gBAAgB,OAAO,gBAAgB;AAC1E,WAAO;AAAA,MACN,GAAG;AAAA,MACH,aAAa,OAAO,eAAe,OAAO,YAAY;AAAA,IACvD;AAAA,EACD;AACA,SAAO;AACR;;;ADpEA,
|
|
4
|
+
"sourcesContent": ["import { createRequire } from \"node:module\";\nimport path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { applyLogicalPortMapping, shouldNotifyDevice } from \"./device-filter\";\nimport type {\n\tDeviceAddCallback,\n\tDeviceInfo,\n\tDeviceRemoveCallback,\n\tListenerConfig,\n\tUsbDeviceListenerI,\n} from \"./types\";\n\nexport interface NativeAddon {\n\tstartListening(): void;\n\tstopListening(): void;\n\tonDeviceAdd(callback: DeviceAddCallback): void;\n\tonDeviceRemove(callback: DeviceRemoveCallback): void;\n\tlistDevices(): DeviceInfo[];\n}\n\nfunction loadDefaultAddon(): NativeAddon {\n\tconst require = createRequire(import.meta.url);\n\tconst __filename = fileURLToPath(import.meta.url);\n\tconst __dirname = path.dirname(__filename);\n\tconst packageRoot = path.join(__dirname, \"..\");\n\treturn require(\"node-gyp-build\")(packageRoot);\n}\n\n/**\n * USB Device Listener implementation\n * Provides a type-safe wrapper around the native C++ addon\n */\nexport default class UsbDeviceListener implements UsbDeviceListenerI {\n\tprivate readonly addon: NativeAddon;\n\tprivate config: ListenerConfig = {};\n\tprivate userAddCallback: DeviceAddCallback | null = null;\n\tprivate userRemoveCallback: DeviceRemoveCallback | null = null;\n\n\tconstructor(addon?: NativeAddon) {\n\t\tthis.addon = addon ?? loadDefaultAddon();\n\t}\n\n\t/**\n\t * Start listening for USB device events\n\t */\n\tpublic startListening(config: ListenerConfig): void {\n\t\tif (typeof config !== \"object\" || config === null) {\n\t\t\tthrow new TypeError(\"Config must be an object\");\n\t\t}\n\t\tthis.config = config;\n\t\tthis.addon.startListening();\n\t}\n\n\t/**\n\t * Stop listening for USB device events\n\t */\n\tpublic stopListening(): void {\n\t\tthis.addon.stopListening();\n\t}\n\n\t/**\n\t * Update the listener config at runtime.\n\t * When listening, subsequent device events and listDevices() use the new config.\n\t * When not listening, only listDevices() uses it until the next startListening().\n\t */\n\tpublic updateConfig(config: ListenerConfig): void {\n\t\tif (typeof config !== \"object\" || config === null) {\n\t\t\tthrow new TypeError(\"Config must be an object\");\n\t\t}\n\t\tthis.config = config;\n\t}\n\n\t/**\n\t * Return a shallow copy of the current config.\n\t * Mutating the returned object does not affect the listener's internal config.\n\t */\n\tpublic getCurrentConfig(): ListenerConfig {\n\t\treturn { ...this.config };\n\t}\n\n\t/**\n\t * Register callback for device connection events\n\t */\n\tpublic onDeviceAdd(callback: DeviceAddCallback): void {\n\t\tif (typeof callback !== \"function\") {\n\t\t\tthrow new TypeError(\"Callback must be a function\");\n\t\t}\n\t\tthis.userAddCallback = callback;\n\n\t\t// Set up internal callback that filters devices\n\t\tthis.addon.onDeviceAdd((device: DeviceInfo) => {\n\t\t\tif (shouldNotifyDevice(device, this.config)) {\n\t\t\t\tconst enrichedDevice = applyLogicalPortMapping(device, this.config);\n\t\t\t\tthis.userAddCallback?.(enrichedDevice);\n\t\t\t}\n\t\t});\n\t}\n\n\t/**\n\t * Register callback for device disconnection events\n\t */\n\tpublic onDeviceRemove(callback: DeviceRemoveCallback): void {\n\t\tif (typeof callback !== \"function\") {\n\t\t\tthrow new TypeError(\"Callback must be a function\");\n\t\t}\n\t\tthis.userRemoveCallback = callback;\n\n\t\t// Set up internal callback that filters devices\n\t\tthis.addon.onDeviceRemove((device: DeviceInfo) => {\n\t\t\tif (shouldNotifyDevice(device, this.config)) {\n\t\t\t\tconst enrichedDevice = applyLogicalPortMapping(device, this.config);\n\t\t\t\tthis.userRemoveCallback?.(enrichedDevice);\n\t\t\t}\n\t\t});\n\t}\n\n\t/**\n\t * List all currently connected USB devices\n\t * Applies logical port mapping from config if set\n\t */\n\tpublic listDevices(): DeviceInfo[] {\n\t\tconst devices = this.addon.listDevices();\n\t\t// Apply logical port mapping to each device\n\t\treturn devices.map((device) => applyLogicalPortMapping(device, this.config));\n\t}\n}\n\nexport type {\n\tDeviceInfo,\n\tDeviceAddCallback,\n\tDeviceRemoveCallback,\n\tListenerConfig,\n\tTargetDevice,\n} from \"./types\";\n", "import type { DeviceInfo, ListenerConfig, TargetDevice } from \"./types\";\n\n/**\n * Convert a decimal VID/PID to uppercase hex string for comparison\n */\nfunction toHexString(value: number): string {\n\treturn value.toString(16).toUpperCase().padStart(4, \"0\");\n}\n\n/**\n * Check if a device matches a target device filter by VID/PID\n */\nfunction matchesDevice(device: DeviceInfo, target: TargetDevice): boolean {\n\tconst deviceVid = toHexString(device.vid);\n\tconst devicePid = toHexString(device.pid);\n\tconst targetVid = target.vid.toUpperCase();\n\tconst targetPid = target.pid.toUpperCase();\n\n\treturn deviceVid === targetVid && devicePid === targetPid;\n}\n\n/**\n * Check if a device matches any device in a list of target devices\n */\nfunction matchesAnyDevice(device: DeviceInfo, targets: TargetDevice[]): boolean {\n\treturn targets.some((target) => matchesDevice(device, target));\n}\n\n/**\n * Determine if a device notification should be sent based on the configuration.\n *\n * Filter priority (highest to lowest):\n * 1. ignoredDevices - if device matches, always return false\n * 2. listenOnlyDevices - if specified, device must match at least one\n * 3. targetDevices - if specified, device must match at least one\n * 4. logicalPortMap - if specified, device location must be in the map\n *\n * @param device - The device information from the native addon\n * @param config - The listener configuration\n * @returns true if the device should trigger a notification, false otherwise\n */\nexport function shouldNotifyDevice(device: DeviceInfo, config: ListenerConfig): boolean {\n\t// Priority 1: Check ignoredDevices (highest priority - always blocks)\n\tif (config.ignoredDevices && config.ignoredDevices.length > 0) {\n\t\tif (matchesAnyDevice(device, config.ignoredDevices)) {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t// Priority 2: Check listenOnlyDevices (if specified, device must match)\n\tif (config.listenOnlyDevices && config.listenOnlyDevices.length > 0) {\n\t\tif (!matchesAnyDevice(device, config.listenOnlyDevices)) {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t// Priority 3: Check targetDevices (if specified, device must match)\n\tif (config.targetDevices && config.targetDevices.length > 0) {\n\t\tif (!matchesAnyDevice(device, config.targetDevices)) {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t// Priority 4: Check logicalPortMap (if specified, device must be mapped)\n\tif (config.logicalPortMap && Object.keys(config.logicalPortMap).length > 0) {\n\t\tif (!(device.locationInfo in config.logicalPortMap)) {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\treturn true;\n}\n\n/**\n * Apply logical port mapping to a device if configured\n *\n * @param device - The device information from the native addon\n * @param config - The listener configuration\n * @returns Device info with logicalPort set if mapped, otherwise unchanged\n */\nexport function applyLogicalPortMapping(device: DeviceInfo, config: ListenerConfig): DeviceInfo {\n\tif (config.logicalPortMap && device.locationInfo in config.logicalPortMap) {\n\t\treturn {\n\t\t\t...device,\n\t\t\tlogicalPort: config.logicalPortMap[device.locationInfo],\n\t\t};\n\t}\n\treturn device;\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["require"]
|
|
7
7
|
}
|
package/dist/types.d.ts
CHANGED
|
@@ -157,6 +157,32 @@ export interface UsbDeviceListenerI {
|
|
|
157
157
|
* listener.stopListening();
|
|
158
158
|
*/
|
|
159
159
|
stopListening(): void;
|
|
160
|
+
/**
|
|
161
|
+
* Update the config used for filtering and logical port mapping.
|
|
162
|
+
*
|
|
163
|
+
* When listening, subsequent device events and listDevices() use the new config.
|
|
164
|
+
* When not listening, only listDevices() uses it until the next startListening().
|
|
165
|
+
*
|
|
166
|
+
* @param config - New listener configuration (full replace; use getCurrentConfig() to merge)
|
|
167
|
+
* @throws {TypeError} If config is not an object
|
|
168
|
+
*
|
|
169
|
+
* @example
|
|
170
|
+
* listener.updateConfig({ ...listener.getCurrentConfig(), logicalPortMap: newMap });
|
|
171
|
+
*/
|
|
172
|
+
updateConfig(config: ListenerConfig): void;
|
|
173
|
+
/**
|
|
174
|
+
* Return a copy of the current config.
|
|
175
|
+
*
|
|
176
|
+
* Mutating the returned object does not affect the listener's internal config.
|
|
177
|
+
* Use with updateConfig() to merge partial changes.
|
|
178
|
+
*
|
|
179
|
+
* @returns Shallow copy of the current ListenerConfig
|
|
180
|
+
*
|
|
181
|
+
* @example
|
|
182
|
+
* const current = listener.getCurrentConfig();
|
|
183
|
+
* listener.updateConfig({ ...current, targetDevices: [...(current.targetDevices ?? []), newDevice] });
|
|
184
|
+
*/
|
|
185
|
+
getCurrentConfig(): ListenerConfig;
|
|
160
186
|
/**
|
|
161
187
|
* Register callback for device connection events
|
|
162
188
|
*
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;GAEG;AACH,MAAM,WAAW,UAAU;IAC1B;;;;;OAKG;IACH,QAAQ,EAAE,MAAM,CAAC;IAEjB;;;OAGG;IACH,YAAY,EAAE,MAAM,CAAC;IAErB;;;;OAIG;IACH,UAAU,EAAE,MAAM,CAAC;IAEnB;;;OAGG;IACH,GAAG,EAAE,MAAM,CAAC;IAEZ;;;OAGG;IACH,GAAG,EAAE,MAAM,CAAC;IAEZ;;;;OAIG;IACH,YAAY,EAAE,MAAM,CAAC;IAErB;;;OAGG;IACH,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC5B;;OAEG;IACH,GAAG,EAAE,MAAM,CAAC;IAEZ;;OAEG;IACH,GAAG,EAAE,MAAM,CAAC;CACZ;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC9B;;;;;;;;;;;;;OAaG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAExC;;;;;;;;;;OAUG;IACH,aAAa,CAAC,EAAE,YAAY,EAAE,CAAC;IAE/B;;;;;;;;;;;OAWG;IACH,cAAc,CAAC,EAAE,YAAY,EAAE,CAAC;IAEhC;;;;;;;;;;OAUG;IACH,iBAAiB,CAAC,EAAE,YAAY,EAAE,CAAC;CACnC;AAED;;GAEG;AACH,MAAM,MAAM,iBAAiB,GAAG,CAAC,UAAU,EAAE,UAAU,KAAK,IAAI,CAAC;AAEjE;;GAEG;AACH,MAAM,MAAM,oBAAoB,GAAG,CAAC,UAAU,EAAE,UAAU,KAAK,IAAI,CAAC;AAEpE;;GAEG;AACH,MAAM,WAAW,kBAAkB;IAClC;;;;;;;;;;;;;;;;OAgBG;IACH,cAAc,CAAC,MAAM,EAAE,cAAc,GAAG,IAAI,CAAC;IAE7C;;;;;;;;OAQG;IACH,aAAa,IAAI,IAAI,CAAC;IAEtB;;;;;;;;;;;;;;OAcG;IACH,WAAW,CAAC,QAAQ,EAAE,iBAAiB,GAAG,IAAI,CAAC;IAE/C;;;;;;;;;;;;;OAaG;IACH,cAAc,CAAC,QAAQ,EAAE,oBAAoB,GAAG,IAAI,CAAC;IAErD;;;;;;;;;;;;;;OAcG;IACH,WAAW,IAAI,UAAU,EAAE,CAAC;CAC5B"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;GAEG;AACH,MAAM,WAAW,UAAU;IAC1B;;;;;OAKG;IACH,QAAQ,EAAE,MAAM,CAAC;IAEjB;;;OAGG;IACH,YAAY,EAAE,MAAM,CAAC;IAErB;;;;OAIG;IACH,UAAU,EAAE,MAAM,CAAC;IAEnB;;;OAGG;IACH,GAAG,EAAE,MAAM,CAAC;IAEZ;;;OAGG;IACH,GAAG,EAAE,MAAM,CAAC;IAEZ;;;;OAIG;IACH,YAAY,EAAE,MAAM,CAAC;IAErB;;;OAGG;IACH,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC5B;;OAEG;IACH,GAAG,EAAE,MAAM,CAAC;IAEZ;;OAEG;IACH,GAAG,EAAE,MAAM,CAAC;CACZ;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC9B;;;;;;;;;;;;;OAaG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAExC;;;;;;;;;;OAUG;IACH,aAAa,CAAC,EAAE,YAAY,EAAE,CAAC;IAE/B;;;;;;;;;;;OAWG;IACH,cAAc,CAAC,EAAE,YAAY,EAAE,CAAC;IAEhC;;;;;;;;;;OAUG;IACH,iBAAiB,CAAC,EAAE,YAAY,EAAE,CAAC;CACnC;AAED;;GAEG;AACH,MAAM,MAAM,iBAAiB,GAAG,CAAC,UAAU,EAAE,UAAU,KAAK,IAAI,CAAC;AAEjE;;GAEG;AACH,MAAM,MAAM,oBAAoB,GAAG,CAAC,UAAU,EAAE,UAAU,KAAK,IAAI,CAAC;AAEpE;;GAEG;AACH,MAAM,WAAW,kBAAkB;IAClC;;;;;;;;;;;;;;;;OAgBG;IACH,cAAc,CAAC,MAAM,EAAE,cAAc,GAAG,IAAI,CAAC;IAE7C;;;;;;;;OAQG;IACH,aAAa,IAAI,IAAI,CAAC;IAEtB;;;;;;;;;;;OAWG;IACH,YAAY,CAAC,MAAM,EAAE,cAAc,GAAG,IAAI,CAAC;IAE3C;;;;;;;;;;;OAWG;IACH,gBAAgB,IAAI,cAAc,CAAC;IAEnC;;;;;;;;;;;;;;OAcG;IACH,WAAW,CAAC,QAAQ,EAAE,iBAAiB,GAAG,IAAI,CAAC;IAE/C;;;;;;;;;;;;;OAaG;IACH,cAAc,CAAC,QAAQ,EAAE,oBAAoB,GAAG,IAAI,CAAC;IAErD;;;;;;;;;;;;;;OAcG;IACH,WAAW,IAAI,UAAU,EAAE,CAAC;CAC5B"}
|