@grest-ts/websocket 0.0.5
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/LICENSE +21 -0
- package/dist/src/adapter/BrowserSocketAdapter.d.ts +18 -0
- package/dist/src/adapter/BrowserSocketAdapter.d.ts.map +1 -0
- package/dist/src/adapter/BrowserSocketAdapter.js +51 -0
- package/dist/src/adapter/BrowserSocketAdapter.js.map +1 -0
- package/dist/src/adapter/NodeSocketAdapter.d.ts +21 -0
- package/dist/src/adapter/NodeSocketAdapter.d.ts.map +1 -0
- package/dist/src/adapter/NodeSocketAdapter.js +52 -0
- package/dist/src/adapter/NodeSocketAdapter.js.map +1 -0
- package/dist/src/adapter/getDefaultAdapter.d.ts +5 -0
- package/dist/src/adapter/getDefaultAdapter.d.ts.map +1 -0
- package/dist/src/adapter/getDefaultAdapter.js +15 -0
- package/dist/src/adapter/getDefaultAdapter.js.map +1 -0
- package/dist/src/client/GGSocketClient.d.ts +10 -0
- package/dist/src/client/GGSocketClient.d.ts.map +1 -0
- package/dist/src/client/GGSocketClient.js +17 -0
- package/dist/src/client/GGSocketClient.js.map +1 -0
- package/dist/src/client/GGSocketPool.d.ts +63 -0
- package/dist/src/client/GGSocketPool.d.ts.map +1 -0
- package/dist/src/client/GGSocketPool.js +203 -0
- package/dist/src/client/GGSocketPool.js.map +1 -0
- package/dist/src/index-browser.d.ts +11 -0
- package/dist/src/index-browser.d.ts.map +1 -0
- package/dist/src/index-browser.js +17 -0
- package/dist/src/index-browser.js.map +1 -0
- package/dist/src/index-node.d.ts +14 -0
- package/dist/src/index-node.d.ts.map +1 -0
- package/dist/src/index-node.js +22 -0
- package/dist/src/index-node.js.map +1 -0
- package/dist/src/schema/GGWebSocketMiddleware.d.ts +40 -0
- package/dist/src/schema/GGWebSocketMiddleware.d.ts.map +1 -0
- package/dist/src/schema/GGWebSocketMiddleware.js +6 -0
- package/dist/src/schema/GGWebSocketMiddleware.js.map +1 -0
- package/dist/src/schema/GGWebSocketSchema.d.ts +31 -0
- package/dist/src/schema/GGWebSocketSchema.d.ts.map +1 -0
- package/dist/src/schema/GGWebSocketSchema.js +32 -0
- package/dist/src/schema/GGWebSocketSchema.js.map +1 -0
- package/dist/src/schema/webSocketSchema.d.ts +52 -0
- package/dist/src/schema/webSocketSchema.d.ts.map +1 -0
- package/dist/src/schema/webSocketSchema.js +62 -0
- package/dist/src/schema/webSocketSchema.js.map +1 -0
- package/dist/src/server/GGSocketServer.d.ts +34 -0
- package/dist/src/server/GGSocketServer.d.ts.map +1 -0
- package/dist/src/server/GGSocketServer.js +186 -0
- package/dist/src/server/GGSocketServer.js.map +1 -0
- package/dist/src/server/GGWebSocketMetrics.d.ts +43 -0
- package/dist/src/server/GGWebSocketMetrics.d.ts.map +1 -0
- package/dist/src/server/GGWebSocketMetrics.js +38 -0
- package/dist/src/server/GGWebSocketMetrics.js.map +1 -0
- package/dist/src/server/GGWebSocketSchema.startServer.d.ts +33 -0
- package/dist/src/server/GGWebSocketSchema.startServer.d.ts.map +1 -0
- package/dist/src/server/GGWebSocketSchema.startServer.js +80 -0
- package/dist/src/server/GGWebSocketSchema.startServer.js.map +1 -0
- package/dist/src/server/GG_WS_CONNECTION.d.ts +12 -0
- package/dist/src/server/GG_WS_CONNECTION.d.ts.map +1 -0
- package/dist/src/server/GG_WS_CONNECTION.js +8 -0
- package/dist/src/server/GG_WS_CONNECTION.js.map +1 -0
- package/dist/src/server/GG_WS_MESSAGE.d.ts +10 -0
- package/dist/src/server/GG_WS_MESSAGE.d.ts.map +1 -0
- package/dist/src/server/GG_WS_MESSAGE.js +7 -0
- package/dist/src/server/GG_WS_MESSAGE.js.map +1 -0
- package/dist/src/socket/GGSocket.d.ts +81 -0
- package/dist/src/socket/GGSocket.d.ts.map +1 -0
- package/dist/src/socket/GGSocket.js +315 -0
- package/dist/src/socket/GGSocket.js.map +1 -0
- package/dist/src/socket/SocketAdapter.d.ts +13 -0
- package/dist/src/socket/SocketAdapter.d.ts.map +1 -0
- package/dist/src/socket/SocketAdapter.js +2 -0
- package/dist/src/socket/SocketAdapter.js.map +1 -0
- package/dist/src/socket/SocketMessage.d.ts +47 -0
- package/dist/src/socket/SocketMessage.d.ts.map +1 -0
- package/dist/src/socket/SocketMessage.js +51 -0
- package/dist/src/socket/SocketMessage.js.map +1 -0
- package/dist/src/socket/WebSocketTypes.d.ts +18 -0
- package/dist/src/socket/WebSocketTypes.d.ts.map +1 -0
- package/dist/src/socket/WebSocketTypes.js +5 -0
- package/dist/src/socket/WebSocketTypes.js.map +1 -0
- package/dist/src/socket/utils/PendingRequestsMap.d.ts +32 -0
- package/dist/src/socket/utils/PendingRequestsMap.d.ts.map +1 -0
- package/dist/src/socket/utils/PendingRequestsMap.js +104 -0
- package/dist/src/socket/utils/PendingRequestsMap.js.map +1 -0
- package/dist/src/tsconfig.json +17 -0
- package/dist/testkit/client/GGSocketCall.d.ts +37 -0
- package/dist/testkit/client/GGSocketCall.d.ts.map +1 -0
- package/dist/testkit/client/GGSocketCall.js +44 -0
- package/dist/testkit/client/GGSocketCall.js.map +1 -0
- package/dist/testkit/client/GGWebSocketSchema.callOn.d.ts +70 -0
- package/dist/testkit/client/GGWebSocketSchema.callOn.d.ts.map +1 -0
- package/dist/testkit/client/GGWebSocketSchema.callOn.js +135 -0
- package/dist/testkit/client/GGWebSocketSchema.callOn.js.map +1 -0
- package/dist/testkit/index-testkit.d.ts +4 -0
- package/dist/testkit/index-testkit.d.ts.map +1 -0
- package/dist/testkit/index-testkit.js +3 -0
- package/dist/testkit/index-testkit.js.map +1 -0
- package/dist/tsconfig.publish.tsbuildinfo +1 -0
- package/package.json +74 -0
- package/src/adapter/BrowserSocketAdapter.ts +63 -0
- package/src/adapter/NodeSocketAdapter.ts +67 -0
- package/src/adapter/getDefaultAdapter.ts +14 -0
- package/src/client/GGSocketClient.ts +25 -0
- package/src/client/GGSocketPool.ts +244 -0
- package/src/index-browser.ts +21 -0
- package/src/index-node.ts +28 -0
- package/src/schema/GGWebSocketMiddleware.ts +43 -0
- package/src/schema/GGWebSocketSchema.ts +57 -0
- package/src/schema/webSocketSchema.ts +109 -0
- package/src/server/GGSocketServer.ts +217 -0
- package/src/server/GGWebSocketMetrics.ts +58 -0
- package/src/server/GGWebSocketSchema.startServer.ts +136 -0
- package/src/server/GG_WS_CONNECTION.ts +10 -0
- package/src/server/GG_WS_MESSAGE.ts +9 -0
- package/src/socket/GGSocket.ts +394 -0
- package/src/socket/SocketAdapter.ts +21 -0
- package/src/socket/SocketMessage.ts +97 -0
- package/src/socket/WebSocketTypes.ts +19 -0
- package/src/socket/utils/PendingRequestsMap.ts +128 -0
- package/src/tsconfig.json +17 -0
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
export const DELIMITER = ":";
|
|
2
|
+
// Message types (single character for fast type checking)
|
|
3
|
+
export var MessageType;
|
|
4
|
+
(function (MessageType) {
|
|
5
|
+
MessageType["HANDSHAKE"] = "h";
|
|
6
|
+
MessageType["HANDSHAKE_OK"] = "k";
|
|
7
|
+
MessageType["HANDSHAKE_ERR"] = "x";
|
|
8
|
+
MessageType["MSG"] = "m";
|
|
9
|
+
MessageType["REQ"] = "r";
|
|
10
|
+
MessageType["RES"] = "s";
|
|
11
|
+
})(MessageType || (MessageType = {}));
|
|
12
|
+
export class Message {
|
|
13
|
+
static create(type, path, id, data) {
|
|
14
|
+
const dataStr = data !== undefined ? JSON.stringify(data) : "";
|
|
15
|
+
return type + DELIMITER + String(path) + DELIMITER + (id || "") + DELIMITER + dataStr;
|
|
16
|
+
}
|
|
17
|
+
static parse(msg) {
|
|
18
|
+
if (!msg) {
|
|
19
|
+
return undefined;
|
|
20
|
+
}
|
|
21
|
+
const parts = String(msg).split(DELIMITER);
|
|
22
|
+
// Extract the first 4 parts (type, path, id) and everything else is data
|
|
23
|
+
const type = parts[0];
|
|
24
|
+
const path = parts[1];
|
|
25
|
+
const id = parts[2];
|
|
26
|
+
const data = parts.length > 3 ? parts.slice(3).join(DELIMITER) : undefined;
|
|
27
|
+
// Handshake messages don't require path
|
|
28
|
+
const isHandshake = type === MessageType.HANDSHAKE ||
|
|
29
|
+
type === MessageType.HANDSHAKE_OK ||
|
|
30
|
+
type === MessageType.HANDSHAKE_ERR;
|
|
31
|
+
if (!type || (!isHandshake && !path)) {
|
|
32
|
+
return undefined;
|
|
33
|
+
}
|
|
34
|
+
let dataParsed = undefined;
|
|
35
|
+
if (data) {
|
|
36
|
+
try {
|
|
37
|
+
dataParsed = JSON.parse(data);
|
|
38
|
+
}
|
|
39
|
+
catch (e) {
|
|
40
|
+
// If JSON parse fails, keep as undefined
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return {
|
|
44
|
+
type: type,
|
|
45
|
+
path,
|
|
46
|
+
id: (id || undefined),
|
|
47
|
+
data: dataParsed
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=SocketMessage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SocketMessage.js","sourceRoot":"","sources":["../../../src/socket/SocketMessage.ts"],"names":[],"mappings":"AAGA,MAAM,CAAC,MAAM,SAAS,GAAG,GAAG,CAAA;AAE5B,0DAA0D;AAC1D,MAAM,CAAN,IAAY,WAOX;AAPD,WAAY,WAAW;IACnB,8BAAe,CAAA;IACf,iCAAkB,CAAA;IAClB,kCAAmB,CAAA;IACnB,wBAAS,CAAA;IACT,wBAAS,CAAA;IACT,wBAAS,CAAA;AACb,CAAC,EAPW,WAAW,KAAX,WAAW,QAOtB;AAyCD,MAAM,OAAO,OAAO;IAET,MAAM,CAAC,MAAM,CAAC,IAAiB,EAAE,IAAY,EAAE,EAA0B,EAAE,IAAS;QACvF,MAAM,OAAO,GAAG,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QAC/D,OAAO,IAAI,GAAG,SAAS,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,SAAS,GAAG,CAAC,EAAE,IAAI,EAAE,CAAC,GAAG,SAAS,GAAG,OAAO,CAAC;IAC1F,CAAC;IAEM,MAAM,CAAC,KAAK,CAAC,GAAY;QAC5B,IAAI,CAAC,GAAG,EAAE,CAAC;YACP,OAAO,SAAS,CAAC;QACrB,CAAC;QACD,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;QAE3C,yEAAyE;QACzE,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QACtB,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QACtB,MAAM,EAAE,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QACpB,MAAM,IAAI,GAAG,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QAE3E,wCAAwC;QACxC,MAAM,WAAW,GAAG,IAAI,KAAK,WAAW,CAAC,SAAS;YAC9C,IAAI,KAAK,WAAW,CAAC,YAAY;YACjC,IAAI,KAAK,WAAW,CAAC,aAAa,CAAC;QAEvC,IAAI,CAAC,IAAI,IAAI,CAAC,CAAC,WAAW,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YACnC,OAAO,SAAS,CAAC;QACrB,CAAC;QACD,IAAI,UAAU,GAAQ,SAAS,CAAC;QAChC,IAAI,IAAI,EAAE,CAAC;YACP,IAAI,CAAC;gBACD,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YAClC,CAAC;YAAC,OAAO,CAAC,EAAE,CAAC;gBACT,yCAAyC;YAC7C,CAAC;QACL,CAAC;QACD,OAAO;YACH,IAAI,EAAE,IAAmB;YACzB,IAAI;YACJ,EAAE,EAAE,CAAC,EAAE,IAAI,SAAS,CAAQ;YAC5B,IAAI,EAAE,UAAU;SACL,CAAC;IACpB,CAAC;CACJ"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Type helpers for WebSocket connection handlers
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Incoming handler for clientToServer messages.
|
|
6
|
+
* Call .on() with handlers for each method.
|
|
7
|
+
*/
|
|
8
|
+
export type WebSocketIncoming<TClientToServer> = {
|
|
9
|
+
on(handlers: TClientToServer): void;
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* Outgoing interface for serverToClient messages.
|
|
13
|
+
* Includes all serverToClient methods plus onClose for lifecycle.
|
|
14
|
+
*/
|
|
15
|
+
export type WebSocketOutgoing<TServerToClient> = TServerToClient & {
|
|
16
|
+
onClose(callback: () => void): void;
|
|
17
|
+
};
|
|
18
|
+
//# sourceMappingURL=WebSocketTypes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WebSocketTypes.d.ts","sourceRoot":"","sources":["../../../src/socket/WebSocketTypes.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;;GAGG;AACH,MAAM,MAAM,iBAAiB,CAAC,eAAe,IAAI;IAC7C,EAAE,CAAC,QAAQ,EAAE,eAAe,GAAG,IAAI,CAAA;CACtC,CAAA;AAED;;;GAGG;AACH,MAAM,MAAM,iBAAiB,CAAC,eAAe,IAAI,eAAe,GAAG;IAC/D,OAAO,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,IAAI,CAAA;CACtC,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WebSocketTypes.js","sourceRoot":"","sources":["../../../src/socket/WebSocketTypes.ts"],"names":[],"mappings":"AAAA;;GAEG"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { ERROR_JSON, OK_JSON, SERVER_ERROR } from "@grest-ts/schema";
|
|
2
|
+
export type tPendingMessageId = string & {
|
|
3
|
+
tt: never;
|
|
4
|
+
};
|
|
5
|
+
export declare class PendingRequestsMap {
|
|
6
|
+
private readonly requests;
|
|
7
|
+
private requestIdCounter;
|
|
8
|
+
private drainCallbacks;
|
|
9
|
+
/**
|
|
10
|
+
* Get the number of pending requests
|
|
11
|
+
*/
|
|
12
|
+
get size(): number;
|
|
13
|
+
/**
|
|
14
|
+
* Check if there are any pending requests
|
|
15
|
+
*/
|
|
16
|
+
hasPending(): boolean;
|
|
17
|
+
/**
|
|
18
|
+
* Wait for all pending requests to complete (resolve or reject).
|
|
19
|
+
* Uses event-driven notification instead of polling.
|
|
20
|
+
* @param timeoutMs - Maximum time to wait for pending requests
|
|
21
|
+
* @returns Promise that resolves when all pending requests are done or timeout is reached
|
|
22
|
+
*/
|
|
23
|
+
waitForPending(timeoutMs?: number): Promise<void>;
|
|
24
|
+
/**
|
|
25
|
+
* Notify drain callbacks if map is empty
|
|
26
|
+
*/
|
|
27
|
+
private notifyDrainIfEmpty;
|
|
28
|
+
create(path: string, timeoutMs: number, callback: (id: tPendingMessageId, waitForResponsePromise: Promise<any>) => Promise<any>): Promise<any>;
|
|
29
|
+
resolve(requestId: tPendingMessageId, value: OK_JSON<any> | ERROR_JSON): boolean;
|
|
30
|
+
rejectAll(error: typeof SERVER_ERROR.infer): void;
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=PendingRequestsMap.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PendingRequestsMap.d.ts","sourceRoot":"","sources":["../../../../src/socket/utils/PendingRequestsMap.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,UAAU,EAAE,OAAO,EAAE,YAAY,EAAC,MAAM,kBAAkB,CAAC;AASnE,MAAM,MAAM,iBAAiB,GAAG,MAAM,GAAG;IAAE,EAAE,EAAE,KAAK,CAAA;CAAE,CAAC;AAEvD,qBAAa,kBAAkB;IAC3B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAqD;IAC9E,OAAO,CAAC,gBAAgB,CAAa;IAErC,OAAO,CAAC,cAAc,CAAyB;IAE/C;;OAEG;IACH,IAAW,IAAI,IAAI,MAAM,CAExB;IAED;;OAEG;IACI,UAAU,IAAI,OAAO;IAI5B;;;;;OAKG;IACI,cAAc,CAAC,SAAS,GAAE,MAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IA0B9D;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAQnB,MAAM,CACT,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,CAAC,EAAE,EAAE,iBAAiB,EAAE,sBAAsB,EAAE,OAAO,CAAC,GAAG,CAAC,KAAK,OAAO,CAAC,GAAG,CAAC,GACxF,OAAO,CAAC,GAAG,CAAC;IA6BR,OAAO,CAAC,SAAS,EAAE,iBAAiB,EAAE,KAAK,EAAE,OAAO,CAAC,GAAG,CAAC,GAAG,UAAU,GAAG,OAAO;IAYhF,SAAS,CAAC,KAAK,EAAE,OAAO,YAAY,CAAC,KAAK,GAAG,IAAI;CAQ3D"}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { SERVER_ERROR } from "@grest-ts/schema";
|
|
2
|
+
export class PendingRequestsMap {
|
|
3
|
+
requests = new Map();
|
|
4
|
+
requestIdCounter = 1;
|
|
5
|
+
// Callbacks waiting for the map to drain (become empty)
|
|
6
|
+
drainCallbacks = [];
|
|
7
|
+
/**
|
|
8
|
+
* Get the number of pending requests
|
|
9
|
+
*/
|
|
10
|
+
get size() {
|
|
11
|
+
return this.requests.size;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Check if there are any pending requests
|
|
15
|
+
*/
|
|
16
|
+
hasPending() {
|
|
17
|
+
return this.requests.size > 0;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Wait for all pending requests to complete (resolve or reject).
|
|
21
|
+
* Uses event-driven notification instead of polling.
|
|
22
|
+
* @param timeoutMs - Maximum time to wait for pending requests
|
|
23
|
+
* @returns Promise that resolves when all pending requests are done or timeout is reached
|
|
24
|
+
*/
|
|
25
|
+
waitForPending(timeoutMs = 5000) {
|
|
26
|
+
if (this.requests.size === 0) {
|
|
27
|
+
return Promise.resolve();
|
|
28
|
+
}
|
|
29
|
+
return new Promise((resolve) => {
|
|
30
|
+
const cleanup = () => {
|
|
31
|
+
clearTimeout(timeout);
|
|
32
|
+
const idx = this.drainCallbacks.indexOf(onDrain);
|
|
33
|
+
if (idx !== -1)
|
|
34
|
+
this.drainCallbacks.splice(idx, 1);
|
|
35
|
+
};
|
|
36
|
+
const onDrain = () => {
|
|
37
|
+
cleanup();
|
|
38
|
+
resolve();
|
|
39
|
+
};
|
|
40
|
+
const timeout = setTimeout(() => {
|
|
41
|
+
cleanup();
|
|
42
|
+
resolve(); // Resolve on timeout (caller checks hasPending)
|
|
43
|
+
}, timeoutMs);
|
|
44
|
+
this.drainCallbacks.push(onDrain);
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Notify drain callbacks if map is empty
|
|
49
|
+
*/
|
|
50
|
+
notifyDrainIfEmpty() {
|
|
51
|
+
if (this.requests.size === 0 && this.drainCallbacks.length > 0) {
|
|
52
|
+
const callbacks = [...this.drainCallbacks];
|
|
53
|
+
this.drainCallbacks = [];
|
|
54
|
+
callbacks.forEach(cb => cb());
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
create(path, timeoutMs, callback) {
|
|
58
|
+
const requestId = String(this.requestIdCounter++);
|
|
59
|
+
const reqPromise = new Promise((resolve, reject) => {
|
|
60
|
+
const timeout = setTimeout(() => {
|
|
61
|
+
this.requests.delete(requestId);
|
|
62
|
+
this.notifyDrainIfEmpty();
|
|
63
|
+
reject(new SERVER_ERROR({
|
|
64
|
+
displayMessage: 'Request timeout',
|
|
65
|
+
debugData: {
|
|
66
|
+
timeout: timeoutMs,
|
|
67
|
+
}
|
|
68
|
+
}));
|
|
69
|
+
}, timeoutMs);
|
|
70
|
+
this.requests.set(requestId, { resolve, reject, timeout, path });
|
|
71
|
+
});
|
|
72
|
+
return callback(requestId, reqPromise)
|
|
73
|
+
.catch((error) => {
|
|
74
|
+
// If callback throws an error, clean up the pending request
|
|
75
|
+
const pending = this.requests.get(requestId);
|
|
76
|
+
if (pending) {
|
|
77
|
+
clearTimeout(pending.timeout);
|
|
78
|
+
this.requests.delete(requestId);
|
|
79
|
+
this.notifyDrainIfEmpty();
|
|
80
|
+
}
|
|
81
|
+
throw error;
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
resolve(requestId, value) {
|
|
85
|
+
const pending = this.requests.get(requestId);
|
|
86
|
+
if (!pending) {
|
|
87
|
+
throw new Error('Pending request not found: ' + requestId);
|
|
88
|
+
}
|
|
89
|
+
clearTimeout(pending.timeout);
|
|
90
|
+
this.requests.delete(requestId);
|
|
91
|
+
pending.resolve(value);
|
|
92
|
+
this.notifyDrainIfEmpty();
|
|
93
|
+
return true;
|
|
94
|
+
}
|
|
95
|
+
rejectAll(error) {
|
|
96
|
+
this.requests.forEach((pending) => {
|
|
97
|
+
clearTimeout(pending.timeout);
|
|
98
|
+
pending.resolve(error.toJSON());
|
|
99
|
+
});
|
|
100
|
+
this.requests.clear();
|
|
101
|
+
this.notifyDrainIfEmpty();
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
//# sourceMappingURL=PendingRequestsMap.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PendingRequestsMap.js","sourceRoot":"","sources":["../../../../src/socket/utils/PendingRequestsMap.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Test action for WebSocket calls.
|
|
3
|
+
*
|
|
4
|
+
* Handles client-to-server WebSocket messages with proper test action
|
|
5
|
+
* lifecycle (interceptors, expectations, logging).
|
|
6
|
+
*/
|
|
7
|
+
import { ERROR, VALIDATION_ERROR, ValidationIssueJson } from "@grest-ts/schema";
|
|
8
|
+
import { GGTestAction, tActionRawData } from "@grest-ts/testkit";
|
|
9
|
+
import { ConstructorOf } from "@grest-ts/common";
|
|
10
|
+
import { GGSocket } from "../../src/socket/GGSocket";
|
|
11
|
+
export declare class GGSocketCall<InputData, SuccessData, ErrorsUnion extends ERROR<any, any>> extends GGTestAction<SuccessData> {
|
|
12
|
+
private readonly socket;
|
|
13
|
+
private readonly path;
|
|
14
|
+
private readonly request;
|
|
15
|
+
private readonly hasResponse;
|
|
16
|
+
private _validatingError;
|
|
17
|
+
constructor(socket: GGSocket, path: string, request: any, hasResponse?: boolean);
|
|
18
|
+
toBeError<Type extends ConstructorOf<ErrorsUnion>>(type: Type): GGSocketCall<InputData, ExtractSocketErrorData<Type, ErrorsUnion, InputData>, never>;
|
|
19
|
+
protected executeAction(): Promise<tActionRawData>;
|
|
20
|
+
protected processRawResponse(result: tActionRawData): Promise<SuccessData>;
|
|
21
|
+
}
|
|
22
|
+
export type ExtractSocketErrorData<Type extends {
|
|
23
|
+
new (...args: any[]): any;
|
|
24
|
+
}, Union, InputData = unknown> = Union extends InstanceType<Type> ? Union extends typeof VALIDATION_ERROR.infer ? SocketValidationErrorsObject<InputData> : Union extends ERROR<any, infer Data> ? Data : never : never;
|
|
25
|
+
export type SocketValidationFieldError = string[] & {
|
|
26
|
+
__issue?: ValidationIssueJson;
|
|
27
|
+
};
|
|
28
|
+
export type SocketValidationErrorsObject<T> = T extends object ? {
|
|
29
|
+
[K in keyof T]?: SocketValidationFieldError | {
|
|
30
|
+
__issue?: ValidationIssueJson;
|
|
31
|
+
};
|
|
32
|
+
} : {
|
|
33
|
+
[key: string]: SocketValidationFieldError | {
|
|
34
|
+
__issue?: ValidationIssueJson;
|
|
35
|
+
};
|
|
36
|
+
};
|
|
37
|
+
//# sourceMappingURL=GGSocketCall.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GGSocketCall.d.ts","sourceRoot":"","sources":["../../../testkit/client/GGSocketCall.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAC,KAAK,EAAE,gBAAgB,EAAE,mBAAmB,EAAC,MAAM,kBAAkB,CAAC;AAC9E,OAAO,EAAC,YAAY,EAAsB,cAAc,EAAC,MAAM,mBAAmB,CAAC;AACnF,OAAO,EAAC,aAAa,EAAC,MAAM,kBAAkB,CAAC;AAE/C,OAAO,EAAC,QAAQ,EAAC,MAAM,2BAA2B,CAAC;AAGnD,qBAAa,YAAY,CAAC,SAAS,EAAE,WAAW,EAAE,WAAW,SAAS,KAAK,CAAC,GAAG,EAAE,GAAG,CAAC,CAAE,SAAQ,YAAY,CAAC,WAAW,CAAC;IAEpH,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAW;IAClC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAS;IAC9B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAM;IAC9B,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAU;IAEtC,OAAO,CAAC,gBAAgB,CAAiC;gBAE7C,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,EAAE,WAAW,GAAE,OAAc;IAkB9E,SAAS,CAAC,IAAI,SAAS,aAAa,CAAC,WAAW,CAAC,EAAE,IAAI,EAAE,IAAI,GAAG,YAAY,CAAC,SAAS,EAAE,sBAAsB,CAAC,IAAI,EAAE,WAAW,EAAE,SAAS,CAAC,EAAE,KAAK,CAAC;cAM3I,aAAa,IAAI,OAAO,CAAC,cAAc,CAAC;IAIxD,SAAS,CAAC,kBAAkB,CAAC,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,WAAW,CAAC;CAG7E;AAED,MAAM,MAAM,sBAAsB,CAAC,IAAI,SAAS;IAAE,KAAI,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,GAAG,CAAA;CAAE,EAAE,KAAK,EAAE,SAAS,GAAG,OAAO,IACpG,KAAK,SAAS,YAAY,CAAC,IAAI,CAAC,GAC1B,KAAK,SAAS,OAAO,gBAAgB,CAAC,KAAK,GACvC,4BAA4B,CAAC,SAAS,CAAC,GACvC,KAAK,SAAS,KAAK,CAAC,GAAG,EAAE,MAAM,IAAI,CAAC,GAChC,IAAI,GACJ,KAAK,GACb,KAAK,CAAC;AAEhB,MAAM,MAAM,0BAA0B,GAAG,MAAM,EAAE,GAAG;IAAE,OAAO,CAAC,EAAE,mBAAmB,CAAA;CAAE,CAAA;AAErF,MAAM,MAAM,4BAA4B,CAAC,CAAC,IAAI,CAAC,SAAS,MAAM,GACxD;KAAG,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,EAAE,0BAA0B,GAAG;QAAE,OAAO,CAAC,EAAE,mBAAmB,CAAA;KAAE;CAAE,GACnF;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,0BAA0B,GAAG;QAAE,OAAO,CAAC,EAAE,mBAAmB,CAAA;KAAE,CAAA;CAAE,CAAA"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Test action for WebSocket calls.
|
|
3
|
+
*
|
|
4
|
+
* Handles client-to-server WebSocket messages with proper test action
|
|
5
|
+
* lifecycle (interceptors, expectations, logging).
|
|
6
|
+
*/
|
|
7
|
+
import { GGTestAction } from "@grest-ts/testkit";
|
|
8
|
+
import { parseContractResponse } from "@grest-ts/http/testkit";
|
|
9
|
+
import { GGContext } from "@grest-ts/context";
|
|
10
|
+
export class GGSocketCall extends GGTestAction {
|
|
11
|
+
socket;
|
|
12
|
+
path;
|
|
13
|
+
request;
|
|
14
|
+
hasResponse;
|
|
15
|
+
_validatingError;
|
|
16
|
+
constructor(socket, path, request, hasResponse = true) {
|
|
17
|
+
const config = {
|
|
18
|
+
noResponse: !hasResponse,
|
|
19
|
+
logData: {
|
|
20
|
+
message: "[WS " + path + "]",
|
|
21
|
+
request: request
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
// Socket context works differently. The socket itself already runs in a context when it connected.
|
|
25
|
+
// Individual calls can't update context - it's bound at connection time.
|
|
26
|
+
super(new GGContext("SocketCall"), config);
|
|
27
|
+
this.socket = socket;
|
|
28
|
+
this.path = path;
|
|
29
|
+
this.request = request;
|
|
30
|
+
this.hasResponse = hasResponse;
|
|
31
|
+
}
|
|
32
|
+
toBeError(type) {
|
|
33
|
+
this._validatingError = type;
|
|
34
|
+
this.responseExpectations.flush();
|
|
35
|
+
return this;
|
|
36
|
+
}
|
|
37
|
+
async executeAction() {
|
|
38
|
+
return this.socket.send(this.path, this.request, this.hasResponse);
|
|
39
|
+
}
|
|
40
|
+
processRawResponse(result) {
|
|
41
|
+
return parseContractResponse(result, this._validatingError);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=GGSocketCall.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GGSocketCall.js","sourceRoot":"","sources":["../../../testkit/client/GGSocketCall.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAC,YAAY,EAAqC,MAAM,mBAAmB,CAAC;AAEnF,OAAO,EAAC,qBAAqB,EAAC,MAAM,wBAAwB,CAAC;AAE7D,OAAO,EAAC,SAAS,EAAC,MAAM,mBAAmB,CAAC;AAE5C,MAAM,OAAO,YAA0E,SAAQ,YAAyB;IAEnG,MAAM,CAAW;IACjB,IAAI,CAAS;IACb,OAAO,CAAM;IACb,WAAW,CAAU;IAE9B,gBAAgB,CAAiC;IAEzD,YAAY,MAAgB,EAAE,IAAY,EAAE,OAAY,EAAE,cAAuB,IAAI;QACjF,MAAM,MAAM,GAAuB;YAC/B,UAAU,EAAE,CAAC,WAAW;YACxB,OAAO,EAAE;gBACL,OAAO,EAAE,MAAM,GAAG,IAAI,GAAG,GAAG;gBAC5B,OAAO,EAAE,OAAO;aACnB;SACJ,CAAC;QACF,mGAAmG;QACnG,yEAAyE;QACzE,KAAK,CAAC,IAAI,SAAS,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC,CAAC;QAE3C,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,WAAW,GAAG,WAAW,CAAC;IACnC,CAAC;IAEM,SAAS,CAA0C,IAAU;QAChE,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC;QAC7B,IAAI,CAAC,oBAAoB,CAAC,KAAK,EAAE,CAAC;QAClC,OAAO,IAAW,CAAC;IACvB,CAAC;IAES,KAAK,CAAC,aAAa;QACzB,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;IACvE,CAAC;IAES,kBAAkB,CAAC,MAAsB;QAC/C,OAAO,qBAAqB,CAAC,MAAM,EAAE,IAAI,CAAC,gBAAgB,CAAC,CAAC;IAChE,CAAC;CACJ"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CALL_ON_FACTORY implementation for GGWebSocketSchema.
|
|
3
|
+
*
|
|
4
|
+
* Enables callOn(WebSocketApi) to work by providing WebSocket transport.
|
|
5
|
+
* Returns properly typed GGSocketCall for each clientToServer method,
|
|
6
|
+
* plus connect() for lifecycle and mock for serverToClient events.
|
|
7
|
+
*/
|
|
8
|
+
import type { GGSocket } from "../../src/socket/GGSocket";
|
|
9
|
+
import { GGSocketCall } from "./GGSocketCall";
|
|
10
|
+
import { CALL_ON_FACTORY, GGCallInterceptor, GGCallInterceptorConfig, GGCallOnFactory, GGMockWith, GGTestRunner } from "@grest-ts/testkit";
|
|
11
|
+
import { GGContext } from "@grest-ts/context";
|
|
12
|
+
import { GGContractMethod, GGPromise } from "@grest-ts/schema";
|
|
13
|
+
/**
|
|
14
|
+
* Maps clientToServer methods to GGSocketCall.
|
|
15
|
+
* TClientToServer is GGContractClient type (functions), so we extract types from function signatures.
|
|
16
|
+
* Uses Parameters<> to distinguish between functions with and without arguments.
|
|
17
|
+
*/
|
|
18
|
+
type SocketClientMethods<TClientToServer> = {
|
|
19
|
+
[K in keyof TClientToServer]: TClientToServer[K] extends (...args: any[]) => GGPromise<infer Output, infer Errors> ? Parameters<TClientToServer[K]> extends [infer Input] ? (data: Input) => GGSocketCall<Input, Output, Errors> : Parameters<TClientToServer[K]> extends [] ? () => GGSocketCall<void, Output, Errors> : never : never;
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* Maps serverToClient methods to mock interceptors.
|
|
23
|
+
* TServerToClient is GGContractClient type (functions), so we extract types from function signatures.
|
|
24
|
+
* Uses Parameters<> to distinguish between functions with and without arguments.
|
|
25
|
+
*/
|
|
26
|
+
type SocketMockMethods<TServerToClient> = {
|
|
27
|
+
[K in keyof TServerToClient]: TServerToClient[K] extends (...args: any[]) => GGPromise<infer Output, any> ? Parameters<TServerToClient[K]> extends [infer Input] ? GGMockWith<Input, Output, never> : Parameters<TServerToClient[K]> extends [] ? GGMockWith<void, Output, never> : never : never;
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* Full WebSocket call map - clientToServer methods + lifecycle + mock.
|
|
31
|
+
* Both type parameters are GGContractClient types (function signatures).
|
|
32
|
+
*/
|
|
33
|
+
export type GGSocketCallMap<TClientToServer, TServerToClient> = SocketClientMethods<TClientToServer> & {
|
|
34
|
+
/** Connect to the WebSocket server. Must be called before sending messages. */
|
|
35
|
+
connect(): Promise<void>;
|
|
36
|
+
/** Disconnect from the WebSocket server. */
|
|
37
|
+
disconnect(): Promise<void>;
|
|
38
|
+
/** Mock handlers for serverToClient messages. */
|
|
39
|
+
mock: SocketMockMethods<TServerToClient>;
|
|
40
|
+
};
|
|
41
|
+
declare module "../../src/schema/GGWebSocketSchema" {
|
|
42
|
+
interface GGWebSocketSchema<TClientToServer, TServerToClient, TContext, TQuery, TClientToServerImpl> extends GGCallOnFactory {
|
|
43
|
+
[CALL_ON_FACTORY](ctx: GGContext): GGSocketCallMap<TClientToServer, TServerToClient>;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
export interface SocketServerToClientInterceptorConfig extends GGCallInterceptorConfig {
|
|
47
|
+
socket: GGSocket;
|
|
48
|
+
path: string;
|
|
49
|
+
expectError?: any;
|
|
50
|
+
contract?: GGContractMethod;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Interceptor for serverToClient WebSocket messages.
|
|
54
|
+
*
|
|
55
|
+
* Registers a handler on the socket to intercept incoming server messages.
|
|
56
|
+
* Used for mocking/verifying server-to-client events in tests.
|
|
57
|
+
*/
|
|
58
|
+
export declare class GGSocketServerToClientInterceptor extends GGCallInterceptor {
|
|
59
|
+
readonly socket: GGSocket;
|
|
60
|
+
readonly path: string;
|
|
61
|
+
protected readonly expectError?: any;
|
|
62
|
+
protected readonly contract?: GGContractMethod;
|
|
63
|
+
constructor(test: GGTestRunner, config: SocketServerToClientInterceptorConfig);
|
|
64
|
+
getKey(): string;
|
|
65
|
+
protected doRegister(): void;
|
|
66
|
+
protected doUnregister(): void;
|
|
67
|
+
protected parseResponseData(result: any): any;
|
|
68
|
+
}
|
|
69
|
+
export {};
|
|
70
|
+
//# sourceMappingURL=GGWebSocketSchema.callOn.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GGWebSocketSchema.callOn.d.ts","sourceRoot":"","sources":["../../../testkit/client/GGWebSocketSchema.callOn.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CALL_ON_FACTORY implementation for GGWebSocketSchema.
|
|
3
|
+
*
|
|
4
|
+
* Enables callOn(WebSocketApi) to work by providing WebSocket transport.
|
|
5
|
+
* Returns properly typed GGSocketCall for each clientToServer method,
|
|
6
|
+
* plus connect() for lifecycle and mock for serverToClient events.
|
|
7
|
+
*/
|
|
8
|
+
import { GGSocketCall } from "./GGSocketCall.js";
|
|
9
|
+
import { CALL_ON_FACTORY, GG_TEST_RUNNER, GGCallInterceptor, GGMockWith, GGTestError } from "@grest-ts/testkit";
|
|
10
|
+
import { withTimeout } from "@grest-ts/common";
|
|
11
|
+
import { GGSocketPool } from "../../src/client/GGSocketPool.js";
|
|
12
|
+
import { GGContext } from "@grest-ts/context";
|
|
13
|
+
import { GG_TRACE } from "@grest-ts/trace";
|
|
14
|
+
import { GGWebSocketSchema } from "../../src/schema/GGWebSocketSchema.js";
|
|
15
|
+
import { GGPromise } from "@grest-ts/schema";
|
|
16
|
+
import { parseContractResponse } from "@grest-ts/http/testkit";
|
|
17
|
+
// ============================================================================
|
|
18
|
+
// Implementation
|
|
19
|
+
// ============================================================================
|
|
20
|
+
GGWebSocketSchema.prototype[CALL_ON_FACTORY] = function (ctx) {
|
|
21
|
+
const contract = this.contract;
|
|
22
|
+
const name = this.name;
|
|
23
|
+
const middlewares = this.middlewares || [];
|
|
24
|
+
if (!contract) {
|
|
25
|
+
throw new Error(`WebSocketSchema "${name}" has no contract.`);
|
|
26
|
+
}
|
|
27
|
+
const state = { socket: undefined };
|
|
28
|
+
const normalizedPath = this.path.startsWith('/') ? this.path : '/' + this.path;
|
|
29
|
+
// Create mock handlers for serverToClient methods
|
|
30
|
+
const serverToClientMethods = contract.serverToClient.methods;
|
|
31
|
+
const mock = {};
|
|
32
|
+
for (const methodName of Object.keys(serverToClientMethods)) {
|
|
33
|
+
const methodContract = serverToClientMethods[methodName];
|
|
34
|
+
Object.defineProperty(mock, methodName, {
|
|
35
|
+
get() {
|
|
36
|
+
if (!state.socket) {
|
|
37
|
+
throw new Error("Socket is not connected! Call connect() first.");
|
|
38
|
+
}
|
|
39
|
+
return new GGMockWith(GGSocketServerToClientInterceptor, {
|
|
40
|
+
socket: state.socket,
|
|
41
|
+
path: `${name}.${methodName}`,
|
|
42
|
+
contract: methodContract
|
|
43
|
+
});
|
|
44
|
+
},
|
|
45
|
+
enumerable: true
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
// Build the API object
|
|
49
|
+
const api = {
|
|
50
|
+
connect: async () => {
|
|
51
|
+
state.socket = await new GGContext("SocketConnect").run(async () => {
|
|
52
|
+
GG_TRACE.init();
|
|
53
|
+
const runner = GG_TEST_RUNNER.get();
|
|
54
|
+
const domain = runner.discoveryServer.getRoutingUrl(name);
|
|
55
|
+
// Run socket connection inside ctx so middlewares can read context values
|
|
56
|
+
const socket = await ctx.run(() => withTimeout(GGSocketPool.getOrConnect({
|
|
57
|
+
domain: domain,
|
|
58
|
+
path: normalizedPath,
|
|
59
|
+
middlewares: middlewares
|
|
60
|
+
}), 5000, `Socket connection timeout. Tried to connect to: ${domain}${normalizedPath}`));
|
|
61
|
+
// Set handler for unexpected messages
|
|
62
|
+
socket.setUnknownMessageHandler((messagePath, data) => {
|
|
63
|
+
throw new GGTestError({
|
|
64
|
+
test: "Unexpected socket message received: " + messagePath,
|
|
65
|
+
expected: "-",
|
|
66
|
+
received: "Called",
|
|
67
|
+
extra: "All socket messages must be mocked/expected in tests.\n" +
|
|
68
|
+
"Did you forget to add .with(api.mock." + messagePath.split('.').pop() + ".toMatchObject(...)) to your test?"
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
return socket;
|
|
72
|
+
});
|
|
73
|
+
},
|
|
74
|
+
disconnect: async () => {
|
|
75
|
+
if (state.socket) {
|
|
76
|
+
await state.socket.close();
|
|
77
|
+
state.socket = undefined;
|
|
78
|
+
}
|
|
79
|
+
},
|
|
80
|
+
mock
|
|
81
|
+
};
|
|
82
|
+
// Add clientToServer methods
|
|
83
|
+
const clientToServerMethods = contract.clientToServer.methods;
|
|
84
|
+
for (const methodName of Object.keys(clientToServerMethods)) {
|
|
85
|
+
const methodContract = clientToServerMethods[methodName];
|
|
86
|
+
api[methodName] = (data) => {
|
|
87
|
+
if (!state.socket) {
|
|
88
|
+
throw new Error("Socket is not connected! Call connect() first.");
|
|
89
|
+
}
|
|
90
|
+
const hasResponse = methodContract.success !== undefined;
|
|
91
|
+
return new GGSocketCall(state.socket, `${name}.${methodName}`, data, hasResponse);
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
return api;
|
|
95
|
+
};
|
|
96
|
+
/**
|
|
97
|
+
* Interceptor for serverToClient WebSocket messages.
|
|
98
|
+
*
|
|
99
|
+
* Registers a handler on the socket to intercept incoming server messages.
|
|
100
|
+
* Used for mocking/verifying server-to-client events in tests.
|
|
101
|
+
*/
|
|
102
|
+
export class GGSocketServerToClientInterceptor extends GGCallInterceptor {
|
|
103
|
+
socket;
|
|
104
|
+
path;
|
|
105
|
+
expectError;
|
|
106
|
+
contract;
|
|
107
|
+
constructor(test, config) {
|
|
108
|
+
if (config.passThrough) {
|
|
109
|
+
throw new Error("Spy mode is not supported for socket interceptors. " +
|
|
110
|
+
"Sockets are meant for browser-to-server communication and spy does not make sense in tests, " +
|
|
111
|
+
"as the browser side is faked.");
|
|
112
|
+
}
|
|
113
|
+
super(test, config);
|
|
114
|
+
this.socket = config.socket;
|
|
115
|
+
this.path = config.path;
|
|
116
|
+
this.expectError = config.expectError;
|
|
117
|
+
this.contract = config.contract;
|
|
118
|
+
}
|
|
119
|
+
getKey() {
|
|
120
|
+
return this.path;
|
|
121
|
+
}
|
|
122
|
+
doRegister() {
|
|
123
|
+
this.socket.registerHandler({
|
|
124
|
+
path: this.path,
|
|
125
|
+
handler: (data) => new GGPromise(this.onRequest(data))
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
doUnregister() {
|
|
129
|
+
this.socket.unregisterHandler(this.path);
|
|
130
|
+
}
|
|
131
|
+
parseResponseData(result) {
|
|
132
|
+
return parseContractResponse(result, this.expectError);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
//# sourceMappingURL=GGWebSocketSchema.callOn.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GGWebSocketSchema.callOn.js","sourceRoot":"","sources":["../../../testkit/client/GGWebSocketSchema.callOn.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-testkit.d.ts","sourceRoot":"","sources":["../../testkit/index-testkit.ts"],"names":[],"mappings":"AAAA,cAAc,uBAAuB,CAAC;AACtC,YAAY,EAAC,eAAe,EAAC,MAAM,mCAAmC,CAAC;AACvE,OAAO,mCAAmC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-testkit.js","sourceRoot":"","sources":["../../testkit/index-testkit.ts"],"names":[],"mappings":"AAAA,cAAc,uBAAuB,CAAC;AAEtC,OAAO,mCAAmC,CAAC"}
|