@zimic/interceptor 1.5.2-canary.1 → 1.5.2-canary.3
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/dist/{chunk-6YD4TBYJ.js → chunk-7DXCXCFO.js} +60 -19
- package/dist/chunk-7DXCXCFO.js.map +1 -0
- package/dist/{chunk-MCLPYYCY.mjs → chunk-PHFZDUNS.mjs} +60 -19
- package/dist/chunk-PHFZDUNS.mjs.map +1 -0
- package/dist/cli.js +16 -16
- package/dist/cli.js.map +1 -1
- package/dist/cli.mjs +2 -2
- package/dist/cli.mjs.map +1 -1
- package/dist/http.js +17 -5
- package/dist/http.js.map +1 -1
- package/dist/http.mjs +17 -5
- package/dist/http.mjs.map +1 -1
- package/dist/server.js +6 -6
- package/dist/server.mjs +1 -1
- package/package.json +19 -12
- package/src/server/utils/fetch.ts +0 -1
- package/src/utils/webSocket/WebSocketHandler.ts +8 -1
- package/src/utils/webSocket/WebSocketServer.ts +58 -12
- package/src/utils/webSocket/constants.ts +7 -0
- package/src/utils/webSocket/types.ts +1 -2
- package/src/utils/webSocket.ts +2 -2
- package/src/ws/interceptorWorker/types/messages.ts +11 -0
- package/src/ws/utils/messageData.ts +122 -0
- package/dist/chunk-6YD4TBYJ.js.map +0 -1
- package/dist/chunk-MCLPYYCY.mjs.map +0 -1
package/dist/server.js
CHANGED
|
@@ -1,29 +1,29 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var chunk7DXCXCFO_js = require('./chunk-7DXCXCFO.js');
|
|
4
4
|
require('./chunk-DGUM43GV.js');
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
Object.defineProperty(exports, "DEFAULT_ACCESS_CONTROL_HEADERS", {
|
|
9
9
|
enumerable: true,
|
|
10
|
-
get: function () { return
|
|
10
|
+
get: function () { return chunk7DXCXCFO_js.DEFAULT_ACCESS_CONTROL_HEADERS; }
|
|
11
11
|
});
|
|
12
12
|
Object.defineProperty(exports, "DEFAULT_PREFLIGHT_STATUS_CODE", {
|
|
13
13
|
enumerable: true,
|
|
14
|
-
get: function () { return
|
|
14
|
+
get: function () { return chunk7DXCXCFO_js.DEFAULT_PREFLIGHT_STATUS_CODE; }
|
|
15
15
|
});
|
|
16
16
|
Object.defineProperty(exports, "NotRunningInterceptorServerError", {
|
|
17
17
|
enumerable: true,
|
|
18
|
-
get: function () { return
|
|
18
|
+
get: function () { return chunk7DXCXCFO_js.NotRunningInterceptorServerError_default; }
|
|
19
19
|
});
|
|
20
20
|
Object.defineProperty(exports, "RunningInterceptorServerError", {
|
|
21
21
|
enumerable: true,
|
|
22
|
-
get: function () { return
|
|
22
|
+
get: function () { return chunk7DXCXCFO_js.RunningInterceptorServerError_default; }
|
|
23
23
|
});
|
|
24
24
|
Object.defineProperty(exports, "createInterceptorServer", {
|
|
25
25
|
enumerable: true,
|
|
26
|
-
get: function () { return
|
|
26
|
+
get: function () { return chunk7DXCXCFO_js.createInterceptorServer; }
|
|
27
27
|
});
|
|
28
28
|
//# sourceMappingURL=server.js.map
|
|
29
29
|
//# sourceMappingURL=server.js.map
|
package/dist/server.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { DEFAULT_ACCESS_CONTROL_HEADERS, DEFAULT_PREFLIGHT_STATUS_CODE, NotRunningInterceptorServerError_default as NotRunningInterceptorServerError, RunningInterceptorServerError_default as RunningInterceptorServerError, createInterceptorServer } from './chunk-
|
|
1
|
+
export { DEFAULT_ACCESS_CONTROL_HEADERS, DEFAULT_PREFLIGHT_STATUS_CODE, NotRunningInterceptorServerError_default as NotRunningInterceptorServerError, RunningInterceptorServerError_default as RunningInterceptorServerError, createInterceptorServer } from './chunk-PHFZDUNS.mjs';
|
|
2
2
|
import './chunk-BJTO5JO5.mjs';
|
|
3
3
|
//# sourceMappingURL=server.mjs.map
|
|
4
4
|
//# sourceMappingURL=server.mjs.map
|
package/package.json
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
"api",
|
|
15
15
|
"static"
|
|
16
16
|
],
|
|
17
|
-
"version": "1.5.2-canary.
|
|
17
|
+
"version": "1.5.2-canary.3",
|
|
18
18
|
"homepage": "https://zimic.dev/docs/interceptor",
|
|
19
19
|
"repository": {
|
|
20
20
|
"type": "git",
|
|
@@ -80,6 +80,9 @@
|
|
|
80
80
|
},
|
|
81
81
|
"./package.json": "./package.json"
|
|
82
82
|
},
|
|
83
|
+
"browser": {
|
|
84
|
+
"msw/node": "msw/browser"
|
|
85
|
+
},
|
|
83
86
|
"scripts": {
|
|
84
87
|
"setup": "concurrently --names playwright,msw 'playwright install chromium' 'msw init ./public --no-save'",
|
|
85
88
|
"dev": "tsup --watch",
|
|
@@ -96,39 +99,43 @@
|
|
|
96
99
|
"postinstall": "node --enable-source-maps -e \"try{require('./dist/scripts/postinstall')}catch(error){console.error(error)}\""
|
|
97
100
|
},
|
|
98
101
|
"dependencies": {
|
|
99
|
-
"@whatwg-node/server": "0.
|
|
102
|
+
"@whatwg-node/server": "0.13.0",
|
|
100
103
|
"isomorphic-ws": "5.0.0",
|
|
101
104
|
"msw": "2.15.0",
|
|
102
105
|
"picocolors": "^1.1.1",
|
|
103
|
-
"ws": "8.
|
|
104
|
-
"yargs": "18.
|
|
105
|
-
"zod": "^4.5
|
|
106
|
+
"ws": "8.22.0",
|
|
107
|
+
"yargs": "18.2.0",
|
|
108
|
+
"zod": "^4.6.5"
|
|
106
109
|
},
|
|
107
110
|
"devDependencies": {
|
|
108
|
-
"@types/node": "^26.
|
|
111
|
+
"@types/node": "^26.6.3",
|
|
109
112
|
"@types/ws": "^8.18.1",
|
|
110
113
|
"@types/yargs": "^17.0.35",
|
|
111
114
|
"@typescript/native": "npm:typescript@^7.0.2",
|
|
112
|
-
"@vitest/browser": "^
|
|
113
|
-
"@vitest/browser-playwright": "^
|
|
114
|
-
"@vitest/coverage-istanbul": "^
|
|
115
|
+
"@vitest/browser": "^5.0.2",
|
|
116
|
+
"@vitest/browser-playwright": "^5.0.2",
|
|
117
|
+
"@vitest/coverage-istanbul": "^5.0.2",
|
|
115
118
|
"@zimic/eslint-config-node": "workspace:*",
|
|
116
119
|
"@zimic/lint-staged-config": "workspace:*",
|
|
117
120
|
"@zimic/tsconfig": "workspace:*",
|
|
118
121
|
"@zimic/utils": "workspace:*",
|
|
119
122
|
"concurrently": "^10.0.5",
|
|
120
123
|
"dotenv-cli": "^11.0.0",
|
|
121
|
-
"eslint": "^
|
|
122
|
-
"playwright": "^1.
|
|
124
|
+
"eslint": "^10.11.0",
|
|
125
|
+
"playwright": "^1.63.0",
|
|
123
126
|
"tsup": "^8.5.1",
|
|
124
127
|
"typescript": "npm:@typescript/typescript6@^6.0.2",
|
|
125
|
-
"vitest": "^
|
|
128
|
+
"vitest": "^5.0.2"
|
|
126
129
|
},
|
|
127
130
|
"peerDependencies": {
|
|
128
131
|
"@zimic/http": "workspace:^1.2.0",
|
|
132
|
+
"@zimic/ws": "workspace:^0.2.0-canary.0",
|
|
129
133
|
"typescript": "^5.0.0 || ^6.0.0 || ^7.0.0"
|
|
130
134
|
},
|
|
131
135
|
"peerDependenciesMeta": {
|
|
136
|
+
"@zimic/ws": {
|
|
137
|
+
"optional": true
|
|
138
|
+
},
|
|
132
139
|
"typescript": {
|
|
133
140
|
"optional": true
|
|
134
141
|
}
|
|
@@ -64,7 +64,12 @@ abstract class WebSocketHandler<Schema extends WebSocketSchema> {
|
|
|
64
64
|
};
|
|
65
65
|
socket.addEventListener('message', handleSocketMessage);
|
|
66
66
|
|
|
67
|
-
|
|
67
|
+
try {
|
|
68
|
+
await openPromise;
|
|
69
|
+
} catch (error) {
|
|
70
|
+
socket.removeEventListener('message', handleSocketMessage);
|
|
71
|
+
throw error;
|
|
72
|
+
}
|
|
68
73
|
|
|
69
74
|
/* istanbul ignore next -- @preserve
|
|
70
75
|
* It is difficult to reliably simulate socket errors in tests. */
|
|
@@ -87,6 +92,8 @@ abstract class WebSocketHandler<Schema extends WebSocketSchema> {
|
|
|
87
92
|
socket.addEventListener('close', handleSocketClose);
|
|
88
93
|
|
|
89
94
|
this.sockets.add(socket);
|
|
95
|
+
|
|
96
|
+
return handleSocketClose;
|
|
90
97
|
}
|
|
91
98
|
|
|
92
99
|
private handleSocketMessage = async (socket: ClientSocket, rawMessage: ClientSocket.MessageEvent) => {
|
|
@@ -4,29 +4,41 @@ import ClientSocket from 'isomorphic-ws';
|
|
|
4
4
|
|
|
5
5
|
import { closeServerSocket } from '@/utils/webSocket';
|
|
6
6
|
|
|
7
|
-
import { WebSocketControlMessage } from './constants';
|
|
7
|
+
import { WEB_SOCKET_CLOSE_CODES, WebSocketControlMessage } from './constants';
|
|
8
8
|
import { WebSocketSchema } from './types';
|
|
9
9
|
import WebSocketHandler from './WebSocketHandler';
|
|
10
10
|
|
|
11
11
|
const { WebSocketServer: ServerSocket } = ClientSocket;
|
|
12
12
|
|
|
13
|
+
function isSocketOpen(socket: ClientSocket) {
|
|
14
|
+
return socket.readyState === socket.OPEN;
|
|
15
|
+
}
|
|
16
|
+
|
|
13
17
|
export type WebSocketServerAuthenticate = (
|
|
14
18
|
socket: ClientSocket,
|
|
15
19
|
request: IncomingMessage,
|
|
16
20
|
) => PossiblePromise<{ isValid: true } | { isValid: false; message: string }>;
|
|
17
21
|
|
|
22
|
+
export type WebSocketServerConnectionHandler = (
|
|
23
|
+
socket: ClientSocket,
|
|
24
|
+
request: IncomingMessage,
|
|
25
|
+
) => PossiblePromise<{ handled: boolean }>;
|
|
26
|
+
|
|
18
27
|
interface WebSocketServerOptions {
|
|
19
28
|
httpServer: HttpServer;
|
|
20
29
|
socketTimeout?: number;
|
|
21
30
|
messageTimeout?: number;
|
|
22
31
|
authenticate?: WebSocketServerAuthenticate;
|
|
32
|
+
handleConnection?: WebSocketServerConnectionHandler;
|
|
23
33
|
}
|
|
24
34
|
|
|
25
35
|
class WebSocketServer<Schema extends WebSocketSchema> extends WebSocketHandler<Schema> {
|
|
26
36
|
private webSocketServer?: InstanceType<typeof ServerSocket>;
|
|
37
|
+
private isStopping = false;
|
|
27
38
|
|
|
28
39
|
private httpServer: HttpServer;
|
|
29
40
|
private authenticate?: WebSocketServerOptions['authenticate'];
|
|
41
|
+
private handleConnection?: WebSocketServerOptions['handleConnection'];
|
|
30
42
|
|
|
31
43
|
constructor(options: WebSocketServerOptions) {
|
|
32
44
|
super({
|
|
@@ -36,6 +48,7 @@ class WebSocketServer<Schema extends WebSocketSchema> extends WebSocketHandler<S
|
|
|
36
48
|
|
|
37
49
|
this.httpServer = options.httpServer;
|
|
38
50
|
this.authenticate = options.authenticate;
|
|
51
|
+
this.handleConnection = options.handleConnection;
|
|
39
52
|
}
|
|
40
53
|
|
|
41
54
|
get isRunning() {
|
|
@@ -54,19 +67,46 @@ class WebSocketServer<Schema extends WebSocketSchema> extends WebSocketHandler<S
|
|
|
54
67
|
});
|
|
55
68
|
|
|
56
69
|
webSocketServer.on('connection', async (socket, request) => {
|
|
57
|
-
|
|
58
|
-
const result = await this.authenticate(socket, request);
|
|
70
|
+
socket.pause();
|
|
59
71
|
|
|
60
|
-
|
|
61
|
-
|
|
72
|
+
try {
|
|
73
|
+
if (this.authenticate) {
|
|
74
|
+
const result = await this.authenticate(socket, request);
|
|
75
|
+
|
|
76
|
+
if (!isSocketOpen(socket)) {
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if (!result.isValid) {
|
|
81
|
+
socket.resume();
|
|
82
|
+
socket.close(WEB_SOCKET_CLOSE_CODES.POLICY_VIOLATION, result.message);
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const connectionResult = await this.handleConnection?.(socket, request);
|
|
88
|
+
|
|
89
|
+
if (!isSocketOpen(socket)) {
|
|
62
90
|
return;
|
|
63
91
|
}
|
|
64
|
-
}
|
|
65
92
|
|
|
66
|
-
|
|
67
|
-
|
|
93
|
+
if (connectionResult?.handled) {
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const unregisterSocket = await super.registerSocket(socket);
|
|
98
|
+
|
|
99
|
+
if (this.isStopping || !isSocketOpen(socket)) {
|
|
100
|
+
unregisterSocket();
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
socket.resume();
|
|
68
105
|
socket.send('socket:auth:valid' satisfies WebSocketControlMessage);
|
|
69
106
|
} catch (error) {
|
|
107
|
+
socket.resume();
|
|
108
|
+
socket.close(WEB_SOCKET_CLOSE_CODES.INTERNAL_ERROR);
|
|
109
|
+
|
|
70
110
|
webSocketServer.emit('error', error);
|
|
71
111
|
}
|
|
72
112
|
});
|
|
@@ -79,12 +119,18 @@ class WebSocketServer<Schema extends WebSocketSchema> extends WebSocketHandler<S
|
|
|
79
119
|
return;
|
|
80
120
|
}
|
|
81
121
|
|
|
82
|
-
|
|
83
|
-
await super.closeClientSockets();
|
|
122
|
+
this.isStopping = true;
|
|
84
123
|
|
|
85
|
-
|
|
124
|
+
try {
|
|
125
|
+
super.offAny();
|
|
126
|
+
await super.closeClientSockets();
|
|
86
127
|
|
|
87
|
-
|
|
128
|
+
await closeServerSocket(this.webSocketServer, { timeout: this.socketTimeout });
|
|
129
|
+
|
|
130
|
+
this.webSocketServer = undefined;
|
|
131
|
+
} finally {
|
|
132
|
+
this.isStopping = false;
|
|
133
|
+
}
|
|
88
134
|
}
|
|
89
135
|
}
|
|
90
136
|
|
|
@@ -1,2 +1,9 @@
|
|
|
1
1
|
export const WEB_SOCKET_CONTROL_MESSAGES = Object.freeze(['socket:auth:valid'] as const);
|
|
2
2
|
export type WebSocketControlMessage = (typeof WEB_SOCKET_CONTROL_MESSAGES)[number];
|
|
3
|
+
|
|
4
|
+
export const WEB_SOCKET_CLOSE_CODES = Object.freeze({
|
|
5
|
+
DEFAULT: 1000,
|
|
6
|
+
PROTOCOL_ERROR: 1002,
|
|
7
|
+
POLICY_VIOLATION: 1008,
|
|
8
|
+
INTERNAL_ERROR: 1011,
|
|
9
|
+
} as const);
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { JSONValue } from '@zimic/
|
|
2
|
-
import { PossiblePromise } from '@zimic/utils/types';
|
|
1
|
+
import type { JSONValue, PossiblePromise } from '@zimic/utils/types';
|
|
3
2
|
import type { WebSocket as ClientSocket } from 'isomorphic-ws';
|
|
4
3
|
|
|
5
4
|
export interface WebSocketChannelFrame<Channel extends string> {
|
package/src/utils/webSocket.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import ClientSocket, { type WebSocketServer as ServerSocket } from 'isomorphic-ws';
|
|
2
2
|
|
|
3
|
-
import { WebSocketControlMessage } from '@/utils/webSocket/constants';
|
|
3
|
+
import { WEB_SOCKET_CLOSE_CODES, WebSocketControlMessage } from '@/utils/webSocket/constants';
|
|
4
4
|
import UnauthorizedWebSocketConnectionError from '@/utils/webSocket/errors/UnauthorizedWebSocketConnectionError';
|
|
5
5
|
|
|
6
6
|
class WebSocketTimeoutError extends Error {}
|
|
@@ -65,7 +65,7 @@ export async function waitForOpenClientSocket(
|
|
|
65
65
|
}
|
|
66
66
|
|
|
67
67
|
function handleClose(event: ClientSocket.CloseEvent) {
|
|
68
|
-
const isUnauthorized = event.code ===
|
|
68
|
+
const isUnauthorized = event.code === WEB_SOCKET_CLOSE_CODES.POLICY_VIOLATION;
|
|
69
69
|
|
|
70
70
|
/* istanbul ignore else -- @preserve
|
|
71
71
|
* An unauthorized close event is the only one we expect to happen here. */
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export interface SerializedWebSocketBinaryMessageData {
|
|
2
|
+
type: 'binary';
|
|
3
|
+
data: string;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
export interface SerializedWebSocketTextMessageData {
|
|
7
|
+
type: 'text';
|
|
8
|
+
data: string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export type SerializedWebSocketMessageData = SerializedWebSocketBinaryMessageData | SerializedWebSocketTextMessageData;
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { assertTypeOf, ValidationError } from '@zimic/utils/validation';
|
|
2
|
+
import { WebSocketMessageData, WebSocketSchema } from '@zimic/ws';
|
|
3
|
+
|
|
4
|
+
import { convertArrayBufferToBase64, convertBase64ToArrayBuffer } from '@/utils/data';
|
|
5
|
+
|
|
6
|
+
import {
|
|
7
|
+
SerializedWebSocketBinaryMessageData,
|
|
8
|
+
SerializedWebSocketMessageData,
|
|
9
|
+
SerializedWebSocketTextMessageData,
|
|
10
|
+
} from '../interceptorWorker/types/messages';
|
|
11
|
+
|
|
12
|
+
export function isWebSocketBinaryMessageData(data: unknown): data is Blob | BufferSource {
|
|
13
|
+
return data instanceof Blob || data instanceof ArrayBuffer || ArrayBuffer.isView(data);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function normalizeBufferSource(bufferSource: BufferSource): ArrayBuffer {
|
|
17
|
+
if (bufferSource instanceof ArrayBuffer) {
|
|
18
|
+
return bufferSource;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const bytes = new Uint8Array(bufferSource.buffer, bufferSource.byteOffset, bufferSource.byteLength);
|
|
22
|
+
const normalizedBytes = new Uint8Array(bytes.byteLength);
|
|
23
|
+
normalizedBytes.set(bytes);
|
|
24
|
+
|
|
25
|
+
return normalizedBytes.buffer;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function tryParseJSONMessageData(data: string): unknown {
|
|
29
|
+
try {
|
|
30
|
+
return JSON.parse(data);
|
|
31
|
+
} catch {
|
|
32
|
+
return data;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function normalizeWebSocketBinaryMessageData(data: Blob | BufferSource): ArrayBuffer | Blob {
|
|
37
|
+
if (data instanceof Blob) {
|
|
38
|
+
return data;
|
|
39
|
+
}
|
|
40
|
+
return normalizeBufferSource(data);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export function normalizeWebSocketMessageData<Schema extends WebSocketSchema>(
|
|
44
|
+
data: Schema | WebSocketMessageData<Schema>,
|
|
45
|
+
): Schema {
|
|
46
|
+
if (typeof data === 'string') {
|
|
47
|
+
const normalizedStringData = tryParseJSONMessageData(data);
|
|
48
|
+
return normalizedStringData as Schema;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return data as Schema;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export function serializeWebSocketMessageDataForSocket<Schema extends WebSocketSchema>(
|
|
55
|
+
data: Schema | WebSocketMessageData<Schema> | undefined,
|
|
56
|
+
): WebSocketMessageData<Schema> {
|
|
57
|
+
if (isWebSocketBinaryMessageData(data) || typeof data === 'string') {
|
|
58
|
+
return data as WebSocketMessageData<Schema>;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const serializedData = JSON.stringify(data);
|
|
62
|
+
assertTypeOf('serialized WebSocket message data', serializedData, 'string');
|
|
63
|
+
return serializedData as unknown as WebSocketMessageData<Schema>;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export async function serializeWebSocketMessageDataForTransport(
|
|
67
|
+
data: WebSocketMessageData<WebSocketSchema> | undefined,
|
|
68
|
+
): Promise<SerializedWebSocketMessageData> {
|
|
69
|
+
if (data === undefined) {
|
|
70
|
+
throw new ValidationError('WebSocket message data must not be undefined.');
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
if (isWebSocketBinaryMessageData(data)) {
|
|
74
|
+
const normalizedData = normalizeWebSocketBinaryMessageData(data);
|
|
75
|
+
const arrayBuffer = normalizedData instanceof Blob ? await normalizedData.arrayBuffer() : normalizedData;
|
|
76
|
+
|
|
77
|
+
return {
|
|
78
|
+
type: 'binary',
|
|
79
|
+
data: convertArrayBufferToBase64(arrayBuffer),
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
assertTypeOf('WebSocket message data', data, 'string');
|
|
84
|
+
|
|
85
|
+
return { type: 'text', data };
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export function isSerializedWebSocketBinaryMessageData(data: unknown): data is SerializedWebSocketBinaryMessageData {
|
|
89
|
+
return (
|
|
90
|
+
typeof data === 'object' &&
|
|
91
|
+
data !== null &&
|
|
92
|
+
'type' in data &&
|
|
93
|
+
data.type === 'binary' &&
|
|
94
|
+
'data' in data &&
|
|
95
|
+
typeof data.data === 'string'
|
|
96
|
+
);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export function isSerializedWebSocketTextMessageData(data: unknown): data is SerializedWebSocketTextMessageData {
|
|
100
|
+
return (
|
|
101
|
+
typeof data === 'object' &&
|
|
102
|
+
data !== null &&
|
|
103
|
+
'type' in data &&
|
|
104
|
+
data.type === 'text' &&
|
|
105
|
+
'data' in data &&
|
|
106
|
+
typeof data.data === 'string'
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export function isSerializedWebSocketMessageData(data: unknown): data is SerializedWebSocketMessageData {
|
|
111
|
+
return isSerializedWebSocketBinaryMessageData(data) || isSerializedWebSocketTextMessageData(data);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export function deserializeWebSocketMessageDataFromTransport(
|
|
115
|
+
data: SerializedWebSocketMessageData,
|
|
116
|
+
): string | ArrayBuffer {
|
|
117
|
+
if (isSerializedWebSocketBinaryMessageData(data)) {
|
|
118
|
+
return normalizeBufferSource(convertBase64ToArrayBuffer(data.data));
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
return data.data;
|
|
122
|
+
}
|