@neurodevs/node-lsl 18.1.0 → 19.0.0

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.
Files changed (62) hide show
  1. package/build/__tests__/AbstractPackageTest.d.ts +12 -10
  2. package/build/__tests__/AbstractPackageTest.js +33 -14
  3. package/build/__tests__/AbstractPackageTest.js.map +1 -1
  4. package/build/__tests__/impl/BleDeviceController.test.d.ts +5 -0
  5. package/build/__tests__/impl/BleDeviceController.test.js +36 -5
  6. package/build/__tests__/impl/BleDeviceController.test.js.map +1 -1
  7. package/build/__tests__/impl/LslStreamOutlet.test.js +2 -4
  8. package/build/__tests__/impl/LslStreamOutlet.test.js.map +1 -1
  9. package/build/__tests__/impl/UsbDeviceController.test.d.ts +17 -0
  10. package/build/__tests__/impl/UsbDeviceController.test.js +81 -0
  11. package/build/__tests__/impl/UsbDeviceController.test.js.map +1 -0
  12. package/build/__tests__/impl/WindowedClockRegressor.test.d.ts +19 -0
  13. package/build/__tests__/impl/WindowedClockRegressor.test.js +172 -0
  14. package/build/__tests__/impl/WindowedClockRegressor.test.js.map +1 -0
  15. package/build/impl/LslStreamInlet.d.ts +1 -0
  16. package/build/impl/LslStreamInlet.js +2 -1
  17. package/build/impl/LslStreamInlet.js.map +1 -1
  18. package/build/impl/LslStreamOutlet.d.ts +1 -0
  19. package/build/impl/LslStreamOutlet.js +2 -1
  20. package/build/impl/LslStreamOutlet.js.map +1 -1
  21. package/build/impl/WindowedClockRegressor.d.ts +24 -0
  22. package/build/impl/WindowedClockRegressor.js +73 -0
  23. package/build/impl/WindowedClockRegressor.js.map +1 -0
  24. package/build/impl/controllers/BleDeviceController.d.ts +2 -0
  25. package/build/impl/controllers/BleDeviceController.js +8 -0
  26. package/build/impl/controllers/BleDeviceController.js.map +1 -1
  27. package/build/impl/controllers/UsbDeviceController.d.ts +23 -0
  28. package/build/impl/controllers/UsbDeviceController.js +40 -0
  29. package/build/impl/controllers/UsbDeviceController.js.map +1 -0
  30. package/build/index.d.ts +8 -0
  31. package/build/index.js +10 -0
  32. package/build/index.js.map +1 -1
  33. package/build/scripts/runUsb.d.ts +1 -0
  34. package/build/scripts/runUsb.js +14 -0
  35. package/build/scripts/runUsb.js.map +1 -0
  36. package/build/testDoubles/BleController/FakeBleController.d.ts +3 -1
  37. package/build/testDoubles/BleController/FakeBleController.js +5 -0
  38. package/build/testDoubles/BleController/FakeBleController.js.map +1 -1
  39. package/build/testDoubles/ClockRegressor/FakeClockRegressor.d.ts +17 -0
  40. package/build/testDoubles/ClockRegressor/FakeClockRegressor.js +23 -0
  41. package/build/testDoubles/ClockRegressor/FakeClockRegressor.js.map +1 -0
  42. package/build/testDoubles/UsbController/FakeUsbController.d.ts +12 -0
  43. package/build/testDoubles/UsbController/FakeUsbController.js +25 -0
  44. package/build/testDoubles/UsbController/FakeUsbController.js.map +1 -0
  45. package/build/testDoubles/WebSocketBridge/FakeWebSocketBridge.js.map +1 -1
  46. package/package.json +4 -4
  47. package/src/__tests__/AbstractPackageTest.ts +59 -21
  48. package/src/__tests__/impl/BleDeviceController.test.ts +51 -8
  49. package/src/__tests__/impl/LslStreamOutlet.test.ts +5 -4
  50. package/src/__tests__/impl/UsbDeviceController.test.ts +109 -0
  51. package/src/__tests__/impl/WindowedClockRegressor.test.ts +262 -0
  52. package/src/impl/LslStreamInlet.ts +4 -1
  53. package/src/impl/LslStreamOutlet.ts +2 -1
  54. package/src/impl/WindowedClockRegressor.ts +136 -0
  55. package/src/impl/controllers/BleDeviceController.ts +17 -0
  56. package/src/impl/controllers/UsbDeviceController.ts +65 -0
  57. package/src/index.ts +16 -0
  58. package/src/scripts/runUsb.ts +20 -0
  59. package/src/testDoubles/BleController/FakeBleController.ts +11 -0
  60. package/src/testDoubles/ClockRegressor/FakeClockRegressor.ts +46 -0
  61. package/src/testDoubles/UsbController/FakeUsbController.ts +34 -0
  62. package/src/testDoubles/WebSocketBridge/FakeWebSocketBridge.ts +1 -2
@@ -3,6 +3,7 @@ export default class FakeBleController {
3
3
  static callsToConstructor = [];
4
4
  static numCallsToConnect = 0;
5
5
  static callsToWriteCharacteristic = [];
6
+ static callsToSubscribeCharacteristics = [];
6
7
  static numCallsToDisconnect = 0;
7
8
  static fakeCharacteristics = {};
8
9
  static fakeName = `fake-${generateId()}`;
@@ -23,6 +24,9 @@ export default class FakeBleController {
23
24
  value,
24
25
  });
25
26
  }
27
+ async subscribeCharacteristics(charCallbacks) {
28
+ FakeBleController.callsToSubscribeCharacteristics.push(charCallbacks);
29
+ }
26
30
  async disconnect() {
27
31
  FakeBleController.numCallsToDisconnect++;
28
32
  }
@@ -36,6 +40,7 @@ export default class FakeBleController {
36
40
  this.callsToConstructor = [];
37
41
  this.numCallsToConnect = 0;
38
42
  this.callsToWriteCharacteristic = [];
43
+ this.callsToSubscribeCharacteristics = [];
39
44
  this.numCallsToDisconnect = 0;
40
45
  }
41
46
  }
@@ -1 +1 @@
1
- {"version":3,"file":"FakeBleController.js","sourceRoot":"","sources":["../../../src/testDoubles/BleController/FakeBleController.ts"],"names":[],"mappings":"AAAA,OAAO,UAAU,MAAM,wBAAwB,CAAA;AAM/C,MAAM,CAAC,OAAO,OAAO,iBAAiB;IAC3B,MAAM,CAAC,kBAAkB,GAAyC,EAAE,CAAA;IAEpE,MAAM,CAAC,iBAAiB,GAAG,CAAC,CAAA;IAE5B,MAAM,CAAC,0BAA0B,GAGlC,EAAE,CAAA;IAED,MAAM,CAAC,oBAAoB,GAAG,CAAC,CAAA;IAE/B,MAAM,CAAC,mBAAmB,GAA4B,EAAE,CAAA;IACxD,MAAM,CAAC,QAAQ,GAAG,QAAQ,UAAU,EAAE,EAAE,CAAA;IAEvC,KAAK,CAAQ;IACb,KAAK,CAAQ;IAErB,YAAmB,OAA8B;QAC7C,MAAM,EAAE,UAAU,EAAE,GAAG,OAAO,IAAI,EAAE,CAAA;QAEpC,IAAI,CAAC,KAAK,GAAG,UAAU,IAAI,UAAU,EAAE,CAAA;QACvC,IAAI,CAAC,KAAK,GAAG,iBAAiB,CAAC,QAAQ,CAAA;QAEvC,iBAAiB,CAAC,kBAAkB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;IACtD,CAAC;IAEM,KAAK,CAAC,OAAO;QAChB,iBAAiB,CAAC,iBAAiB,EAAE,CAAA;IACzC,CAAC;IAEM,KAAK,CAAC,mBAAmB,CAC5B,kBAA0B,EAC1B,KAAa;QAEb,iBAAiB,CAAC,0BAA0B,CAAC,IAAI,CAAC;YAC9C,kBAAkB;YAClB,KAAK;SACR,CAAC,CAAA;IACN,CAAC;IAEM,KAAK,CAAC,UAAU;QACnB,iBAAiB,CAAC,oBAAoB,EAAE,CAAA;IAC5C,CAAC;IAED,IAAW,IAAI;QACX,OAAO,IAAI,CAAC,KAAK,CAAA;IACrB,CAAC;IAED,IAAW,IAAI;QACX,OAAO,IAAI,CAAC,KAAK,CAAA;IACrB,CAAC;IAEM,MAAM,CAAC,eAAe;QACzB,IAAI,CAAC,kBAAkB,GAAG,EAAE,CAAA;QAC5B,IAAI,CAAC,iBAAiB,GAAG,CAAC,CAAA;QAC1B,IAAI,CAAC,0BAA0B,GAAG,EAAE,CAAA;QACpC,IAAI,CAAC,oBAAoB,GAAG,CAAC,CAAA;IACjC,CAAC"}
1
+ {"version":3,"file":"FakeBleController.js","sourceRoot":"","sources":["../../../src/testDoubles/BleController/FakeBleController.ts"],"names":[],"mappings":"AAAA,OAAO,UAAU,MAAM,wBAAwB,CAAA;AAO/C,MAAM,CAAC,OAAO,OAAO,iBAAiB;IAC3B,MAAM,CAAC,kBAAkB,GAAyC,EAAE,CAAA;IAEpE,MAAM,CAAC,iBAAiB,GAAG,CAAC,CAAA;IAE5B,MAAM,CAAC,0BAA0B,GAGlC,EAAE,CAAA;IAED,MAAM,CAAC,+BAA+B,GACzC,EAAE,CAAA;IAEC,MAAM,CAAC,oBAAoB,GAAG,CAAC,CAAA;IAE/B,MAAM,CAAC,mBAAmB,GAA4B,EAAE,CAAA;IACxD,MAAM,CAAC,QAAQ,GAAG,QAAQ,UAAU,EAAE,EAAE,CAAA;IAEvC,KAAK,CAAQ;IACb,KAAK,CAAQ;IAErB,YAAmB,OAA8B;QAC7C,MAAM,EAAE,UAAU,EAAE,GAAG,OAAO,IAAI,EAAE,CAAA;QAEpC,IAAI,CAAC,KAAK,GAAG,UAAU,IAAI,UAAU,EAAE,CAAA;QACvC,IAAI,CAAC,KAAK,GAAG,iBAAiB,CAAC,QAAQ,CAAA;QAEvC,iBAAiB,CAAC,kBAAkB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;IACtD,CAAC;IAEM,KAAK,CAAC,OAAO;QAChB,iBAAiB,CAAC,iBAAiB,EAAE,CAAA;IACzC,CAAC;IAEM,KAAK,CAAC,mBAAmB,CAC5B,kBAA0B,EAC1B,KAAa;QAEb,iBAAiB,CAAC,0BAA0B,CAAC,IAAI,CAAC;YAC9C,kBAAkB;YAClB,KAAK;SACR,CAAC,CAAA;IACN,CAAC;IAEM,KAAK,CAAC,wBAAwB,CACjC,aAAsC;QAEtC,iBAAiB,CAAC,+BAA+B,CAAC,IAAI,CAAC,aAAa,CAAC,CAAA;IACzE,CAAC;IAEM,KAAK,CAAC,UAAU;QACnB,iBAAiB,CAAC,oBAAoB,EAAE,CAAA;IAC5C,CAAC;IAED,IAAW,IAAI;QACX,OAAO,IAAI,CAAC,KAAK,CAAA;IACrB,CAAC;IAED,IAAW,IAAI;QACX,OAAO,IAAI,CAAC,KAAK,CAAA;IACrB,CAAC;IAEM,MAAM,CAAC,eAAe;QACzB,IAAI,CAAC,kBAAkB,GAAG,EAAE,CAAA;QAC5B,IAAI,CAAC,iBAAiB,GAAG,CAAC,CAAA;QAC1B,IAAI,CAAC,0BAA0B,GAAG,EAAE,CAAA;QACpC,IAAI,CAAC,+BAA+B,GAAG,EAAE,CAAA;QACzC,IAAI,CAAC,oBAAoB,GAAG,CAAC,CAAA;IACjC,CAAC"}
@@ -0,0 +1,17 @@
1
+ import { ClockRegressor, WindowedClockRegressorOptions } from '../../impl/WindowedClockRegressor.js';
2
+ export default class FakeClockRegressor implements ClockRegressor {
3
+ static callsToConstructor: {
4
+ nominalHz: number;
5
+ options?: WindowedClockRegressorOptions;
6
+ }[];
7
+ static callsToDeriveTimestamps: {
8
+ deviceTime: number;
9
+ earliestLslTime: number;
10
+ chunkSize: number;
11
+ }[];
12
+ static fakeResultValue: number;
13
+ readonly nominalHz: number;
14
+ constructor(nominalHz: number, options?: WindowedClockRegressorOptions);
15
+ deriveTimestamps(deviceTime: number, earliestLslTime: number, chunkSize: number): any[];
16
+ static resetTestDouble(): void;
17
+ }
@@ -0,0 +1,23 @@
1
+ export default class FakeClockRegressor {
2
+ static callsToConstructor = [];
3
+ static callsToDeriveTimestamps = [];
4
+ static fakeResultValue = 0;
5
+ nominalHz;
6
+ constructor(nominalHz, options) {
7
+ FakeClockRegressor.callsToConstructor.push({ nominalHz, options });
8
+ this.nominalHz = nominalHz;
9
+ }
10
+ deriveTimestamps(deviceTime, earliestLslTime, chunkSize) {
11
+ FakeClockRegressor.callsToDeriveTimestamps.push({
12
+ deviceTime,
13
+ earliestLslTime,
14
+ chunkSize,
15
+ });
16
+ return Array(chunkSize).fill(FakeClockRegressor.fakeResultValue);
17
+ }
18
+ static resetTestDouble() {
19
+ FakeClockRegressor.callsToConstructor = [];
20
+ FakeClockRegressor.callsToDeriveTimestamps = [];
21
+ }
22
+ }
23
+ //# sourceMappingURL=FakeClockRegressor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FakeClockRegressor.js","sourceRoot":"","sources":["../../../src/testDoubles/ClockRegressor/FakeClockRegressor.ts"],"names":[],"mappings":"AAKA,MAAM,CAAC,OAAO,OAAO,kBAAkB;IAC5B,MAAM,CAAC,kBAAkB,GAG1B,EAAE,CAAA;IACD,MAAM,CAAC,uBAAuB,GAI/B,EAAE,CAAA;IAED,MAAM,CAAC,eAAe,GAAG,CAAC,CAAA;IAEjB,SAAS,CAAQ;IAEjC,YACI,SAAiB,EACjB,OAAuC;QAEvC,kBAAkB,CAAC,kBAAkB,CAAC,IAAI,CAAC,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,CAAA;QAClE,IAAI,CAAC,SAAS,GAAG,SAAS,CAAA;IAC9B,CAAC;IAEM,gBAAgB,CACnB,UAAkB,EAClB,eAAuB,EACvB,SAAiB;QAEjB,kBAAkB,CAAC,uBAAuB,CAAC,IAAI,CAAC;YAC5C,UAAU;YACV,eAAe;YACf,SAAS;SACZ,CAAC,CAAA;QACF,OAAO,KAAK,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,kBAAkB,CAAC,eAAe,CAAC,CAAA;IACpE,CAAC;IAEM,MAAM,CAAC,eAAe;QACzB,kBAAkB,CAAC,kBAAkB,GAAG,EAAE,CAAA;QAC1C,kBAAkB,CAAC,uBAAuB,GAAG,EAAE,CAAA;IACnD,CAAC"}
@@ -0,0 +1,12 @@
1
+ import { UsbController, UsbControllerOptions } from '../../impl/controllers/UsbDeviceController.js';
2
+ export default class FakeUsbController implements UsbController {
3
+ static callsToConstructor: (UsbControllerOptions | undefined)[];
4
+ static numCallsToConnect: number;
5
+ static callsToWriteUsb: string[];
6
+ static numCallsToDisconnect: number;
7
+ constructor(options?: UsbControllerOptions);
8
+ connect(): Promise<void>;
9
+ writeUsb(value: string): Promise<void>;
10
+ disconnect(): Promise<void>;
11
+ static resetTestDouble(): void;
12
+ }
@@ -0,0 +1,25 @@
1
+ export default class FakeUsbController {
2
+ static callsToConstructor = [];
3
+ static numCallsToConnect = 0;
4
+ static callsToWriteUsb = [];
5
+ static numCallsToDisconnect = 0;
6
+ constructor(options) {
7
+ FakeUsbController.callsToConstructor.push(options);
8
+ }
9
+ async connect() {
10
+ FakeUsbController.numCallsToConnect++;
11
+ }
12
+ async writeUsb(value) {
13
+ FakeUsbController.callsToWriteUsb.push(value);
14
+ }
15
+ async disconnect() {
16
+ FakeUsbController.numCallsToDisconnect++;
17
+ }
18
+ static resetTestDouble() {
19
+ FakeUsbController.callsToConstructor.length = 0;
20
+ FakeUsbController.numCallsToConnect = 0;
21
+ FakeUsbController.callsToWriteUsb.length = 0;
22
+ FakeUsbController.numCallsToDisconnect = 0;
23
+ }
24
+ }
25
+ //# sourceMappingURL=FakeUsbController.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FakeUsbController.js","sourceRoot":"","sources":["../../../src/testDoubles/UsbController/FakeUsbController.ts"],"names":[],"mappings":"AAKA,MAAM,CAAC,OAAO,OAAO,iBAAiB;IAC3B,MAAM,CAAC,kBAAkB,GAAyC,EAAE,CAAA;IACpE,MAAM,CAAC,iBAAiB,GAAG,CAAC,CAAA;IAC5B,MAAM,CAAC,eAAe,GAAa,EAAE,CAAA;IACrC,MAAM,CAAC,oBAAoB,GAAG,CAAC,CAAA;IAEtC,YAAmB,OAA8B;QAC7C,iBAAiB,CAAC,kBAAkB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;IACtD,CAAC;IAEM,KAAK,CAAC,OAAO;QAChB,iBAAiB,CAAC,iBAAiB,EAAE,CAAA;IACzC,CAAC;IAEM,KAAK,CAAC,QAAQ,CAAC,KAAa;QAC/B,iBAAiB,CAAC,eAAe,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IACjD,CAAC;IAEM,KAAK,CAAC,UAAU;QACnB,iBAAiB,CAAC,oBAAoB,EAAE,CAAA;IAC5C,CAAC;IAEM,MAAM,CAAC,eAAe;QACzB,iBAAiB,CAAC,kBAAkB,CAAC,MAAM,GAAG,CAAC,CAAA;QAC/C,iBAAiB,CAAC,iBAAiB,GAAG,CAAC,CAAA;QACvC,iBAAiB,CAAC,eAAe,CAAC,MAAM,GAAG,CAAC,CAAA;QAC5C,iBAAiB,CAAC,oBAAoB,GAAG,CAAC,CAAA;IAC9C,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"FakeWebSocketBridge.js","sourceRoot":"","sources":["../../../src/testDoubles/WebSocketBridge/FakeWebSocketBridge.ts"],"names":[],"mappings":"AACA,OAAO,kBAGN,MAAM,kCAAkC,CAAA;AACzC,OAAO,aAAa,MAAM,gCAAgC,CAAA;AAC1D,OAAO,mBAAmB,MAAM,sCAAsC,CAAA;AAEtE,MAAM,CAAC,OAAO,OAAO,mBAAmB;IAC7B,MAAM,CAAC,kBAAkB,GAG1B,EAAE,CAAA;IAED,MAAM,CAAC,kBAAkB,GAAG,CAAC,CAAA;IAC7B,MAAM,CAAC,oBAAoB,GAAG,CAAC,CAAA;IAC/B,MAAM,CAAC,iBAAiB,GAAG,CAAC,CAAA;IAEnC,YAAmB,OAA2C;QAC1D,mBAAmB,CAAC,kBAAkB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;IACxD,CAAC;IAEM,KAAK,CAAC,QAAQ;QACjB,mBAAmB,CAAC,kBAAkB,EAAE,CAAA;IAC5C,CAAC;IAEM,UAAU;QACb,mBAAmB,CAAC,oBAAoB,EAAE,CAAA;IAC9C,CAAC;IAEM,OAAO;QACV,mBAAmB,CAAC,iBAAiB,EAAE,CAAA;IAC3C,CAAC;IAEM,MAAM,CAAC,eAAe;QACzB,IAAI,CAAC,kBAAkB,GAAG,EAAE,CAAA;QAC5B,IAAI,CAAC,kBAAkB,GAAG,CAAC,CAAA;QAC3B,IAAI,CAAC,oBAAoB,GAAG,CAAC,CAAA;QAC7B,IAAI,CAAC,iBAAiB,GAAG,CAAC,CAAA;QAE1B,IAAI,CAAC,gBAAgB,EAAE,CAAA;QACvB,IAAI,CAAC,sBAAsB,EAAE,CAAA;IACjC,CAAC;IAEO,MAAM,CAAC,gBAAgB;QAC3B,kBAAkB,CAAC,EAAE,GAAG,aAA4C,CAAA;QACpE,aAAa,CAAC,eAAe,EAAE,CAAA;IACnC,CAAC;IAEO,MAAM,CAAC,sBAAsB;QACjC,kBAAkB,CAAC,GAAG;YAClB,mBAAwD,CAAA;QAC5D,mBAAmB,CAAC,eAAe,EAAE,CAAA;IACzC,CAAC"}
1
+ {"version":3,"file":"FakeWebSocketBridge.js","sourceRoot":"","sources":["../../../src/testDoubles/WebSocketBridge/FakeWebSocketBridge.ts"],"names":[],"mappings":"AACA,OAAO,kBAGN,MAAM,kCAAkC,CAAA;AACzC,OAAO,aAAa,MAAM,gCAAgC,CAAA;AAC1D,OAAO,mBAAmB,MAAM,sCAAsC,CAAA;AAEtE,MAAM,CAAC,OAAO,OAAO,mBAAmB;IAC7B,MAAM,CAAC,kBAAkB,GAE1B,EAAE,CAAA;IAED,MAAM,CAAC,kBAAkB,GAAG,CAAC,CAAA;IAC7B,MAAM,CAAC,oBAAoB,GAAG,CAAC,CAAA;IAC/B,MAAM,CAAC,iBAAiB,GAAG,CAAC,CAAA;IAEnC,YAAmB,OAA2C;QAC1D,mBAAmB,CAAC,kBAAkB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;IACxD,CAAC;IAEM,KAAK,CAAC,QAAQ;QACjB,mBAAmB,CAAC,kBAAkB,EAAE,CAAA;IAC5C,CAAC;IAEM,UAAU;QACb,mBAAmB,CAAC,oBAAoB,EAAE,CAAA;IAC9C,CAAC;IAEM,OAAO;QACV,mBAAmB,CAAC,iBAAiB,EAAE,CAAA;IAC3C,CAAC;IAEM,MAAM,CAAC,eAAe;QACzB,IAAI,CAAC,kBAAkB,GAAG,EAAE,CAAA;QAC5B,IAAI,CAAC,kBAAkB,GAAG,CAAC,CAAA;QAC3B,IAAI,CAAC,oBAAoB,GAAG,CAAC,CAAA;QAC7B,IAAI,CAAC,iBAAiB,GAAG,CAAC,CAAA;QAE1B,IAAI,CAAC,gBAAgB,EAAE,CAAA;QACvB,IAAI,CAAC,sBAAsB,EAAE,CAAA;IACjC,CAAC;IAEO,MAAM,CAAC,gBAAgB;QAC3B,kBAAkB,CAAC,EAAE,GAAG,aAA4C,CAAA;QACpE,aAAa,CAAC,eAAe,EAAE,CAAA;IACnC,CAAC;IAEO,MAAM,CAAC,sBAAsB;QACjC,kBAAkB,CAAC,GAAG;YAClB,mBAAwD,CAAA;QAC5D,mBAAmB,CAAC,eAAe,EAAE,CAAA;IACzC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@neurodevs/node-lsl",
3
- "version": "18.1.0",
3
+ "version": "19.0.0",
4
4
  "description": "Lab Streaming Layer (LSL) bindings for Node",
5
5
  "type": "module",
6
6
  "keywords": [
@@ -41,8 +41,8 @@
41
41
  "watch.build.dev": "tsc-watch --sourceMap --onCompilationComplete 'yarn run build.copy-files'"
42
42
  },
43
43
  "dependencies": {
44
- "@neurodevs/generate-id": "^1.1.2",
45
- "@neurodevs/ndx-native": "^7.0.1",
44
+ "@neurodevs/generate-id": "^1.1.3",
45
+ "@neurodevs/ndx-native": "^7.1.4",
46
46
  "ffi-rs": "^1.3.1",
47
47
  "ws": "^8.18.3"
48
48
  },
@@ -51,7 +51,7 @@
51
51
  "@neurodevs/node-tdd": "^3.0.1",
52
52
  "@neurodevs/prettier-config-ndx": "^1.0.2",
53
53
  "@types/ws": "^8.18.1",
54
- "prettier": "^3.8.3",
54
+ "prettier": "^3.9.4",
55
55
  "typescript": "^5.9.3"
56
56
  },
57
57
  "resolutions": {
@@ -1,3 +1,6 @@
1
+ import { randomInt } from 'node:crypto'
2
+
3
+ import WebSocket, { Server } from 'ws'
1
4
  import {
2
5
  FakeLiblsl,
3
6
  FakeLibndx,
@@ -6,7 +9,6 @@ import {
6
9
  LibndxAdapter,
7
10
  } from '@neurodevs/ndx-native'
8
11
  import AbstractModuleTest from '@neurodevs/node-tdd'
9
- import WebSocket, { Server } from 'ws'
10
12
 
11
13
  import SpyEventMarkerEmitter from '../testDoubles/EventMarkerEmitter/SpyEventMarkerEmitter.js'
12
14
  import FakeStreamInfo from '../testDoubles/StreamInfo/FakeStreamInfo.js'
@@ -17,7 +19,6 @@ import FakeStreamOutlet from '../testDoubles/StreamOutlet/FakeStreamOutlet.js'
17
19
  import SpyLslWebSocketBridge from '../testDoubles/WebSocketBridge/SpyLslWebSocketBridge.js'
18
20
  import FakeWebSocket from '../testDoubles/WebSockets/FakeWebSocket.js'
19
21
  import FakeWebSocketServer from '../testDoubles/WebSockets/FakeWebSocketServer.js'
20
-
21
22
  import LslWebSocketBridge from '../impl/LslWebSocketBridge.js'
22
23
  import BleDeviceController from '../impl/controllers/BleDeviceController.js'
23
24
  import LslEventMarkerEmitter from '../impl/LslEventMarkerEmitter.js'
@@ -32,8 +33,31 @@ export default class AbstractPackageTest extends AbstractModuleTest {
32
33
  protected static fakeLiblsl: FakeLiblsl
33
34
  protected static fakeLibndx: FakeLibndx
34
35
 
36
+ protected static readonly fakeStreamInfo = new FakeStreamInfo()
37
+
38
+ protected static readonly name_ = this.generateId()
39
+ protected static readonly type = this.generateId()
40
+ protected static readonly sourceId = this.generateId()
41
+ protected static readonly units = this.generateId()
42
+
43
+ protected static readonly channelNames = [
44
+ this.generateId(),
45
+ this.generateId(),
46
+ this.generateId(),
47
+ ]
48
+
49
+ protected static readonly channelCount = this.channelNames.length
50
+
51
+ protected static readonly chunkSize = randomInt(2, 100)
52
+ protected static readonly sampleRateHz = Math.floor(Math.random() * 100)
53
+ protected static readonly maxBufferedMs = Math.floor(Math.random() * 1000)
54
+
35
55
  protected static async beforeEach() {
36
56
  await super.beforeEach()
57
+
58
+ this.setImmediateTimeouts()
59
+
60
+ this.setFakeLibndx()
37
61
  }
38
62
 
39
63
  protected static setFakeLiblsl() {
@@ -44,6 +68,39 @@ export default class AbstractPackageTest extends AbstractModuleTest {
44
68
  FakeLiblsl.fakeInfoHandles = [{} as InfoHandle]
45
69
  }
46
70
 
71
+ protected static callsToSetTimeout: number[] = []
72
+
73
+ protected static setImmediateTimeouts() {
74
+ this.callsToSetTimeout = []
75
+
76
+ BleDeviceController.setTimeout = ((
77
+ callback: (...args: unknown[]) => void,
78
+ delayMs?: number,
79
+ ...args: unknown[]
80
+ ) => {
81
+ this.callsToSetTimeout.push(delayMs ?? 0)
82
+ return setTimeout(callback, 0, ...args)
83
+ }) as unknown as typeof setTimeout
84
+
85
+ LslStreamOutlet.setTimeout = ((
86
+ callback: (...args: unknown[]) => void,
87
+ delayMs?: number,
88
+ ...args: unknown[]
89
+ ) => {
90
+ this.callsToSetTimeout.push(delayMs ?? 0)
91
+ return setTimeout(callback, 0, ...args)
92
+ }) as unknown as typeof setTimeout
93
+
94
+ LslStreamInlet.setTimeout = ((
95
+ callback: (...args: unknown[]) => void,
96
+ delayMs?: number,
97
+ ...args: unknown[]
98
+ ) => {
99
+ this.callsToSetTimeout.push(delayMs ?? 0)
100
+ return setTimeout(callback, 0, ...args)
101
+ }) as unknown as typeof setTimeout
102
+ }
103
+
47
104
  protected static setFakeLibndx() {
48
105
  this.fakeLibndx = new FakeLibndx()
49
106
  LibndxAdapter.setInstance(this.fakeLibndx)
@@ -96,25 +153,6 @@ export default class AbstractPackageTest extends AbstractModuleTest {
96
153
  FakeWebSocketServer.resetTestDouble()
97
154
  }
98
155
 
99
- protected static readonly fakeStreamInfo = new FakeStreamInfo()
100
-
101
- protected static readonly name_ = this.generateId()
102
- protected static readonly type = this.generateId()
103
- protected static readonly sourceId = this.generateId()
104
- protected static readonly units = this.generateId()
105
-
106
- protected static readonly channelNames = [
107
- this.generateId(),
108
- this.generateId(),
109
- this.generateId(),
110
- ]
111
-
112
- protected static readonly channelCount = this.channelNames.length
113
-
114
- protected static readonly chunkSize = 2
115
- protected static readonly sampleRateHz = Math.floor(Math.random() * 100)
116
- protected static readonly maxBufferedMs = Math.floor(Math.random() * 1000)
117
-
118
156
  protected static async LslStreamInlet(
119
157
  options: Partial<StreamInletOptions>,
120
158
  onData: OnDataCallback
@@ -35,6 +35,14 @@ export default class BleDeviceControllerTest extends AbstractPackageTest {
35
35
  },
36
36
  ]
37
37
 
38
+ private static readonly extraCharCallbacks = [
39
+ {
40
+ charUuid: this.generateId(),
41
+ charName: this.generateId(),
42
+ onData: async () => {},
43
+ },
44
+ ]
45
+
38
46
  private static onConnected = (_peripheral: NativePeripheral) => {
39
47
  this.wasConnected = true
40
48
  }
@@ -58,8 +66,6 @@ export default class BleDeviceControllerTest extends AbstractPackageTest {
58
66
  await super.beforeEach()
59
67
 
60
68
  BleDeviceController.waitAfterMs = 0
61
-
62
- this.setFakeLibndx()
63
69
  BleDeviceController.Class = SpyBleController
64
70
 
65
71
  this.wasConnected = false
@@ -262,13 +268,10 @@ export default class BleDeviceControllerTest extends AbstractPackageTest {
262
268
  const waitAfterMs = 20
263
269
  BleDeviceController.waitAfterMs = waitAfterMs
264
270
 
265
- const t0 = Date.now()
266
271
  await this.connect()
267
- const t1 = Date.now()
268
272
 
269
- assert.isAbove(
270
- t1 - t0,
271
- 100 + waitAfterMs * 0.8,
273
+ assert.isTruthy(
274
+ this.callsToSetTimeout.includes(waitAfterMs),
272
275
  'Did not wait after on connected!'
273
276
  )
274
277
  }
@@ -310,6 +313,42 @@ export default class BleDeviceControllerTest extends AbstractPackageTest {
310
313
  )
311
314
  }
312
315
 
316
+ @test()
317
+ protected static async subscribeCharacteristicsCallsLibndxBinding() {
318
+ await this.subscribeCharacteristics()
319
+
320
+ assert.isEqualDeep(
321
+ FakeLibndx.callsToAddBleCharCallbacks[0],
322
+ {
323
+ deviceUuid: this.uuid,
324
+ charCallbacks: this.extraCharCallbacks,
325
+ },
326
+ 'Did not call addBleCharCallbacks as expected!'
327
+ )
328
+ }
329
+
330
+ @test()
331
+ protected static async subscribeCharacteristicsMergesIntoCharCallbacks() {
332
+ await this.subscribeCharacteristics()
333
+
334
+ assert.isEqualDeep(
335
+ this.instance.getCharacteristicCallbacks(),
336
+ [...this.charCallbacks, ...this.extraCharCallbacks],
337
+ 'Did not merge the newly subscribed callbacks into charCallbacks!'
338
+ )
339
+ }
340
+
341
+ @test()
342
+ protected static async subscribeCharacteristicsThrowsOn400() {
343
+ this.setFake400Error()
344
+
345
+ await assert.doesThrowAsync(
346
+ async () => await this.subscribeCharacteristics(),
347
+ this.fake400Error,
348
+ 'Did not throw error!'
349
+ )
350
+ }
351
+
313
352
  @test()
314
353
  protected static async callsSetBleRssiInterval() {
315
354
  await this.connect()
@@ -431,7 +470,7 @@ export default class BleDeviceControllerTest extends AbstractPackageTest {
431
470
  if (getCall()) {
432
471
  resolve()
433
472
  } else {
434
- setTimeout(check, 10)
473
+ setTimeout(check, 0)
435
474
  }
436
475
  }
437
476
  check()
@@ -445,6 +484,10 @@ export default class BleDeviceControllerTest extends AbstractPackageTest {
445
484
  )
446
485
  }
447
486
 
487
+ private static async subscribeCharacteristics() {
488
+ await this.instance.subscribeCharacteristics(this.extraCharCallbacks)
489
+ }
490
+
448
491
  private static async disconnect() {
449
492
  await this.instance.disconnect()
450
493
  }
@@ -265,11 +265,12 @@ export default class LslStreamOutletTest extends AbstractPackageTest {
265
265
 
266
266
  @test()
267
267
  protected static async waitsForTenMsAfterConstructionBeforeReturning() {
268
- const startMs = Date.now()
269
- await this.LslStreamOutlet({ waitAfterConstructionMs: 10 })
270
- const endMs = Date.now()
268
+ await this.LslStreamOutlet()
271
269
 
272
- assert.isAbove(endMs - startMs, 8)
270
+ assert.isTruthy(
271
+ this.callsToSetTimeout.includes(10),
272
+ 'Did not wait for 10ms after construction!'
273
+ )
273
274
  }
274
275
 
275
276
  @test()
@@ -0,0 +1,109 @@
1
+ import { test, assert } from '@neurodevs/node-tdd'
2
+
3
+ import UsbDeviceController, {
4
+ UsbController,
5
+ } from '../../impl/controllers/UsbDeviceController.js'
6
+ import AbstractPackageTest from '../AbstractPackageTest.js'
7
+ import { FakeLibndx } from '@neurodevs/ndx-native'
8
+
9
+ export default class UsbDeviceControllerTest extends AbstractPackageTest {
10
+ private static instance: UsbController
11
+
12
+ private static readonly serialNumber = this.generateId()
13
+ private static readonly valueToWrite = this.generateId()
14
+
15
+ private static readonly callsToOnData: {
16
+ data: Buffer
17
+ length: number
18
+ timestampSec: number
19
+ }[] = []
20
+
21
+ private static readonly onData = (
22
+ data: Buffer,
23
+ length: number,
24
+ timestampSec: number
25
+ ) => {
26
+ this.callsToOnData.push({ data, length, timestampSec })
27
+ }
28
+
29
+ protected static async beforeEach() {
30
+ await super.beforeEach()
31
+
32
+ this.instance = this.UsbDeviceController()
33
+ }
34
+
35
+ @test()
36
+ protected static async createsInstance() {
37
+ assert.isTruthy(this.instance, 'Failed to create instance!')
38
+ }
39
+
40
+ @test()
41
+ protected static async connectCallsLibndxCreateUsbBackend() {
42
+ await this.connect()
43
+
44
+ assert.isEqualDeep(
45
+ FakeLibndx.callsToCreateUsbBackend[0],
46
+ {
47
+ serialNumber: this.serialNumber,
48
+ },
49
+ 'Did not call create_usb_backend!'
50
+ )
51
+ }
52
+
53
+ @test()
54
+ protected static async connectCallsLibndxStartUsbBackend() {
55
+ await this.connect()
56
+
57
+ assert.isEqualDeep(
58
+ FakeLibndx.callsToStartUsbBackend[0],
59
+ {
60
+ serialNumber: this.serialNumber,
61
+ onData: this.onData,
62
+ },
63
+ 'Did not call start_usb_backend!'
64
+ )
65
+ }
66
+
67
+ @test()
68
+ protected static async disconnectCallsLibndxStopUsbBackend() {
69
+ await this.connect()
70
+ await this.disconnect()
71
+
72
+ assert.isEqualDeep(
73
+ FakeLibndx.callsToStopUsbBackend[0],
74
+ {
75
+ serialNumber: this.serialNumber,
76
+ },
77
+ 'Did not call stop_usb_backend!'
78
+ )
79
+ }
80
+
81
+ @test()
82
+ protected static async writeUsbCallsLibndxWriteUsbBackend() {
83
+ await this.instance.writeUsb(this.valueToWrite)
84
+
85
+ assert.isEqualDeep(
86
+ FakeLibndx.callsToWriteUsbBackend[0],
87
+ {
88
+ serialNumber: this.serialNumber,
89
+ value: this.valueToWrite,
90
+ },
91
+ 'Did not call write_usb_backend!'
92
+ )
93
+ }
94
+
95
+ private static async connect() {
96
+ await this.instance.connect()
97
+ }
98
+
99
+ private static async disconnect() {
100
+ await this.instance.disconnect()
101
+ }
102
+
103
+ private static UsbDeviceController() {
104
+ return UsbDeviceController.Create({
105
+ onData: this.onData,
106
+ serialNumber: this.serialNumber,
107
+ })
108
+ }
109
+ }