@neurodevs/node-lsl 17.1.1 → 18.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 (178) hide show
  1. package/.claude/settings.local.json +10 -0
  2. package/.regressionproof.json +7 -0
  3. package/.vscode/launch.json +3 -2
  4. package/README.md +9 -35
  5. package/build/.spruce/settings.json +5 -1
  6. package/build/__tests__/AbstractPackageTest.d.ts +4 -4
  7. package/build/__tests__/AbstractPackageTest.js +9 -11
  8. package/build/__tests__/AbstractPackageTest.js.map +1 -1
  9. package/build/__tests__/impl/LslBackpressureMonitor.test.d.ts +7 -0
  10. package/build/__tests__/impl/LslBackpressureMonitor.test.js +26 -0
  11. package/build/__tests__/impl/LslBackpressureMonitor.test.js.map +1 -0
  12. package/build/__tests__/impl/LslEventMarkerEmitter.test.d.ts +34 -0
  13. package/build/__tests__/impl/LslEventMarkerEmitter.test.js +243 -0
  14. package/build/__tests__/impl/LslEventMarkerEmitter.test.js.map +1 -0
  15. package/build/__tests__/impl/LslStreamInfo.test.d.ts +0 -3
  16. package/build/__tests__/impl/LslStreamInfo.test.js +2 -27
  17. package/build/__tests__/impl/LslStreamInfo.test.js.map +1 -1
  18. package/build/__tests__/impl/LslStreamInlet.test.d.ts +20 -8
  19. package/build/__tests__/impl/LslStreamInlet.test.js +224 -69
  20. package/build/__tests__/impl/LslStreamInlet.test.js.map +1 -1
  21. package/build/__tests__/impl/LslStreamOutlet.test.d.ts +3 -7
  22. package/build/__tests__/impl/LslStreamOutlet.test.js +36 -46
  23. package/build/__tests__/impl/LslStreamOutlet.test.js.map +1 -1
  24. package/build/__tests__/impl/LslWebSocketBridge.test.js +16 -17
  25. package/build/__tests__/impl/LslWebSocketBridge.test.js.map +1 -1
  26. package/build/assertions.d.ts +1 -1
  27. package/build/assertions.js.map +1 -1
  28. package/build/impl/LslBackpressureMonitor.d.ts +8 -0
  29. package/build/impl/LslBackpressureMonitor.js +8 -0
  30. package/build/impl/LslBackpressureMonitor.js.map +1 -0
  31. package/build/impl/LslEventMarkerEmitter.d.ts +35 -0
  32. package/build/impl/LslEventMarkerEmitter.js +86 -0
  33. package/build/impl/LslEventMarkerEmitter.js.map +1 -0
  34. package/build/impl/LslStreamInfo.d.ts +4 -8
  35. package/build/impl/LslStreamInfo.js +8 -21
  36. package/build/impl/LslStreamInfo.js.map +1 -1
  37. package/build/impl/LslStreamInlet.d.ts +31 -50
  38. package/build/impl/LslStreamInlet.js +79 -149
  39. package/build/impl/LslStreamInlet.js.map +1 -1
  40. package/build/impl/LslStreamOutlet.d.ts +15 -18
  41. package/build/impl/LslStreamOutlet.js +39 -47
  42. package/build/impl/LslStreamOutlet.js.map +1 -1
  43. package/build/impl/LslWebSocketBridge.d.ts +4 -5
  44. package/build/impl/LslWebSocketBridge.js +8 -8
  45. package/build/impl/LslWebSocketBridge.js.map +1 -1
  46. package/build/impl/workers/inlet/LslStreamInlet.worker.d.ts +22 -0
  47. package/build/impl/workers/inlet/LslStreamInlet.worker.js +42 -0
  48. package/build/impl/workers/inlet/LslStreamInlet.worker.js.map +1 -0
  49. package/build/impl/workers/inlet/StreamInletWorker.d.ts +73 -0
  50. package/build/impl/workers/inlet/StreamInletWorker.js +253 -0
  51. package/build/impl/workers/inlet/StreamInletWorker.js.map +1 -0
  52. package/build/impl/workers/outlet/LslStreamOutlet.worker.d.ts +32 -0
  53. package/build/impl/workers/outlet/LslStreamOutlet.worker.js +82 -0
  54. package/build/impl/workers/outlet/LslStreamOutlet.worker.js.map +1 -0
  55. package/build/index.d.ts +12 -14
  56. package/build/index.js +14 -16
  57. package/build/index.js.map +1 -1
  58. package/build/scripts/finalizeHandles.d.ts +2 -0
  59. package/build/scripts/finalizeHandles.js +48 -0
  60. package/build/scripts/finalizeHandles.js.map +1 -0
  61. package/build/scripts/runLslEventMarkerEmitter.js +11 -0
  62. package/build/scripts/runLslEventMarkerEmitter.js.map +1 -0
  63. package/build/scripts/runOutletToInlet.js +7 -6
  64. package/build/scripts/runOutletToInlet.js.map +1 -1
  65. package/build/scripts/testDestroyOutlet.d.ts +1 -0
  66. package/build/scripts/testDestroyOutlet.js +4 -0
  67. package/build/scripts/testDestroyOutlet.js.map +1 -0
  68. package/build/testDoubles/BackpressureMonitor/FakeBackpressureMonitor.d.ts +6 -0
  69. package/build/testDoubles/BackpressureMonitor/FakeBackpressureMonitor.js +10 -0
  70. package/build/testDoubles/BackpressureMonitor/FakeBackpressureMonitor.js.map +1 -0
  71. package/build/testDoubles/EventMarkerEmitter/FakeEventMarkerEmitter.d.ts +17 -0
  72. package/build/testDoubles/EventMarkerEmitter/FakeEventMarkerEmitter.js +30 -0
  73. package/build/testDoubles/EventMarkerEmitter/FakeEventMarkerEmitter.js.map +1 -0
  74. package/build/testDoubles/EventMarkerEmitter/SpyEventMarkerEmitter.d.ts +10 -0
  75. package/build/testDoubles/EventMarkerEmitter/SpyEventMarkerEmitter.js +23 -0
  76. package/build/testDoubles/EventMarkerEmitter/SpyEventMarkerEmitter.js.map +1 -0
  77. package/build/testDoubles/EventMarkerEmitter/ThrowingEventMarkerEmitter.d.ts +9 -0
  78. package/build/testDoubles/EventMarkerEmitter/ThrowingEventMarkerEmitter.js +19 -0
  79. package/build/testDoubles/EventMarkerEmitter/ThrowingEventMarkerEmitter.js.map +1 -0
  80. package/build/testDoubles/StreamInfo/FakeStreamInfo.d.ts +3 -3
  81. package/build/testDoubles/StreamInfo/FakeStreamInfo.js +3 -3
  82. package/build/testDoubles/StreamInfo/FakeStreamInfo.js.map +1 -1
  83. package/build/testDoubles/StreamInlet/FakeStreamInlet.d.ts +8 -10
  84. package/build/testDoubles/StreamInlet/FakeStreamInlet.js +6 -7
  85. package/build/testDoubles/StreamInlet/FakeStreamInlet.js.map +1 -1
  86. package/build/testDoubles/StreamInlet/SpyStreamInlet.d.ts +2 -5
  87. package/build/testDoubles/StreamInlet/SpyStreamInlet.js +2 -8
  88. package/build/testDoubles/StreamInlet/SpyStreamInlet.js.map +1 -1
  89. package/build/testDoubles/StreamOutlet/FakeStreamOutlet.d.ts +7 -9
  90. package/build/testDoubles/StreamOutlet/FakeStreamOutlet.js +5 -8
  91. package/build/testDoubles/StreamOutlet/FakeStreamOutlet.js.map +1 -1
  92. package/build/testDoubles/WebSocketBridge/FakeWebSocketBridge.d.ts +1 -1
  93. package/build/testDoubles/WebSocketBridge/FakeWebSocketBridge.js +1 -1
  94. package/build/testDoubles/WebSocketBridge/FakeWebSocketBridge.js.map +1 -1
  95. package/build/testDoubles/WorkerThreads/FakeWorker.d.ts +27 -0
  96. package/build/testDoubles/WorkerThreads/FakeWorker.js +67 -0
  97. package/build/testDoubles/WorkerThreads/FakeWorker.js.map +1 -0
  98. package/build/validations.js +0 -2
  99. package/build/validations.js.map +1 -1
  100. package/package.json +23 -7
  101. package/src/.spruce/settings.json +5 -1
  102. package/src/__tests__/AbstractPackageTest.ts +12 -14
  103. package/src/__tests__/impl/LslBackpressureMonitor.test.ts +25 -0
  104. package/src/__tests__/impl/LslEventMarkerEmitter.test.ts +322 -0
  105. package/src/__tests__/impl/LslStreamInfo.test.ts +3 -40
  106. package/src/__tests__/impl/LslStreamInlet.test.ts +344 -97
  107. package/src/__tests__/impl/LslStreamOutlet.test.ts +61 -69
  108. package/src/__tests__/impl/LslWebSocketBridge.test.ts +18 -18
  109. package/src/assertions.ts +2 -1
  110. package/src/impl/LslBackpressureMonitor.ts +13 -0
  111. package/src/impl/LslEventMarkerEmitter.ts +133 -0
  112. package/src/impl/LslStreamInfo.ts +17 -29
  113. package/src/impl/LslStreamInlet.ts +102 -215
  114. package/src/impl/LslStreamOutlet.ts +54 -78
  115. package/src/impl/LslWebSocketBridge.ts +12 -12
  116. package/src/impl/workers/inlet/LslStreamInlet.worker.ts +74 -0
  117. package/src/impl/workers/inlet/StreamInletWorker.ts +348 -0
  118. package/src/impl/workers/outlet/LslStreamOutlet.worker.ts +144 -0
  119. package/src/index.ts +14 -17
  120. package/src/scripts/finalizeHandles.ts +63 -0
  121. package/src/scripts/runLslEventMarkerEmitter.ts +15 -0
  122. package/src/scripts/runOutletToInlet.ts +10 -8
  123. package/src/scripts/testDestroyOutlet.ts +5 -0
  124. package/src/testDoubles/BackpressureMonitor/FakeBackpressureMonitor.ts +13 -0
  125. package/src/testDoubles/EventMarkerEmitter/FakeEventMarkerEmitter.ts +46 -0
  126. package/src/testDoubles/EventMarkerEmitter/SpyEventMarkerEmitter.ts +31 -0
  127. package/src/testDoubles/EventMarkerEmitter/ThrowingEventMarkerEmitter.ts +29 -0
  128. package/src/testDoubles/StreamInfo/FakeStreamInfo.ts +4 -4
  129. package/src/testDoubles/StreamInlet/FakeStreamInlet.ts +11 -17
  130. package/src/testDoubles/StreamInlet/SpyStreamInlet.ts +3 -16
  131. package/src/testDoubles/StreamOutlet/FakeStreamOutlet.ts +12 -15
  132. package/src/testDoubles/WebSocketBridge/FakeWebSocketBridge.ts +1 -1
  133. package/src/testDoubles/WorkerThreads/FakeWorker.ts +99 -0
  134. package/src/validations.ts +0 -2
  135. package/build/__tests__/impl/LiblslAdapter.test.d.ts +0 -79
  136. package/build/__tests__/impl/LiblslAdapter.test.js +0 -688
  137. package/build/__tests__/impl/LiblslAdapter.test.js.map +0 -1
  138. package/build/__tests__/impl/LslEventMarkerOutlet.test.d.ts +0 -21
  139. package/build/__tests__/impl/LslEventMarkerOutlet.test.js +0 -160
  140. package/build/__tests__/impl/LslEventMarkerOutlet.test.js.map +0 -1
  141. package/build/handleError.d.ts +0 -8
  142. package/build/handleError.js +0 -25
  143. package/build/handleError.js.map +0 -1
  144. package/build/impl/LiblslAdapter.d.ts +0 -154
  145. package/build/impl/LiblslAdapter.js +0 -317
  146. package/build/impl/LiblslAdapter.js.map +0 -1
  147. package/build/impl/LslEventMarkerOutlet.d.ts +0 -28
  148. package/build/impl/LslEventMarkerOutlet.js +0 -63
  149. package/build/impl/LslEventMarkerOutlet.js.map +0 -1
  150. package/build/scripts/runLslEventMarkerOutlet.js +0 -18
  151. package/build/scripts/runLslEventMarkerOutlet.js.map +0 -1
  152. package/build/testDoubles/EventMarkerOutlet/FakeEventMarkerOutlet.d.ts +0 -13
  153. package/build/testDoubles/EventMarkerOutlet/FakeEventMarkerOutlet.js +0 -26
  154. package/build/testDoubles/EventMarkerOutlet/FakeEventMarkerOutlet.js.map +0 -1
  155. package/build/testDoubles/EventMarkerOutlet/MockEventMarkerOutlet.d.ts +0 -17
  156. package/build/testDoubles/EventMarkerOutlet/MockEventMarkerOutlet.js +0 -46
  157. package/build/testDoubles/EventMarkerOutlet/MockEventMarkerOutlet.js.map +0 -1
  158. package/build/testDoubles/EventMarkerOutlet/SpyEventMarkerOutlet.d.ts +0 -9
  159. package/build/testDoubles/EventMarkerOutlet/SpyEventMarkerOutlet.js +0 -19
  160. package/build/testDoubles/EventMarkerOutlet/SpyEventMarkerOutlet.js.map +0 -1
  161. package/build/testDoubles/EventMarkerOutlet/ThrowingEventMarkerOutlet.d.ts +0 -9
  162. package/build/testDoubles/EventMarkerOutlet/ThrowingEventMarkerOutlet.js +0 -19
  163. package/build/testDoubles/EventMarkerOutlet/ThrowingEventMarkerOutlet.js.map +0 -1
  164. package/build/testDoubles/Liblsl/FakeLiblsl.d.ts +0 -50
  165. package/build/testDoubles/Liblsl/FakeLiblsl.js +0 -126
  166. package/build/testDoubles/Liblsl/FakeLiblsl.js.map +0 -1
  167. package/src/__tests__/impl/LiblslAdapter.test.ts +0 -817
  168. package/src/__tests__/impl/LslEventMarkerOutlet.test.ts +0 -195
  169. package/src/handleError.ts +0 -24
  170. package/src/impl/LiblslAdapter.ts +0 -543
  171. package/src/impl/LslEventMarkerOutlet.ts +0 -97
  172. package/src/scripts/runLslEventMarkerOutlet.ts +0 -23
  173. package/src/testDoubles/EventMarkerOutlet/FakeEventMarkerOutlet.ts +0 -36
  174. package/src/testDoubles/EventMarkerOutlet/MockEventMarkerOutlet.ts +0 -75
  175. package/src/testDoubles/EventMarkerOutlet/SpyEventMarkerOutlet.ts +0 -24
  176. package/src/testDoubles/EventMarkerOutlet/ThrowingEventMarkerOutlet.ts +0 -28
  177. package/src/testDoubles/Liblsl/FakeLiblsl.ts +0 -182
  178. /package/build/scripts/{runLslEventMarkerOutlet.d.ts → runLslEventMarkerEmitter.d.ts} +0 -0
@@ -9,7 +9,7 @@ export default class FakeWebSocketBridge {
9
9
  constructor(options) {
10
10
  FakeWebSocketBridge.callsToConstructor.push(options);
11
11
  }
12
- activate() {
12
+ async activate() {
13
13
  FakeWebSocketBridge.numCallsToActivate++;
14
14
  }
15
15
  deactivate() {
@@ -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,QAAQ;QACX,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,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"}
@@ -0,0 +1,27 @@
1
+ import { WorkerOptions } from 'node:worker_threads';
2
+ import { OnDataCallback } from '../../impl/LslStreamInlet.js';
3
+ import StreamInletWorker from '../../impl/workers/inlet/StreamInletWorker.js';
4
+ export default class FakeWorker {
5
+ static callsToConstructor: {
6
+ filename: string | URL;
7
+ options?: WorkerOptions;
8
+ }[];
9
+ static callsToPostMessage: WorkerMessage[];
10
+ static callsToOn: {
11
+ type: string;
12
+ listener: (...args: unknown[]) => void;
13
+ }[];
14
+ static inletWorker: StreamInletWorker;
15
+ static fakeOnData: OnDataCallback;
16
+ createInletPromise?: Promise<void>;
17
+ constructor(filename: string | URL, options?: WorkerOptions);
18
+ postMessage(msg: WorkerMessage): void;
19
+ on(type: string, listener: (...args: unknown[]) => void): void;
20
+ private get inletWorker();
21
+ private get fakeOnData();
22
+ static resetTestDoubles(): void;
23
+ }
24
+ export interface WorkerMessage {
25
+ type: string;
26
+ payload?: Record<string, unknown>[];
27
+ }
@@ -0,0 +1,67 @@
1
+ import StreamInletWorker from '../../impl/workers/inlet/StreamInletWorker.js';
2
+ import { createOutlet, destroyOutlet, pushSample, } from '../../impl/workers/outlet/LslStreamOutlet.worker.js';
3
+ export default class FakeWorker {
4
+ static callsToConstructor = [];
5
+ static callsToPostMessage = [];
6
+ static callsToOn = [];
7
+ static inletWorker = new StreamInletWorker();
8
+ static fakeOnData;
9
+ createInletPromise;
10
+ constructor(filename, options) {
11
+ FakeWorker.callsToConstructor.push({ filename, options });
12
+ }
13
+ postMessage(msg) {
14
+ FakeWorker.callsToPostMessage.push(msg);
15
+ const { type } = msg;
16
+ switch (type) {
17
+ case 'createOutlet': {
18
+ createOutlet(msg);
19
+ break;
20
+ }
21
+ case 'pushSample': {
22
+ pushSample(msg);
23
+ break;
24
+ }
25
+ case 'destroyOutlet': {
26
+ destroyOutlet();
27
+ break;
28
+ }
29
+ case 'createInlet': {
30
+ const { payload } = msg;
31
+ this.createInletPromise = this.inletWorker.createInlet(payload);
32
+ break;
33
+ }
34
+ case 'startPulling': {
35
+ this.inletWorker.startPulling(this.fakeOnData);
36
+ break;
37
+ }
38
+ case 'flushInlet': {
39
+ this.inletWorker.flushInlet();
40
+ break;
41
+ }
42
+ case 'stopPulling': {
43
+ this.inletWorker.stopPulling();
44
+ break;
45
+ }
46
+ case 'destroyInlet': {
47
+ this.inletWorker.destroyInlet();
48
+ break;
49
+ }
50
+ }
51
+ }
52
+ on(type, listener) {
53
+ FakeWorker.callsToOn.push({ type, listener });
54
+ }
55
+ get inletWorker() {
56
+ return FakeWorker.inletWorker;
57
+ }
58
+ get fakeOnData() {
59
+ return FakeWorker.fakeOnData;
60
+ }
61
+ static resetTestDoubles() {
62
+ this.callsToConstructor = [];
63
+ this.callsToPostMessage = [];
64
+ this.callsToOn = [];
65
+ }
66
+ }
67
+ //# sourceMappingURL=FakeWorker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FakeWorker.js","sourceRoot":"","sources":["../../../src/testDoubles/WorkerThreads/FakeWorker.ts"],"names":[],"mappings":"AAGA,OAAO,iBAAiB,MAAM,+CAA+C,CAAA;AAC7E,OAAO,EACH,YAAY,EACZ,aAAa,EACb,UAAU,GACb,MAAM,qDAAqD,CAAA;AAE5D,MAAM,CAAC,OAAO,OAAO,UAAU;IACpB,MAAM,CAAC,kBAAkB,GAG1B,EAAE,CAAA;IAED,MAAM,CAAC,kBAAkB,GAAoB,EAAE,CAAA;IAE/C,MAAM,CAAC,SAAS,GAGjB,EAAE,CAAA;IAED,MAAM,CAAC,WAAW,GAAG,IAAI,iBAAiB,EAAE,CAAA;IAC5C,MAAM,CAAC,UAAU,CAAgB;IAEjC,kBAAkB,CAAgB;IAEzC,YAAmB,QAAsB,EAAE,OAAuB;QAC9D,UAAU,CAAC,kBAAkB,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAA;IAC7D,CAAC;IAEM,WAAW,CAAC,GAAkB;QACjC,UAAU,CAAC,kBAAkB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;QAEvC,MAAM,EAAE,IAAI,EAAE,GAAG,GAAG,CAAA;QAEpB,QAAQ,IAAI,EAAE,CAAC;YACX,KAAK,cAAc,CAAC,CAAC,CAAC;gBAClB,YAAY,CAAC,GAAU,CAAC,CAAA;gBACxB,MAAK;YACT,CAAC;YACD,KAAK,YAAY,CAAC,CAAC,CAAC;gBAChB,UAAU,CAAC,GAAU,CAAC,CAAA;gBACtB,MAAK;YACT,CAAC;YACD,KAAK,eAAe,CAAC,CAAC,CAAC;gBACnB,aAAa,EAAE,CAAA;gBACf,MAAK;YACT,CAAC;YACD,KAAK,aAAa,CAAC,CAAC,CAAC;gBACjB,MAAM,EAAE,OAAO,EAAE,GAAG,GAAG,CAAA;gBACvB,IAAI,CAAC,kBAAkB,GAAG,IAAI,CAAC,WAAW,CAAC,WAAW,CAClD,OAAc,CACjB,CAAA;gBACD,MAAK;YACT,CAAC;YACD,KAAK,cAAc,CAAC,CAAC,CAAC;gBAClB,IAAI,CAAC,WAAW,CAAC,YAAY,CAAC,IAAI,CAAC,UAAU,CAAC,CAAA;gBAC9C,MAAK;YACT,CAAC;YACD,KAAK,YAAY,CAAC,CAAC,CAAC;gBAChB,IAAI,CAAC,WAAW,CAAC,UAAU,EAAE,CAAA;gBAC7B,MAAK;YACT,CAAC;YACD,KAAK,aAAa,CAAC,CAAC,CAAC;gBACjB,IAAI,CAAC,WAAW,CAAC,WAAW,EAAE,CAAA;gBAC9B,MAAK;YACT,CAAC;YACD,KAAK,cAAc,CAAC,CAAC,CAAC;gBAClB,IAAI,CAAC,WAAW,CAAC,YAAY,EAAE,CAAA;gBAC/B,MAAK;YACT,CAAC;QACL,CAAC;IACL,CAAC;IAEM,EAAE,CAAC,IAAY,EAAE,QAAsC;QAC1D,UAAU,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAA;IACjD,CAAC;IAED,IAAY,WAAW;QACnB,OAAO,UAAU,CAAC,WAAW,CAAA;IACjC,CAAC;IAED,IAAY,UAAU;QAClB,OAAO,UAAU,CAAC,UAAU,CAAA;IAChC,CAAC;IAEM,MAAM,CAAC,gBAAgB;QAC1B,IAAI,CAAC,kBAAkB,GAAG,EAAE,CAAA;QAC5B,IAAI,CAAC,kBAAkB,GAAG,EAAE,CAAA;QAC5B,IAAI,CAAC,SAAS,GAAG,EAAE,CAAA;IACvB,CAAC"}
@@ -5,11 +5,9 @@ export function isGreaterThanOrEqualToZero(value) {
5
5
  return value >= 0;
6
6
  }
7
7
  export function isPositiveInteger(value) {
8
- //@ts-ignore
9
8
  return Number.isInteger(value) && value > 0;
10
9
  }
11
10
  export function isPositiveIntegerOrZero(value) {
12
- //@ts-ignore
13
11
  return Number.isInteger(value) && value >= 0;
14
12
  }
15
13
  //# sourceMappingURL=validations.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"validations.js","sourceRoot":"","sources":["../src/validations.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,eAAe,CAAC,KAAa,EAAE,KAAwB;IACnE,OAAO,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAA;AACtC,CAAC;AAED,MAAM,UAAU,0BAA0B,CAAC,KAAa;IACpD,OAAO,KAAK,IAAI,CAAC,CAAA;AACrB,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,KAAa;IAC3C,YAAY;IACZ,OAAO,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,CAAA;AAC/C,CAAC;AAED,MAAM,UAAU,uBAAuB,CAAC,KAAa;IACjD,YAAY;IACZ,OAAO,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC,CAAA;AAChD,CAAC"}
1
+ {"version":3,"file":"validations.js","sourceRoot":"","sources":["../src/validations.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,eAAe,CAAC,KAAa,EAAE,KAAwB;IACnE,OAAO,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAA;AACtC,CAAC;AAED,MAAM,UAAU,0BAA0B,CAAC,KAAa;IACpD,OAAO,KAAK,IAAI,CAAC,CAAA;AACrB,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,KAAa;IAC3C,OAAO,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,CAAA;AAC/C,CAAC;AAED,MAAM,UAAU,uBAAuB,CAAC,KAAa;IACjD,OAAO,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC,CAAA;AAChD,CAAC"}
package/package.json CHANGED
@@ -1,12 +1,17 @@
1
1
  {
2
2
  "name": "@neurodevs/node-lsl",
3
- "version": "17.1.1",
3
+ "version": "18.0.0",
4
4
  "description": "Lab Streaming Layer (LSL) bindings for Node",
5
5
  "type": "module",
6
6
  "keywords": [
7
7
  "nodejs",
8
8
  "typescript",
9
- "tdd"
9
+ "tdd",
10
+ "lsl",
11
+ "lab streaming layer",
12
+ "neurotech",
13
+ "bci",
14
+ "brain-computer interface"
10
15
  ],
11
16
  "license": "MIT",
12
17
  "author": "Eric Yates <hello@ericthecurious.com>",
@@ -36,7 +41,7 @@
36
41
  "rebuild": "yarn run clean.all && yarn install && yarn run build.dev",
37
42
  "update.dependencies": "yarn run clean.dependencies && yarn",
38
43
  "resolve-paths.lint": "yarn run build.resolve-paths ; yarn run lint",
39
- "test": "jest",
44
+ "test": "NODE_OPTIONS=--experimental-vm-modules jest",
40
45
  "watch.build.dev": "tsc-watch --sourceMap --onCompilationComplete 'yarn run post.watch.build'",
41
46
  "watch.lint": "concurrently 'yarn lint' \"chokidar 'src/**/*' -c 'yarn lint.tsc'\"",
42
47
  "watch.rebuild": "yarn run clean.all && yarn install && yarn run watch.build.dev",
@@ -44,7 +49,8 @@
44
49
  "test.rs": "node build/test.js"
45
50
  },
46
51
  "dependencies": {
47
- "@neurodevs/generate-id": "^1.0.9",
52
+ "@neurodevs/generate-id": "^1.1.2",
53
+ "@neurodevs/ndx-native": "^0.2.0",
48
54
  "ffi-rs": "^1.3.1",
49
55
  "node-gyp": "^12.1.0",
50
56
  "ref-array-napi": "^1.2.2",
@@ -52,13 +58,15 @@
52
58
  "ws": "^8.18.3"
53
59
  },
54
60
  "devDependencies": {
55
- "@neurodevs/node-tdd": "^0.2.3",
61
+ "@neurodevs/node-tdd": "0.2.5",
62
+ "@regressionproof/cli": "^0.8.0",
63
+ "@regressionproof/jest-reporter": "^0.8.0",
56
64
  "@types/ffi-napi": "^4.0.10",
57
65
  "@types/node": "^25.0.2",
58
66
  "@types/ws": "^8.18.1",
59
67
  "chokidar-cli": "^3.0.0",
60
68
  "concurrently": "^9.2.1",
61
- "eslint": "^9.39.2",
69
+ "eslint": "8.57.0",
62
70
  "eslint-config-spruce": "^11.2.26",
63
71
  "jest": "^30.2.0",
64
72
  "jest-circus": "^30.2.0",
@@ -72,6 +80,10 @@
72
80
  "maxWorkers": 4,
73
81
  "testTimeout": 120000,
74
82
  "testEnvironment": "node",
83
+ "extensionsToTreatAsEsm": [
84
+ ".ts"
85
+ ],
86
+ "transform": {},
75
87
  "testPathIgnorePatterns": [
76
88
  "<rootDir>/tmp/",
77
89
  "<rootDir>/src/",
@@ -83,7 +95,11 @@
83
95
  ],
84
96
  "moduleNameMapper": {
85
97
  "^#spruce/(.*)$": "<rootDir>/build/.spruce/$1"
86
- }
98
+ },
99
+ "reporters": [
100
+ "default",
101
+ "@regressionproof/jest-reporter"
102
+ ]
87
103
  },
88
104
  "skill": {
89
105
  "namespace": "node-lsl",
@@ -7,5 +7,9 @@
7
7
  ],
8
8
  "installed": [
9
9
  "test"
10
- ]
10
+ ],
11
+ "regressionproof": {
12
+ "enabled": true,
13
+ "projectName": "node-lsl"
14
+ }
11
15
  }
@@ -1,8 +1,8 @@
1
+ import { FakeLiblsl, InfoHandle, LiblslAdapter } from '@neurodevs/ndx-native'
1
2
  import AbstractModuleTest from '@neurodevs/node-tdd'
2
3
  import WebSocket, { Server } from 'ws'
3
4
 
4
- import LiblslAdapter from '../impl/LiblslAdapter.js'
5
- import LslEventMarkerOutlet from '../impl/LslEventMarkerOutlet.js'
5
+ import LslEventMarkerEmitter from '../impl/LslEventMarkerEmitter.js'
6
6
  import LslStreamInfo from '../impl/LslStreamInfo.js'
7
7
  import LslStreamInlet, {
8
8
  OnDataCallback,
@@ -10,9 +10,7 @@ import LslStreamInlet, {
10
10
  } from '../impl/LslStreamInlet.js'
11
11
  import LslStreamOutlet from '../impl/LslStreamOutlet.js'
12
12
  import LslWebSocketBridge from '../impl/LslWebSocketBridge.js'
13
-
14
- import SpyEventMarkerOutlet from '../testDoubles/EventMarkerOutlet/SpyEventMarkerOutlet.js'
15
- import FakeLiblsl from '../testDoubles/Liblsl/FakeLiblsl.js'
13
+ import SpyEventMarkerEmitter from '../testDoubles/EventMarkerEmitter/SpyEventMarkerEmitter.js'
16
14
  import FakeStreamInfo from '../testDoubles/StreamInfo/FakeStreamInfo.js'
17
15
  import SpyStreamInfo from '../testDoubles/StreamInfo/SpyStreamInfo.js'
18
16
  import FakeStreamInlet from '../testDoubles/StreamInlet/FakeStreamInlet.js'
@@ -34,6 +32,7 @@ export default class AbstractPackageTest extends AbstractModuleTest {
34
32
  LiblslAdapter.setInstance(this.fakeLiblsl)
35
33
 
36
34
  FakeLiblsl.fakeErrorCode = 0
35
+ FakeLiblsl.fakeInfoHandles = [{} as InfoHandle]
37
36
  }
38
37
 
39
38
  protected static setSpyStreamInfo() {
@@ -60,8 +59,8 @@ export default class AbstractPackageTest extends AbstractModuleTest {
60
59
  FakeStreamOutlet.resetTestDouble()
61
60
  }
62
61
 
63
- protected static setSpyEventMarkerOutlet() {
64
- LslEventMarkerOutlet.Class = SpyEventMarkerOutlet
62
+ protected static setSpyEventMarkerEmitter() {
63
+ LslEventMarkerEmitter.Class = SpyEventMarkerEmitter
65
64
  }
66
65
 
67
66
  protected static setSpyLslWebSocketBridge() {
@@ -78,7 +77,8 @@ export default class AbstractPackageTest extends AbstractModuleTest {
78
77
  FakeWebSocketServer.resetTestDouble()
79
78
  }
80
79
 
81
- protected static readonly info = new FakeStreamInfo()
80
+ protected static readonly fakeStreamInfo = new FakeStreamInfo()
81
+
82
82
  protected static readonly name_ = this.generateId()
83
83
  protected static readonly type = this.generateId()
84
84
  protected static readonly sourceId = this.generateId()
@@ -90,9 +90,7 @@ export default class AbstractPackageTest extends AbstractModuleTest {
90
90
  this.generateId(),
91
91
  ]
92
92
 
93
- protected static get channelCount() {
94
- return this.channelNames.length
95
- }
93
+ protected static readonly channelCount = this.channelNames.length
96
94
 
97
95
  protected static readonly chunkSize = 2
98
96
  protected static readonly sampleRateHz = Math.floor(Math.random() * 100)
@@ -102,12 +100,12 @@ export default class AbstractPackageTest extends AbstractModuleTest {
102
100
  options: Partial<StreamInletOptions>,
103
101
  onData: OnDataCallback
104
102
  ) {
105
- const defaultOptions = {
106
- info: this.info,
103
+ const defaultOptions: StreamInletOptions = {
104
+ sourceId: this.sourceId,
107
105
  chunkSize: this.chunkSize,
108
106
  maxBufferedMs: this.maxBufferedMs,
109
107
  ...options,
110
- } as StreamInletOptions
108
+ }
111
109
 
112
110
  return LslStreamInlet.Create(defaultOptions, onData)
113
111
  }
@@ -0,0 +1,25 @@
1
+ import { test, assert } from '@neurodevs/node-tdd'
2
+
3
+ import LslBackpressureMonitor, {
4
+ BackpressureMonitor,
5
+ } from '../../impl/LslBackpressureMonitor.js'
6
+ import AbstractPackageTest from '../AbstractPackageTest.js'
7
+
8
+ export default class LslBackpressureMonitorTest extends AbstractPackageTest {
9
+ private static instance: BackpressureMonitor
10
+
11
+ protected static async beforeEach() {
12
+ await super.beforeEach()
13
+
14
+ this.instance = this.LslBackpressureMonitor()
15
+ }
16
+
17
+ @test()
18
+ protected static async createsInstance() {
19
+ assert.isTruthy(this.instance, 'Failed to create instance!')
20
+ }
21
+
22
+ private static LslBackpressureMonitor() {
23
+ return LslBackpressureMonitor.Create()
24
+ }
25
+ }
@@ -0,0 +1,322 @@
1
+ import { randomInt } from 'crypto'
2
+ import { assert, test } from '@neurodevs/node-tdd'
3
+
4
+ import LslEventMarkerEmitter, {
5
+ EventMarkerOptions,
6
+ } from '../../impl/LslEventMarkerEmitter.js'
7
+ import { StreamOutletOptions } from '../../impl/LslStreamOutlet.js'
8
+ import SpyEventMarkerEmitter from '../../testDoubles/EventMarkerEmitter/SpyEventMarkerEmitter.js'
9
+ import generateRandomOutletOptions from '../../testDoubles/generateRandomOutletOptions.js'
10
+ import FakeStreamOutlet from '../../testDoubles/StreamOutlet/FakeStreamOutlet.js'
11
+ import AbstractPackageTest from '../AbstractPackageTest.js'
12
+
13
+ export default class EventMarkerEmitterTest extends AbstractPackageTest {
14
+ private static instance: SpyEventMarkerEmitter
15
+
16
+ protected static async beforeEach() {
17
+ await super.beforeEach()
18
+
19
+ this.setFakeLiblsl()
20
+ this.setFakeStreamOutlet()
21
+ this.setSpyEventMarkerEmitter()
22
+
23
+ this.instance = await this.LslEventMarkerEmitter()
24
+ }
25
+
26
+ private static readonly markerName = this.generateId()
27
+
28
+ @test()
29
+ protected static async createsInstance() {
30
+ assert.isTruthy(this.instance, 'Failed to create instance!')
31
+ }
32
+
33
+ @test()
34
+ protected static async loadsWithEventMarkerSpecificOptions() {
35
+ assert.isEqualDeep(
36
+ {
37
+ ...FakeStreamOutlet.callsToConstructor[0],
38
+ name: undefined,
39
+ sourceId: undefined,
40
+ },
41
+ {
42
+ name: undefined,
43
+ type: 'Markers',
44
+ sourceId: undefined,
45
+ channelNames: ['Markers'],
46
+ channelFormat: 'string',
47
+ sampleRateHz: 0,
48
+ chunkSize: 1,
49
+ }
50
+ )
51
+
52
+ assert.isTrue(
53
+ FakeStreamOutlet.callsToConstructor[0]?.sourceId.startsWith(
54
+ 'event-markers-'
55
+ ),
56
+ 'Source ID was not generated uniquely!'
57
+ )
58
+
59
+ assert.isTrue(
60
+ FakeStreamOutlet.callsToConstructor[0]?.name.startsWith(
61
+ 'Event markers ('
62
+ ),
63
+ 'Name was not generated uniquely!'
64
+ )
65
+ }
66
+
67
+ @test()
68
+ protected static async canOverrideDefaultOptions() {
69
+ const options = generateRandomOutletOptions()
70
+ await this.LslEventMarkerEmitter(options)
71
+
72
+ assert.isEqualDeep(FakeStreamOutlet.callsToConstructor[1], options)
73
+ }
74
+
75
+ @test()
76
+ protected static async emittingSingleMarkerIncrementsHitCountAndWaitTime() {
77
+ const markers = [this.generateEventMarker()]
78
+ await this.instance.emitMany(markers)
79
+
80
+ const marker = markers[0]
81
+
82
+ assert.isEqual(
83
+ FakeStreamOutlet.callsToPushSample[0]?.sample[0],
84
+ marker.name,
85
+ 'Pushed the wrong marker!'
86
+ )
87
+
88
+ assert.isEqual(this.instance.totalwaitAfterMs, marker.waitAfterMs)
89
+ }
90
+
91
+ @test()
92
+ protected static async emittingTwoMarkersIncrementsHitCountAndWaitTimeTwice() {
93
+ const markers = await this.emitManyFor(2)
94
+
95
+ assert.isEqual(FakeStreamOutlet.callsToPushSample.length, 2)
96
+
97
+ assert.isEqual(
98
+ this.instance.totalwaitAfterMs,
99
+ markers[0].waitAfterMs + markers[1].waitAfterMs
100
+ )
101
+ }
102
+
103
+ @test('interrupts on first marker', 1)
104
+ @test('interrupts on second marker', 2)
105
+ @test('interrupts on third marker', 3)
106
+ protected static async emitterIsInterruptable(bailIdx: number) {
107
+ let hitCount = 0
108
+
109
+ this.streamOutlet.pushSample = () => {
110
+ hitCount += 1
111
+ if (hitCount === bailIdx) {
112
+ this.interrupt()
113
+ }
114
+ }
115
+
116
+ await this.emitManyFor(10)
117
+
118
+ assert.isEqual(hitCount, bailIdx)
119
+ }
120
+
121
+ @test()
122
+ protected static async canStartAgainAfterInterrupting() {
123
+ this.interrupt()
124
+
125
+ let hitCount = 0
126
+
127
+ this.streamOutlet.pushSample = () => {
128
+ hitCount++
129
+ }
130
+
131
+ await this.emitManyFor(10)
132
+
133
+ assert.isEqual(hitCount, 10)
134
+ }
135
+
136
+ @test()
137
+ protected static async doesNotWaitIfInterrupted() {
138
+ await this.setupOutlet()
139
+
140
+ const startMs = Date.now()
141
+ const promise = this.emitManyFor(2, 1000)
142
+ this.interrupt()
143
+ await promise
144
+ const endMs = Date.now()
145
+
146
+ assert.isBelow(endMs - startMs, 10)
147
+ }
148
+
149
+ @test()
150
+ protected static async clearsTimeoutOnInterrupt() {
151
+ void this.emitManyFor(2, 100)
152
+ this.interrupt()
153
+
154
+ this.streamOutlet.pushSample = () =>
155
+ assert.fail('Should not have been called')
156
+ }
157
+
158
+ @test()
159
+ protected static async emitCallsPushSampleOnStreamOutlet() {
160
+ const markerName = this.generateId()
161
+ await this.emit(markerName)
162
+
163
+ assert.isEqualDeep(
164
+ FakeStreamOutlet.callsToPushSample[0]?.sample,
165
+ [markerName],
166
+ 'Pushed the wrong sample!'
167
+ )
168
+ }
169
+
170
+ @test()
171
+ protected static async emitWaitsForMsIfPassed() {
172
+ SpyEventMarkerEmitter.shouldCallWaitOnSuper = true
173
+
174
+ const waitAfterMs = 10
175
+
176
+ const startMs = Date.now()
177
+ await this.instance.emit(this.markerName, { waitAfterMs })
178
+ const endMs = Date.now()
179
+
180
+ assert.isAbove(
181
+ endMs - startMs,
182
+ 0.8 * waitAfterMs,
183
+ 'Did not wait for the specified time!'
184
+ )
185
+ }
186
+
187
+ @test()
188
+ protected static async destroyCallsDestroyOnInternalStreamOutlet() {
189
+ this.destroy()
190
+
191
+ assert.isEqual(
192
+ FakeStreamOutlet.numCallsToDestroy,
193
+ 1,
194
+ 'Did not call destroy on outlet!'
195
+ )
196
+ }
197
+
198
+ @test()
199
+ protected static async destroyInterruptsIfRunning() {
200
+ let wasHit = false
201
+
202
+ const original = this.instance.interrupt.bind(this.instance)
203
+
204
+ this.instance.interrupt = () => {
205
+ wasHit = true
206
+ original()
207
+ }
208
+
209
+ const promise = this.emitManyFor(5, 10)
210
+ this.destroy()
211
+
212
+ assert.isTrue(wasHit, 'Did not call interrupt on destroy!')
213
+
214
+ await promise
215
+ }
216
+
217
+ @test()
218
+ protected static async sourceIdIsUniqueAcrossInstances() {
219
+ const instance = await this.LslEventMarkerEmitter()
220
+
221
+ assert.isNotEqual(
222
+ instance['outlet'].sourceId,
223
+ this.instance['outlet'].sourceId,
224
+ 'Source IDs are not unique!'
225
+ )
226
+ }
227
+
228
+ @test()
229
+ protected static async emitThrowsIfCalledWhileAlreadyRunning() {
230
+ void this.instance.emit(this.markerName, { waitAfterMs: 10 })
231
+
232
+ await assert.doesThrowAsync(async () => {
233
+ await this.emit(this.generateId())
234
+ }, 'Cannot call emit while already running!')
235
+ }
236
+
237
+ @test()
238
+ protected static async emitManyThrowsIfCalledWhileAlreadyRunning() {
239
+ void EventMarkerEmitterTest.emitManyOnce()
240
+
241
+ await assert.doesThrowAsync(async () => {
242
+ await this.emitManyFor(5, 1)
243
+ }, 'Cannot call emitMany while already running!')
244
+ }
245
+
246
+ @test()
247
+ protected static async emitSetsIsRunningFalseOnceDone() {
248
+ await this.emitOnce()
249
+
250
+ assert.isFalse(
251
+ this.instance['isRunning'],
252
+ 'emit did not set isRunning to false once done!'
253
+ )
254
+ }
255
+
256
+ @test()
257
+ protected static async emitManySetsIsRunningFalseOnceDone() {
258
+ await this.emitManyOnce()
259
+
260
+ assert.isFalse(
261
+ this.instance['isRunning'],
262
+ 'emitMany did not set isRunning to false once done! '
263
+ )
264
+ }
265
+
266
+ private static async emitOnce() {
267
+ await this.emit(this.markerName)
268
+ }
269
+
270
+ private static async emit(
271
+ markerName: string,
272
+ options?: EventMarkerOptions
273
+ ) {
274
+ return this.instance.emit(markerName, options)
275
+ }
276
+
277
+ private static async emitManyOnce() {
278
+ return this.emitManyFor(5, 1)
279
+ }
280
+
281
+ private static async emitManyFor(total: number, waitAfterMs?: number) {
282
+ const markers = new Array(total)
283
+ .fill(null)
284
+ .map(() => this.generateEventMarker(waitAfterMs))
285
+
286
+ await this.instance.emitMany(markers)
287
+
288
+ return markers
289
+ }
290
+
291
+ private static generateEventMarker(waitAfterMs?: number) {
292
+ return {
293
+ name: this.generateId(),
294
+ waitAfterMs: waitAfterMs ?? randomInt(100, 1000),
295
+ }
296
+ }
297
+
298
+ private static interrupt() {
299
+ this.instance.interrupt()
300
+ }
301
+
302
+ private static destroy() {
303
+ this.instance.destroy()
304
+ }
305
+
306
+ private static get streamOutlet() {
307
+ return this.instance.getStreamOutlet()
308
+ }
309
+
310
+ private static async setupOutlet() {
311
+ LslEventMarkerEmitter.Class = LslEventMarkerEmitter as any
312
+ this.instance = await this.LslEventMarkerEmitter()
313
+ }
314
+
315
+ private static async LslEventMarkerEmitter(
316
+ options?: Partial<StreamOutletOptions>
317
+ ) {
318
+ return (await LslEventMarkerEmitter.Create(
319
+ options
320
+ )) as SpyEventMarkerEmitter
321
+ }
322
+ }