@neurodevs/node-lsl 14.1.4 → 15.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.
- package/build/__tests__/AbstractPackageTest.d.ts +1 -0
- package/build/__tests__/AbstractPackageTest.js +7 -0
- package/build/__tests__/AbstractPackageTest.js.map +1 -1
- package/build/__tests__/impl/LslStreamInfo.test.d.ts +1 -0
- package/build/__tests__/impl/LslStreamInfo.test.js +33 -6
- package/build/__tests__/impl/LslStreamInfo.test.js.map +1 -1
- package/build/__tests__/impl/LslStreamInlet.test.d.ts +0 -1
- package/build/__tests__/impl/LslStreamInlet.test.js +0 -7
- package/build/__tests__/impl/LslStreamInlet.test.js.map +1 -1
- package/build/__tests__/impl/LslWebSocketBridge.test.d.ts +10 -2
- package/build/__tests__/impl/LslWebSocketBridge.test.js +81 -12
- package/build/__tests__/impl/LslWebSocketBridge.test.js.map +1 -1
- package/build/impl/LslStreamInfo.d.ts +17 -8
- package/build/impl/LslStreamInfo.js +12 -6
- package/build/impl/LslStreamInfo.js.map +1 -1
- package/build/impl/LslStreamInlet.d.ts +0 -1
- package/build/impl/LslStreamInlet.js +2 -5
- package/build/impl/LslStreamInlet.js.map +1 -1
- package/build/impl/LslStreamOutlet.d.ts +3 -2
- package/build/impl/LslStreamOutlet.js +4 -4
- package/build/impl/LslStreamOutlet.js.map +1 -1
- package/build/impl/LslWebSocketBridge.d.ts +18 -6
- package/build/impl/LslWebSocketBridge.js +73 -27
- package/build/impl/LslWebSocketBridge.js.map +1 -1
- package/build/testDoubles/StreamInfo/FakeStreamInfo.d.ts +8 -0
- package/build/testDoubles/StreamInfo/FakeStreamInfo.js +11 -0
- package/build/testDoubles/StreamInfo/FakeStreamInfo.js.map +1 -1
- package/build/testDoubles/StreamInfo/SpyStreamInfo.d.ts +2 -0
- package/build/testDoubles/StreamInfo/SpyStreamInfo.js +5 -0
- package/build/testDoubles/StreamInfo/SpyStreamInfo.js.map +1 -1
- package/build/testDoubles/WebSocketBridge/FakeWebSocketBridge.d.ts +2 -0
- package/build/testDoubles/WebSocketBridge/FakeWebSocketBridge.js +18 -4
- package/build/testDoubles/WebSocketBridge/FakeWebSocketBridge.js.map +1 -1
- package/build/testDoubles/WebSockets/FakeWebSocket.d.ts +4 -0
- package/build/testDoubles/WebSockets/FakeWebSocket.js +12 -1
- package/build/testDoubles/WebSockets/FakeWebSocket.js.map +1 -1
- package/package.json +1 -1
- package/src/__tests__/AbstractPackageTest.ts +10 -0
- package/src/__tests__/impl/LslStreamInfo.test.ts +40 -6
- package/src/__tests__/impl/LslStreamInlet.test.ts +0 -11
- package/src/__tests__/impl/LslWebSocketBridge.test.ts +114 -13
- package/src/impl/LslStreamInfo.ts +28 -12
- package/src/impl/LslStreamInlet.ts +4 -6
- package/src/impl/LslStreamOutlet.ts +6 -5
- package/src/impl/LslWebSocketBridge.ts +107 -38
- package/src/testDoubles/StreamInfo/FakeStreamInfo.ts +14 -0
- package/src/testDoubles/StreamInfo/SpyStreamInfo.ts +7 -0
- package/src/testDoubles/WebSocketBridge/FakeWebSocketBridge.ts +24 -5
- package/src/testDoubles/WebSockets/FakeWebSocket.ts +14 -1
|
@@ -14,7 +14,7 @@ export default class LslStreamOutlet implements StreamOutlet {
|
|
|
14
14
|
readonly manufacturer: string;
|
|
15
15
|
readonly units: string;
|
|
16
16
|
private info;
|
|
17
|
-
private
|
|
17
|
+
private boundOutlet;
|
|
18
18
|
private pushSampleMethod;
|
|
19
19
|
private lsl;
|
|
20
20
|
protected constructor(info: StreamInfo, options: StreamOutletOptions);
|
|
@@ -42,12 +42,13 @@ export interface StreamOutlet {
|
|
|
42
42
|
readonly type: string;
|
|
43
43
|
readonly sourceId: string;
|
|
44
44
|
readonly channelNames: string[];
|
|
45
|
+
readonly channelCount: number;
|
|
45
46
|
readonly channelFormat: ChannelFormat;
|
|
46
47
|
readonly sampleRateHz: number;
|
|
48
|
+
readonly units: string;
|
|
47
49
|
readonly chunkSize: number;
|
|
48
50
|
readonly maxBufferedMs: number;
|
|
49
51
|
readonly manufacturer: string;
|
|
50
|
-
readonly units: string;
|
|
51
52
|
}
|
|
52
53
|
export type StreamOutletConstructor = new (info: StreamInfo, options: StreamOutletOptions) => StreamOutlet;
|
|
53
54
|
export interface StreamOutletOptions {
|
|
@@ -16,7 +16,7 @@ export default class LslStreamOutlet {
|
|
|
16
16
|
manufacturer = 'N/A';
|
|
17
17
|
units = 'N/A';
|
|
18
18
|
info;
|
|
19
|
-
|
|
19
|
+
boundOutlet;
|
|
20
20
|
pushSampleMethod;
|
|
21
21
|
lsl = LiblslAdapter.getInstance();
|
|
22
22
|
constructor(info, options) {
|
|
@@ -64,7 +64,7 @@ export default class LslStreamOutlet {
|
|
|
64
64
|
throw new Error(`This method currently does not support the ${this.channelFormat} type! Please implement it.`);
|
|
65
65
|
}
|
|
66
66
|
createStreamOutlet() {
|
|
67
|
-
this.
|
|
67
|
+
this.boundOutlet = this.lsl.createOutlet({
|
|
68
68
|
info: this.boundStreamInfo,
|
|
69
69
|
chunkSize: this.chunkSize,
|
|
70
70
|
maxBufferedMs: this.maxBufferedMs,
|
|
@@ -86,7 +86,7 @@ export default class LslStreamOutlet {
|
|
|
86
86
|
pushSample(sample) {
|
|
87
87
|
const timestamp = this.lsl.localClock();
|
|
88
88
|
const err = this.pushSampleMethod({
|
|
89
|
-
outlet: this.
|
|
89
|
+
outlet: this.boundOutlet,
|
|
90
90
|
sample,
|
|
91
91
|
timestamp,
|
|
92
92
|
});
|
|
@@ -100,7 +100,7 @@ export default class LslStreamOutlet {
|
|
|
100
100
|
this.lsl.destroyStreamInfo({ info: this.boundStreamInfo });
|
|
101
101
|
}
|
|
102
102
|
destroyBoundOutlet() {
|
|
103
|
-
this.lsl.destroyOutlet({ outlet: this.
|
|
103
|
+
this.lsl.destroyOutlet({ outlet: this.boundOutlet });
|
|
104
104
|
}
|
|
105
105
|
static async waitToAllowSetup(waitAfterConstructionMs) {
|
|
106
106
|
await new Promise((resolve) => setTimeout(resolve, waitAfterConstructionMs));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LslStreamOutlet.js","sourceRoot":"","sources":["../../src/impl/LslStreamOutlet.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,uBAAuB,EACvB,wBAAwB,EACxB,oBAAoB,EACpB,wBAAwB,EACxB,uBAAuB,GAC1B,MAAM,kBAAkB,CAAA;AACzB,OAAO,WAA6B,MAAM,mBAAmB,CAAA;AAO7D,OAAO,aAAa,MAAM,oBAAoB,CAAA;AAC9C,OAAO,aAGN,MAAM,oBAAoB,CAAA;AAE3B,MAAM,CAAC,OAAO,OAAO,eAAe;IACzB,MAAM,CAAC,KAAK,CAA0B;IAE7B,IAAI,CAAQ;IACZ,IAAI,CAAQ;IACZ,QAAQ,CAAQ;IAChB,YAAY,CAAU;IACtB,aAAa,CAAe;IAC5B,YAAY,CAAQ;IACpB,YAAY,CAAQ;IACpB,SAAS,CAAQ;IACjB,aAAa,GAAG,GAAG,GAAG,IAAI,CAAA;IAC1B,YAAY,GAAW,KAAK,CAAA;IAC5B,KAAK,GAAW,KAAK,CAAA;IAE7B,IAAI,CAAY;IAChB,
|
|
1
|
+
{"version":3,"file":"LslStreamOutlet.js","sourceRoot":"","sources":["../../src/impl/LslStreamOutlet.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,26 +1,36 @@
|
|
|
1
|
-
import { WebSocketServer } from 'ws';
|
|
1
|
+
import WebSocket, { WebSocketServer } from 'ws';
|
|
2
2
|
import { ChannelFormat } from './LiblslAdapter.js';
|
|
3
3
|
import { StreamInlet } from './LslStreamInlet.js';
|
|
4
4
|
export default class LslWebSocketBridge implements WebSocketBridge {
|
|
5
5
|
static Class?: WebSocketBridgeConstructor;
|
|
6
|
+
static WS: typeof WebSocket;
|
|
6
7
|
static WSS: typeof import("ws").Server;
|
|
7
8
|
private inlet;
|
|
8
|
-
private
|
|
9
|
+
private localServer?;
|
|
10
|
+
private remoteSockets?;
|
|
9
11
|
private isDestroyed;
|
|
10
12
|
protected constructor(options: WebSocketBridgeConstructorOptions);
|
|
11
13
|
static Create(options: WebSocketBridgeOptions): WebSocketBridge;
|
|
14
|
+
private throwIfNoLocalServerOrRemoteSockets;
|
|
15
|
+
private readonly insufficientOptionsError;
|
|
12
16
|
activate(): void;
|
|
13
17
|
private throwIfBridgeIsDestroyed;
|
|
18
|
+
private readonly cannotActivateMessage;
|
|
14
19
|
private startPullingData;
|
|
15
20
|
deactivate(): void;
|
|
21
|
+
private readonly cannotDeactivateMessage;
|
|
16
22
|
private stopPullingData;
|
|
17
23
|
destroy(): void;
|
|
18
24
|
private destroyBoundInlet;
|
|
19
|
-
private
|
|
25
|
+
private closeLocalServerIfExists;
|
|
26
|
+
private closeRemoteSocketsIfExists;
|
|
20
27
|
private static createOnDataCallback;
|
|
21
28
|
private static broadcastToClients;
|
|
22
|
-
private static
|
|
29
|
+
private static sendToSockets;
|
|
30
|
+
private static createSocketsFrom;
|
|
31
|
+
private static WebSocket;
|
|
23
32
|
private static WebSocketServer;
|
|
33
|
+
private static LslStreamInlet;
|
|
24
34
|
}
|
|
25
35
|
export interface WebSocketBridge {
|
|
26
36
|
activate(): void;
|
|
@@ -36,9 +46,11 @@ export interface WebSocketBridgeOptions {
|
|
|
36
46
|
name?: string;
|
|
37
47
|
type?: string;
|
|
38
48
|
sourceId?: string;
|
|
39
|
-
|
|
49
|
+
localWebSocketPort?: number;
|
|
50
|
+
remoteWebSocketUrls?: string | string[];
|
|
40
51
|
}
|
|
41
52
|
export interface WebSocketBridgeConstructorOptions extends WebSocketBridgeOptions {
|
|
42
53
|
inlet: StreamInlet;
|
|
43
|
-
|
|
54
|
+
localServer?: WebSocketServer;
|
|
55
|
+
remoteSockets?: WebSocket[];
|
|
44
56
|
}
|
|
@@ -1,72 +1,118 @@
|
|
|
1
|
-
import { WebSocketServer } from 'ws';
|
|
1
|
+
import WebSocket, { WebSocketServer } from 'ws';
|
|
2
2
|
import LslStreamInlet from './LslStreamInlet.js';
|
|
3
3
|
export default class LslWebSocketBridge {
|
|
4
4
|
static Class;
|
|
5
|
+
static WS = WebSocket;
|
|
5
6
|
static WSS = WebSocketServer;
|
|
6
7
|
inlet;
|
|
7
|
-
|
|
8
|
+
localServer;
|
|
9
|
+
remoteSockets;
|
|
8
10
|
isDestroyed = false;
|
|
9
11
|
constructor(options) {
|
|
10
|
-
const { inlet,
|
|
12
|
+
const { inlet, localServer, remoteSockets } = options;
|
|
11
13
|
this.inlet = inlet;
|
|
12
|
-
this.
|
|
14
|
+
this.localServer = localServer;
|
|
15
|
+
this.remoteSockets = remoteSockets;
|
|
16
|
+
this.throwIfNoLocalServerOrRemoteSockets();
|
|
13
17
|
}
|
|
14
18
|
static Create(options) {
|
|
15
|
-
const {
|
|
16
|
-
const
|
|
17
|
-
const
|
|
18
|
-
|
|
19
|
+
const { localWebSocketPort, remoteWebSocketUrls, ...rest } = options;
|
|
20
|
+
const inletOptions = rest;
|
|
21
|
+
const localServer = this.WebSocketServer(localWebSocketPort);
|
|
22
|
+
const remoteSockets = this.createSocketsFrom(remoteWebSocketUrls);
|
|
23
|
+
const inlet = this.LslStreamInlet(inletOptions, localServer, remoteSockets);
|
|
24
|
+
return new (this.Class ?? this)({
|
|
25
|
+
...options,
|
|
26
|
+
inlet,
|
|
27
|
+
localServer,
|
|
28
|
+
remoteSockets,
|
|
29
|
+
});
|
|
19
30
|
}
|
|
31
|
+
throwIfNoLocalServerOrRemoteSockets() {
|
|
32
|
+
if (!(this.localServer || this.remoteSockets)) {
|
|
33
|
+
throw new Error(this.insufficientOptionsError);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
insufficientOptionsError = `At least one of localWebSocketPort or remoteWebSocketUrls must be provided!`;
|
|
20
37
|
activate() {
|
|
21
|
-
this.throwIfBridgeIsDestroyed();
|
|
38
|
+
this.throwIfBridgeIsDestroyed(this.cannotActivateMessage);
|
|
22
39
|
this.startPullingData();
|
|
23
40
|
}
|
|
24
|
-
throwIfBridgeIsDestroyed() {
|
|
41
|
+
throwIfBridgeIsDestroyed(err) {
|
|
25
42
|
if (this.isDestroyed) {
|
|
26
|
-
throw new Error(
|
|
43
|
+
throw new Error(err);
|
|
27
44
|
}
|
|
28
45
|
}
|
|
46
|
+
cannotActivateMessage = `\n\n Cannot activate bridge after destroying it! \n\n Please create and activate a new instance. \n`;
|
|
29
47
|
startPullingData() {
|
|
30
48
|
this.inlet.startPulling();
|
|
31
49
|
}
|
|
32
50
|
deactivate() {
|
|
51
|
+
this.throwIfBridgeIsDestroyed(this.cannotDeactivateMessage);
|
|
33
52
|
this.stopPullingData();
|
|
34
53
|
}
|
|
54
|
+
cannotDeactivateMessage = `\n\n Cannot deactivate bridge after destroying it! \n\n Please create and activate a new instance. \n`;
|
|
35
55
|
stopPullingData() {
|
|
36
56
|
this.inlet.stopPulling();
|
|
37
57
|
}
|
|
38
58
|
destroy() {
|
|
39
59
|
this.destroyBoundInlet();
|
|
40
|
-
this.
|
|
60
|
+
this.closeLocalServerIfExists();
|
|
61
|
+
this.closeRemoteSocketsIfExists();
|
|
41
62
|
this.isDestroyed = true;
|
|
42
63
|
}
|
|
43
64
|
destroyBoundInlet() {
|
|
44
65
|
this.inlet.destroy();
|
|
45
66
|
}
|
|
46
|
-
|
|
47
|
-
this.
|
|
67
|
+
closeLocalServerIfExists() {
|
|
68
|
+
this.localServer?.close();
|
|
69
|
+
}
|
|
70
|
+
closeRemoteSocketsIfExists() {
|
|
71
|
+
this.remoteSockets?.forEach((socket) => socket.close());
|
|
48
72
|
}
|
|
49
|
-
static createOnDataCallback(
|
|
73
|
+
static createOnDataCallback(localServer, remoteSockets) {
|
|
50
74
|
return (samples, timestamps) => {
|
|
51
|
-
|
|
75
|
+
const payload = JSON.stringify({ samples, timestamps });
|
|
76
|
+
if (localServer) {
|
|
77
|
+
this.broadcastToClients(localServer, payload);
|
|
78
|
+
}
|
|
79
|
+
if (remoteSockets) {
|
|
80
|
+
this.sendToSockets(remoteSockets, payload);
|
|
81
|
+
}
|
|
52
82
|
};
|
|
53
83
|
}
|
|
54
|
-
static broadcastToClients(
|
|
55
|
-
for (const client of
|
|
84
|
+
static broadcastToClients(localServer, payload) {
|
|
85
|
+
for (const client of localServer.clients) {
|
|
56
86
|
if (client.readyState === WebSocket.OPEN) {
|
|
57
|
-
client.send(
|
|
58
|
-
samples,
|
|
59
|
-
timestamps,
|
|
60
|
-
}));
|
|
87
|
+
client.send(payload);
|
|
61
88
|
}
|
|
62
89
|
}
|
|
63
90
|
}
|
|
64
|
-
static
|
|
65
|
-
const
|
|
66
|
-
|
|
91
|
+
static sendToSockets(remoteSockets, payload) {
|
|
92
|
+
for (const socket of remoteSockets) {
|
|
93
|
+
if (socket.readyState === WebSocket.OPEN) {
|
|
94
|
+
socket.send(payload);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
static createSocketsFrom(remoteWebSocketUrls) {
|
|
99
|
+
return remoteWebSocketUrls
|
|
100
|
+
? (Array.isArray(remoteWebSocketUrls)
|
|
101
|
+
? remoteWebSocketUrls
|
|
102
|
+
: [remoteWebSocketUrls]).map((url) => this.WebSocket(url))
|
|
103
|
+
: undefined;
|
|
67
104
|
}
|
|
68
|
-
static
|
|
69
|
-
return new this.
|
|
105
|
+
static WebSocket(url) {
|
|
106
|
+
return new this.WS(url);
|
|
107
|
+
}
|
|
108
|
+
static WebSocketServer(localWebSocketPort) {
|
|
109
|
+
return localWebSocketPort
|
|
110
|
+
? new this.WSS({ port: localWebSocketPort })
|
|
111
|
+
: undefined;
|
|
112
|
+
}
|
|
113
|
+
static LslStreamInlet(options, localServer, remoteSockets) {
|
|
114
|
+
const onData = this.createOnDataCallback(localServer, remoteSockets);
|
|
115
|
+
return LslStreamInlet.Create(options, onData);
|
|
70
116
|
}
|
|
71
117
|
}
|
|
72
118
|
//# sourceMappingURL=LslWebSocketBridge.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LslWebSocketBridge.js","sourceRoot":"","sources":["../../src/impl/LslWebSocketBridge.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,IAAI,CAAA;
|
|
1
|
+
{"version":3,"file":"LslWebSocketBridge.js","sourceRoot":"","sources":["../../src/impl/LslWebSocketBridge.ts"],"names":[],"mappings":"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"}
|
|
@@ -4,8 +4,16 @@ export default class FakeStreamInfo implements StreamInfo {
|
|
|
4
4
|
static callsToConstructor: StreamInfoOptions[];
|
|
5
5
|
static numCallsToDestroy: number;
|
|
6
6
|
static boundStreamInfo: BoundStreamInfo;
|
|
7
|
+
name: string;
|
|
8
|
+
type: string;
|
|
9
|
+
sourceId: string;
|
|
10
|
+
channelNames: string[];
|
|
11
|
+
channelFormat: "float32";
|
|
12
|
+
sampleRateHz: number;
|
|
13
|
+
units: string;
|
|
7
14
|
constructor(options: StreamInfoOptions);
|
|
8
15
|
destroy(): void;
|
|
16
|
+
get channelCount(): number;
|
|
9
17
|
get boundStreamInfo(): BoundStreamInfo;
|
|
10
18
|
static resetTestDouble(): void;
|
|
11
19
|
}
|
|
@@ -1,13 +1,24 @@
|
|
|
1
|
+
import generateId from '@neurodevs/generate-id';
|
|
1
2
|
export default class FakeStreamInfo {
|
|
2
3
|
static callsToConstructor = [];
|
|
3
4
|
static numCallsToDestroy = 0;
|
|
4
5
|
static boundStreamInfo = {};
|
|
6
|
+
name = generateId();
|
|
7
|
+
type = generateId();
|
|
8
|
+
sourceId = generateId();
|
|
9
|
+
channelNames = [generateId(), generateId()];
|
|
10
|
+
channelFormat = 'float32';
|
|
11
|
+
sampleRateHz = 0;
|
|
12
|
+
units = 'N/A';
|
|
5
13
|
constructor(options) {
|
|
6
14
|
FakeStreamInfo.callsToConstructor.push(options);
|
|
7
15
|
}
|
|
8
16
|
destroy() {
|
|
9
17
|
FakeStreamInfo.numCallsToDestroy++;
|
|
10
18
|
}
|
|
19
|
+
get channelCount() {
|
|
20
|
+
return this.channelNames.length;
|
|
21
|
+
}
|
|
11
22
|
get boundStreamInfo() {
|
|
12
23
|
return FakeStreamInfo.boundStreamInfo;
|
|
13
24
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FakeStreamInfo.js","sourceRoot":"","sources":["../../../src/testDoubles/StreamInfo/FakeStreamInfo.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"FakeStreamInfo.js","sourceRoot":"","sources":["../../../src/testDoubles/StreamInfo/FakeStreamInfo.ts"],"names":[],"mappings":"AAAA,OAAO,UAAU,MAAM,wBAAwB,CAAA;AAK/C,MAAM,CAAC,OAAO,OAAO,cAAc;IACxB,MAAM,CAAC,kBAAkB,GAAwB,EAAE,CAAA;IACnD,MAAM,CAAC,iBAAiB,GAAG,CAAC,CAAA;IAE5B,MAAM,CAAC,eAAe,GAAG,EAAqB,CAAA;IAE9C,IAAI,GAAG,UAAU,EAAE,CAAA;IACnB,IAAI,GAAG,UAAU,EAAE,CAAA;IACnB,QAAQ,GAAG,UAAU,EAAE,CAAA;IACvB,YAAY,GAAa,CAAC,UAAU,EAAE,EAAE,UAAU,EAAE,CAAC,CAAA;IACrD,aAAa,GAAG,SAAkB,CAAA;IAClC,YAAY,GAAG,CAAC,CAAA;IAChB,KAAK,GAAG,KAAK,CAAA;IAEpB,YAAmB,OAA0B;QACzC,cAAc,CAAC,kBAAkB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;IACnD,CAAC;IAEM,OAAO;QACV,cAAc,CAAC,iBAAiB,EAAE,CAAA;IACtC,CAAC;IAED,IAAW,YAAY;QACnB,OAAO,IAAI,CAAC,YAAY,CAAC,MAAM,CAAA;IACnC,CAAC;IAED,IAAW,eAAe;QACtB,OAAO,cAAc,CAAC,eAAe,CAAA;IACzC,CAAC;IAEM,MAAM,CAAC,eAAe;QACzB,cAAc,CAAC,kBAAkB,GAAG,EAAE,CAAA;QACtC,cAAc,CAAC,iBAAiB,GAAG,CAAC,CAAA;IACxC,CAAC"}
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import LslStreamInfo, { StreamInfoOptions } from '../../impl/LslStreamInfo.js';
|
|
2
2
|
export default class SpyStreamInfo extends LslStreamInfo {
|
|
3
|
+
static numCallsToConstructor: number;
|
|
3
4
|
constructor(options: StreamInfoOptions);
|
|
4
5
|
getBoundInfo(): import("../../index.js").BoundStreamInfo;
|
|
5
6
|
getName(): string;
|
|
6
7
|
getType(): string;
|
|
7
8
|
getSourceId(): string;
|
|
8
9
|
getUnits(): string;
|
|
10
|
+
static resetTestDouble(): void;
|
|
9
11
|
}
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import LslStreamInfo from '../../impl/LslStreamInfo.js';
|
|
2
2
|
export default class SpyStreamInfo extends LslStreamInfo {
|
|
3
|
+
static numCallsToConstructor = 0;
|
|
3
4
|
constructor(options) {
|
|
4
5
|
super(options);
|
|
6
|
+
SpyStreamInfo.numCallsToConstructor++;
|
|
5
7
|
}
|
|
6
8
|
getBoundInfo() {
|
|
7
9
|
return this.boundInfo;
|
|
@@ -18,5 +20,8 @@ export default class SpyStreamInfo extends LslStreamInfo {
|
|
|
18
20
|
getUnits() {
|
|
19
21
|
return this.units;
|
|
20
22
|
}
|
|
23
|
+
static resetTestDouble() {
|
|
24
|
+
SpyStreamInfo.numCallsToConstructor = 0;
|
|
25
|
+
}
|
|
21
26
|
}
|
|
22
27
|
//# sourceMappingURL=SpyStreamInfo.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SpyStreamInfo.js","sourceRoot":"","sources":["../../../src/testDoubles/StreamInfo/SpyStreamInfo.ts"],"names":[],"mappings":"AAAA,OAAO,aAAoC,MAAM,6BAA6B,CAAA;AAE9E,MAAM,CAAC,OAAO,OAAO,aAAc,SAAQ,aAAa;
|
|
1
|
+
{"version":3,"file":"SpyStreamInfo.js","sourceRoot":"","sources":["../../../src/testDoubles/StreamInfo/SpyStreamInfo.ts"],"names":[],"mappings":"AAAA,OAAO,aAAoC,MAAM,6BAA6B,CAAA;AAE9E,MAAM,CAAC,OAAO,OAAO,aAAc,SAAQ,aAAa;IAC7C,MAAM,CAAC,qBAAqB,GAAG,CAAC,CAAA;IAEvC,YAAmB,OAA0B;QACzC,KAAK,CAAC,OAAO,CAAC,CAAA;QACd,aAAa,CAAC,qBAAqB,EAAE,CAAA;IACzC,CAAC;IAEM,YAAY;QACf,OAAO,IAAI,CAAC,SAAS,CAAA;IACzB,CAAC;IAEM,OAAO;QACV,OAAO,IAAI,CAAC,IAAI,CAAA;IACpB,CAAC;IAEM,OAAO;QACV,OAAO,IAAI,CAAC,IAAI,CAAA;IACpB,CAAC;IAEM,WAAW;QACd,OAAO,IAAI,CAAC,QAAQ,CAAA;IACxB,CAAC;IAEM,QAAQ;QACX,OAAO,IAAI,CAAC,KAAK,CAAA;IACrB,CAAC;IAEM,MAAM,CAAC,eAAe;QACzB,aAAa,CAAC,qBAAqB,GAAG,CAAC,CAAA;IAC3C,CAAC"}
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import LslWebSocketBridge from '../../impl/LslWebSocketBridge.js';
|
|
2
|
+
import FakeWebSocket from '../WebSockets/FakeWebSocket.js';
|
|
3
|
+
import FakeWebSocketServer from '../WebSockets/FakeWebSocketServer.js';
|
|
1
4
|
export default class FakeWebSocketBridge {
|
|
2
5
|
static numCallsToConstructor = 0;
|
|
3
6
|
static numCallsToActivate = 0;
|
|
@@ -16,10 +19,21 @@ export default class FakeWebSocketBridge {
|
|
|
16
19
|
FakeWebSocketBridge.numCallsToDestroy++;
|
|
17
20
|
}
|
|
18
21
|
static resetTestDouble() {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
22
|
+
this.numCallsToConstructor = 0;
|
|
23
|
+
this.numCallsToActivate = 0;
|
|
24
|
+
this.numCallsToDeactivate = 0;
|
|
25
|
+
this.numCallsToDestroy = 0;
|
|
26
|
+
this.setFakeWebSocket();
|
|
27
|
+
this.setFakeWebSocketServer();
|
|
28
|
+
}
|
|
29
|
+
static setFakeWebSocket() {
|
|
30
|
+
LslWebSocketBridge.WS = FakeWebSocket;
|
|
31
|
+
FakeWebSocket.resetTestDouble();
|
|
32
|
+
}
|
|
33
|
+
static setFakeWebSocketServer() {
|
|
34
|
+
LslWebSocketBridge.WSS =
|
|
35
|
+
FakeWebSocketServer;
|
|
36
|
+
FakeWebSocketServer.resetTestDouble();
|
|
23
37
|
}
|
|
24
38
|
}
|
|
25
39
|
//# sourceMappingURL=FakeWebSocketBridge.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FakeWebSocketBridge.js","sourceRoot":"","sources":["../../../src/testDoubles/WebSocketBridge/FakeWebSocketBridge.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"FakeWebSocketBridge.js","sourceRoot":"","sources":["../../../src/testDoubles/WebSocketBridge/FakeWebSocketBridge.ts"],"names":[],"mappings":"AACA,OAAO,kBAEN,MAAM,kCAAkC,CAAA;AACzC,OAAO,aAAa,MAAM,gCAAgC,CAAA;AAC1D,OAAO,mBAAmB,MAAM,sCAAsC,CAAA;AAEtE,MAAM,CAAC,OAAO,OAAO,mBAAmB;IAC7B,MAAM,CAAC,qBAAqB,GAAG,CAAC,CAAA;IAChC,MAAM,CAAC,kBAAkB,GAAG,CAAC,CAAA;IAC7B,MAAM,CAAC,oBAAoB,GAAG,CAAC,CAAA;IAC/B,MAAM,CAAC,iBAAiB,GAAG,CAAC,CAAA;IAEnC;QACI,mBAAmB,CAAC,qBAAqB,EAAE,CAAA;IAC/C,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,qBAAqB,GAAG,CAAC,CAAA;QAC9B,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,10 +1,14 @@
|
|
|
1
1
|
export default class FakeWebSocket {
|
|
2
|
+
static callsToConstructor: (string | undefined)[];
|
|
2
3
|
static callsToSend: {
|
|
3
4
|
id: string;
|
|
4
5
|
data: unknown;
|
|
5
6
|
}[];
|
|
7
|
+
static numCallsToClose: number;
|
|
6
8
|
readyState: number;
|
|
7
9
|
id: string;
|
|
10
|
+
constructor(url?: string);
|
|
8
11
|
send(data: unknown): void;
|
|
12
|
+
close(): void;
|
|
9
13
|
static resetTestDouble(): void;
|
|
10
14
|
}
|
|
@@ -1,14 +1,25 @@
|
|
|
1
1
|
import generateId from '@neurodevs/generate-id';
|
|
2
2
|
import WebSocket from 'ws';
|
|
3
3
|
export default class FakeWebSocket {
|
|
4
|
+
static callsToConstructor = [];
|
|
4
5
|
static callsToSend = [];
|
|
6
|
+
static numCallsToClose = 0;
|
|
5
7
|
readyState = WebSocket.OPEN;
|
|
6
8
|
id = generateId();
|
|
9
|
+
constructor(url) {
|
|
10
|
+
FakeWebSocket.callsToConstructor.push(url);
|
|
11
|
+
}
|
|
7
12
|
send(data) {
|
|
8
13
|
FakeWebSocket.callsToSend.push({ id: this.id, data });
|
|
9
14
|
}
|
|
15
|
+
close() {
|
|
16
|
+
FakeWebSocket.numCallsToClose++;
|
|
17
|
+
this.readyState = WebSocket.CLOSED;
|
|
18
|
+
}
|
|
10
19
|
static resetTestDouble() {
|
|
11
|
-
|
|
20
|
+
this.callsToConstructor = [];
|
|
21
|
+
this.callsToSend = [];
|
|
22
|
+
this.numCallsToClose = 0;
|
|
12
23
|
}
|
|
13
24
|
}
|
|
14
25
|
//# sourceMappingURL=FakeWebSocket.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FakeWebSocket.js","sourceRoot":"","sources":["../../../src/testDoubles/WebSockets/FakeWebSocket.ts"],"names":[],"mappings":"AAAA,OAAO,UAAU,MAAM,wBAAwB,CAAA;AAC/C,OAAO,SAAS,MAAM,IAAI,CAAA;AAE1B,MAAM,CAAC,OAAO,OAAO,aAAa;IACvB,MAAM,CAAC,WAAW,GAAoC,EAAE,CAAA;
|
|
1
|
+
{"version":3,"file":"FakeWebSocket.js","sourceRoot":"","sources":["../../../src/testDoubles/WebSockets/FakeWebSocket.ts"],"names":[],"mappings":"AAAA,OAAO,UAAU,MAAM,wBAAwB,CAAA;AAC/C,OAAO,SAAS,MAAM,IAAI,CAAA;AAE1B,MAAM,CAAC,OAAO,OAAO,aAAa;IACvB,MAAM,CAAC,kBAAkB,GAA2B,EAAE,CAAA;IACtD,MAAM,CAAC,WAAW,GAAoC,EAAE,CAAA;IACxD,MAAM,CAAC,eAAe,GAAG,CAAC,CAAA;IAE1B,UAAU,GAAW,SAAS,CAAC,IAAI,CAAA;IACnC,EAAE,GAAG,UAAU,EAAE,CAAA;IAExB,YAAmB,GAAY;QAC3B,aAAa,CAAC,kBAAkB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;IAC9C,CAAC;IAEM,IAAI,CAAC,IAAa;QACrB,aAAa,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,IAAI,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC,CAAA;IACzD,CAAC;IAEM,KAAK;QACR,aAAa,CAAC,eAAe,EAAE,CAAA;QAC/B,IAAI,CAAC,UAAU,GAAG,SAAS,CAAC,MAAM,CAAA;IACtC,CAAC;IAEM,MAAM,CAAC,eAAe;QACzB,IAAI,CAAC,kBAAkB,GAAG,EAAE,CAAA;QAC5B,IAAI,CAAC,WAAW,GAAG,EAAE,CAAA;QACrB,IAAI,CAAC,eAAe,GAAG,CAAC,CAAA;IAC5B,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import AbstractModuleTest from '@neurodevs/node-tdd'
|
|
2
|
+
import WebSocket from 'ws'
|
|
2
3
|
|
|
3
4
|
import { Server } from 'ws'
|
|
4
5
|
import LiblslAdapter from '../impl/LiblslAdapter.js'
|
|
@@ -18,6 +19,7 @@ import FakeStreamInlet from '../testDoubles/StreamInlet/FakeStreamInlet.js'
|
|
|
18
19
|
import { SpyStreamInlet } from '../testDoubles/StreamInlet/SpyStreamInlet.js'
|
|
19
20
|
import FakeStreamOutlet from '../testDoubles/StreamOutlet/FakeStreamOutlet.js'
|
|
20
21
|
import SpyLslWebSocketBridge from '../testDoubles/WebSocketBridge/SpyLslWebSocketBridge.js'
|
|
22
|
+
import FakeWebSocket from '../testDoubles/WebSockets/FakeWebSocket.js'
|
|
21
23
|
import FakeWebSocketServer from '../testDoubles/WebSockets/FakeWebSocketServer.js'
|
|
22
24
|
|
|
23
25
|
export default class AbstractPackageTest extends AbstractModuleTest {
|
|
@@ -38,11 +40,14 @@ export default class AbstractPackageTest extends AbstractModuleTest {
|
|
|
38
40
|
|
|
39
41
|
protected static setSpyStreamInfo() {
|
|
40
42
|
LslStreamInfo.Class = SpyStreamInfo
|
|
43
|
+
SpyStreamInfo.resetTestDouble()
|
|
41
44
|
}
|
|
42
45
|
|
|
43
46
|
protected static setFakeStreamInfo() {
|
|
44
47
|
LslStreamInfo.Class = FakeStreamInfo
|
|
45
48
|
FakeStreamInfo.resetTestDouble()
|
|
49
|
+
|
|
50
|
+
LslStreamInfo['instanceCache'] = {}
|
|
46
51
|
}
|
|
47
52
|
|
|
48
53
|
protected static setSpyStreamInlet() {
|
|
@@ -67,6 +72,11 @@ export default class AbstractPackageTest extends AbstractModuleTest {
|
|
|
67
72
|
LslWebSocketBridge.Class = SpyLslWebSocketBridge
|
|
68
73
|
}
|
|
69
74
|
|
|
75
|
+
protected static setFakeWebSocket() {
|
|
76
|
+
LslWebSocketBridge.WS = FakeWebSocket as unknown as typeof WebSocket
|
|
77
|
+
FakeWebSocket.resetTestDouble()
|
|
78
|
+
}
|
|
79
|
+
|
|
70
80
|
protected static setFakeWebSocketServer() {
|
|
71
81
|
LslWebSocketBridge.WSS = FakeWebSocketServer as unknown as typeof Server
|
|
72
82
|
FakeWebSocketServer.resetTestDouble()
|
|
@@ -13,6 +13,8 @@ export default class LslStreamInfoTest extends AbstractPackageTest {
|
|
|
13
13
|
|
|
14
14
|
this.setSpyStreamInfo()
|
|
15
15
|
|
|
16
|
+
LslStreamInfo['instanceCache'] = {}
|
|
17
|
+
|
|
16
18
|
this.instance = this.LslStreamInfo()
|
|
17
19
|
}
|
|
18
20
|
|
|
@@ -23,8 +25,15 @@ export default class LslStreamInfoTest extends AbstractPackageTest {
|
|
|
23
25
|
|
|
24
26
|
@test()
|
|
25
27
|
protected static async generatesUniqueNameIfNotProvided() {
|
|
26
|
-
const instance1 = this.LslStreamInfo({
|
|
27
|
-
|
|
28
|
+
const instance1 = this.LslStreamInfo({
|
|
29
|
+
name: undefined,
|
|
30
|
+
type: this.generateId(),
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
const instance2 = this.LslStreamInfo({
|
|
34
|
+
name: undefined,
|
|
35
|
+
type: this.generateId(),
|
|
36
|
+
})
|
|
28
37
|
|
|
29
38
|
assert.isNotEqual(
|
|
30
39
|
instance1.getName(),
|
|
@@ -58,8 +67,15 @@ export default class LslStreamInfoTest extends AbstractPackageTest {
|
|
|
58
67
|
|
|
59
68
|
@test()
|
|
60
69
|
protected static async generatesUniqueTypeIfNotProvided() {
|
|
61
|
-
const instance1 = this.LslStreamInfo({
|
|
62
|
-
|
|
70
|
+
const instance1 = this.LslStreamInfo({
|
|
71
|
+
type: undefined,
|
|
72
|
+
name: this.generateId(),
|
|
73
|
+
})
|
|
74
|
+
|
|
75
|
+
const instance2 = this.LslStreamInfo({
|
|
76
|
+
type: undefined,
|
|
77
|
+
name: this.generateId(),
|
|
78
|
+
})
|
|
63
79
|
|
|
64
80
|
assert.isNotEqual(
|
|
65
81
|
instance1.getType(),
|
|
@@ -82,8 +98,15 @@ export default class LslStreamInfoTest extends AbstractPackageTest {
|
|
|
82
98
|
|
|
83
99
|
@test()
|
|
84
100
|
protected static async generatesUniqueSourceIdIfNotProvided() {
|
|
85
|
-
const instance1 = this.LslStreamInfo({
|
|
86
|
-
|
|
101
|
+
const instance1 = this.LslStreamInfo({
|
|
102
|
+
sourceId: undefined,
|
|
103
|
+
name: this.generateId(),
|
|
104
|
+
})
|
|
105
|
+
|
|
106
|
+
const instance2 = this.LslStreamInfo({
|
|
107
|
+
sourceId: undefined,
|
|
108
|
+
name: this.generateId(),
|
|
109
|
+
})
|
|
87
110
|
|
|
88
111
|
assert.isNotEqual(
|
|
89
112
|
instance1.getSourceId(),
|
|
@@ -192,6 +215,17 @@ export default class LslStreamInfoTest extends AbstractPackageTest {
|
|
|
192
215
|
)
|
|
193
216
|
}
|
|
194
217
|
|
|
218
|
+
@test()
|
|
219
|
+
protected static async cachesInfoIfPassedSameOptions() {
|
|
220
|
+
this.LslStreamInfo()
|
|
221
|
+
|
|
222
|
+
assert.isEqual(
|
|
223
|
+
SpyStreamInfo.numCallsToConstructor,
|
|
224
|
+
1,
|
|
225
|
+
'Did not cache stream info!'
|
|
226
|
+
)
|
|
227
|
+
}
|
|
228
|
+
|
|
195
229
|
private static readonly defaultOptions = {
|
|
196
230
|
name: this.generateId(),
|
|
197
231
|
type: this.generateId(),
|
|
@@ -94,17 +94,6 @@ export default class LslStreamInletTest extends AbstractPackageTest {
|
|
|
94
94
|
)
|
|
95
95
|
}
|
|
96
96
|
|
|
97
|
-
@test()
|
|
98
|
-
protected static async destroyAlsoCallsDestroyStreamInfo() {
|
|
99
|
-
this.instance.destroy()
|
|
100
|
-
|
|
101
|
-
assert.isEqualDeep(
|
|
102
|
-
this.fakeLiblsl.lastDestroyStreamInfoOptions,
|
|
103
|
-
{ info: this.instance.getStreamInfo().boundStreamInfo },
|
|
104
|
-
'Did not destroy stream info!'
|
|
105
|
-
)
|
|
106
|
-
}
|
|
107
|
-
|
|
108
97
|
@test()
|
|
109
98
|
protected static async exposesIsRunningFieldThatIsFalseAtFirst() {
|
|
110
99
|
assert.isFalse(this.isRunning, 'isRunning should be false at first!')
|