msw 2.2.2 → 2.3.0-ws.rc-1
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/cli/init.js +0 -0
- package/config/scripts/postinstall.js +0 -0
- package/lib/browser/index.d.mts +7 -6
- package/lib/browser/index.d.ts +7 -6
- package/lib/browser/index.js +32 -15
- package/lib/browser/index.js.map +1 -1
- package/lib/browser/index.mjs +32 -15
- package/lib/browser/index.mjs.map +1 -1
- package/lib/core/{GraphQLHandler-jOzqbxSK.d.ts → GraphQLHandler-Cbu12sb0.d.ts} +1 -1
- package/lib/core/{GraphQLHandler-AenIUdwE.d.mts → GraphQLHandler-QGQY_9Rc.d.mts} +1 -1
- package/lib/core/{HttpResponse-wcp03c7-.d.mts → HttpResponse-BWB1yDNM.d.mts} +2 -2
- package/lib/core/{HttpResponse-_514VQ9z.d.ts → HttpResponse-DeJBWGN5.d.ts} +2 -2
- package/lib/core/HttpResponse.d.mts +1 -1
- package/lib/core/HttpResponse.d.ts +1 -1
- package/lib/core/SetupApi.d.mts +15 -12
- package/lib/core/SetupApi.d.ts +15 -12
- package/lib/core/SetupApi.js +3 -1
- package/lib/core/SetupApi.js.map +1 -1
- package/lib/core/SetupApi.mjs +3 -1
- package/lib/core/SetupApi.mjs.map +1 -1
- package/lib/core/getResponse.d.mts +1 -1
- package/lib/core/getResponse.d.ts +1 -1
- package/lib/core/graphql.d.mts +2 -2
- package/lib/core/graphql.d.ts +2 -2
- package/lib/core/handlers/GraphQLHandler.d.mts +2 -2
- package/lib/core/handlers/GraphQLHandler.d.ts +2 -2
- package/lib/core/handlers/HttpHandler.d.mts +1 -1
- package/lib/core/handlers/HttpHandler.d.ts +1 -1
- package/lib/core/handlers/RequestHandler.d.mts +1 -1
- package/lib/core/handlers/RequestHandler.d.ts +1 -1
- package/lib/core/handlers/WebSocketHandler.d.mts +38 -0
- package/lib/core/handlers/WebSocketHandler.d.ts +38 -0
- package/lib/core/handlers/WebSocketHandler.js +65 -0
- package/lib/core/handlers/WebSocketHandler.js.map +1 -0
- package/lib/core/handlers/WebSocketHandler.mjs +47 -0
- package/lib/core/handlers/WebSocketHandler.mjs.map +1 -0
- package/lib/core/http.d.mts +1 -1
- package/lib/core/http.d.ts +1 -1
- package/lib/core/index.d.mts +5 -2
- package/lib/core/index.d.ts +5 -2
- package/lib/core/index.js +3 -1
- package/lib/core/index.js.map +1 -1
- package/lib/core/index.mjs +3 -1
- package/lib/core/index.mjs.map +1 -1
- package/lib/core/passthrough.d.mts +1 -1
- package/lib/core/passthrough.d.ts +1 -1
- package/lib/core/utils/HttpResponse/decorators.d.mts +1 -1
- package/lib/core/utils/HttpResponse/decorators.d.ts +1 -1
- package/lib/core/utils/executeHandlers.d.mts +1 -1
- package/lib/core/utils/executeHandlers.d.ts +1 -1
- package/lib/core/utils/executeHandlers.js +4 -0
- package/lib/core/utils/executeHandlers.js.map +1 -1
- package/lib/core/utils/executeHandlers.mjs +6 -0
- package/lib/core/utils/executeHandlers.mjs.map +1 -1
- package/lib/core/utils/handleRequest.d.mts +2 -2
- package/lib/core/utils/handleRequest.d.ts +2 -2
- package/lib/core/utils/handleRequest.js.map +1 -1
- package/lib/core/utils/handleRequest.mjs.map +1 -1
- package/lib/core/utils/handleWebSocketEvent.d.mts +10 -0
- package/lib/core/utils/handleWebSocketEvent.d.ts +10 -0
- package/lib/core/utils/handleWebSocketEvent.js +56 -0
- package/lib/core/utils/handleWebSocketEvent.js.map +1 -0
- package/lib/core/utils/handleWebSocketEvent.mjs +40 -0
- package/lib/core/utils/handleWebSocketEvent.mjs.map +1 -0
- package/lib/core/utils/internal/parseGraphQLRequest.d.mts +2 -2
- package/lib/core/utils/internal/parseGraphQLRequest.d.ts +2 -2
- package/lib/core/utils/internal/parseMultipartData.d.mts +1 -1
- package/lib/core/utils/internal/parseMultipartData.d.ts +1 -1
- package/lib/core/utils/internal/requestHandlerUtils.d.mts +1 -1
- package/lib/core/utils/internal/requestHandlerUtils.d.ts +1 -1
- package/lib/core/utils/matching/matchRequestUrl.d.mts +2 -1
- package/lib/core/utils/matching/matchRequestUrl.d.ts +2 -1
- package/lib/core/utils/matching/matchRequestUrl.js +4 -0
- package/lib/core/utils/matching/matchRequestUrl.js.map +1 -1
- package/lib/core/utils/matching/matchRequestUrl.mjs +4 -0
- package/lib/core/utils/matching/matchRequestUrl.mjs.map +1 -1
- package/lib/core/ws/WebSocketClientManager.d.mts +64 -0
- package/lib/core/ws/WebSocketClientManager.d.ts +64 -0
- package/lib/core/ws/WebSocketClientManager.js +123 -0
- package/lib/core/ws/WebSocketClientManager.js.map +1 -0
- package/lib/core/ws/WebSocketClientManager.mjs +103 -0
- package/lib/core/ws/WebSocketClientManager.mjs.map +1 -0
- package/lib/core/ws/webSocketInterceptor.d.mts +5 -0
- package/lib/core/ws/webSocketInterceptor.d.ts +5 -0
- package/lib/core/ws/webSocketInterceptor.js +26 -0
- package/lib/core/ws/webSocketInterceptor.js.map +1 -0
- package/lib/core/ws/webSocketInterceptor.mjs +6 -0
- package/lib/core/ws/webSocketInterceptor.mjs.map +1 -0
- package/lib/core/ws/ws.d.mts +44 -0
- package/lib/core/ws/ws.d.ts +44 -0
- package/lib/core/ws/ws.js +82 -0
- package/lib/core/ws/ws.js.map +1 -0
- package/lib/core/ws/ws.mjs +65 -0
- package/lib/core/ws/ws.mjs.map +1 -0
- package/lib/iife/index.js +703 -17
- package/lib/iife/index.js.map +1 -1
- package/lib/mockServiceWorker.js +1 -1
- package/lib/native/index.d.mts +6 -5
- package/lib/native/index.d.ts +6 -5
- package/lib/native/index.js +7 -0
- package/lib/native/index.js.map +1 -1
- package/lib/native/index.mjs +7 -0
- package/lib/native/index.mjs.map +1 -1
- package/lib/node/index.d.mts +8 -7
- package/lib/node/index.d.ts +8 -7
- package/lib/node/index.js +7 -0
- package/lib/node/index.js.map +1 -1
- package/lib/node/index.mjs +7 -0
- package/lib/node/index.mjs.map +1 -1
- package/package.json +29 -24
- package/src/browser/setupWorker/glossary.ts +10 -10
- package/src/browser/setupWorker/setupWorker.ts +17 -3
- package/src/core/SetupApi.ts +28 -20
- package/src/core/handlers/WebSocketHandler.ts +89 -0
- package/src/core/index.ts +3 -0
- package/src/core/utils/executeHandlers.ts +6 -2
- package/src/core/utils/handleRequest.ts +1 -2
- package/src/core/utils/handleWebSocketEvent.ts +49 -0
- package/src/core/utils/matching/matchRequestUrl.test.ts +44 -0
- package/src/core/utils/matching/matchRequestUrl.ts +4 -0
- package/src/core/ws/WebSocketClientManager.test.ts +159 -0
- package/src/core/ws/WebSocketClientManager.ts +170 -0
- package/src/core/ws/webSocketInterceptor.ts +3 -0
- package/src/core/ws/ws.test.ts +23 -0
- package/src/core/ws/ws.ts +108 -0
- package/src/node/SetupServerApi.ts +8 -7
- package/src/node/SetupServerCommonApi.ts +10 -1
- package/src/node/glossary.ts +5 -7
- package/src/node/setupServer.ts +2 -1
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { WebSocketData, WebSocketClientConnectionProtocol, WebSocketClientConnection } from '@mswjs/interceptors/WebSocket';
|
|
2
|
+
|
|
3
|
+
type WebSocketBroadcastChannelMessage = {
|
|
4
|
+
type: 'connection:open';
|
|
5
|
+
payload: {
|
|
6
|
+
clientId: string;
|
|
7
|
+
url: string;
|
|
8
|
+
};
|
|
9
|
+
} | {
|
|
10
|
+
type: 'extraneous:send';
|
|
11
|
+
payload: {
|
|
12
|
+
clientId: string;
|
|
13
|
+
data: WebSocketData;
|
|
14
|
+
};
|
|
15
|
+
} | {
|
|
16
|
+
type: 'extraneous:close';
|
|
17
|
+
payload: {
|
|
18
|
+
clientId: string;
|
|
19
|
+
code?: number;
|
|
20
|
+
reason?: string;
|
|
21
|
+
};
|
|
22
|
+
};
|
|
23
|
+
declare const kAddByClientId: unique symbol;
|
|
24
|
+
/**
|
|
25
|
+
* A manager responsible for accumulating WebSocket client
|
|
26
|
+
* connections across different browser runtimes.
|
|
27
|
+
*/
|
|
28
|
+
declare class WebSocketClientManager {
|
|
29
|
+
private channel;
|
|
30
|
+
/**
|
|
31
|
+
* All active WebSocket client connections.
|
|
32
|
+
*/
|
|
33
|
+
clients: Set<WebSocketClientConnectionProtocol>;
|
|
34
|
+
constructor(channel: BroadcastChannel);
|
|
35
|
+
/**
|
|
36
|
+
* Adds the given `WebSocket` client connection to the set
|
|
37
|
+
* of all connections. The given connection is always the complete
|
|
38
|
+
* connection object because `addConnection()` is called only
|
|
39
|
+
* for the opened connections in the same runtime.
|
|
40
|
+
*/
|
|
41
|
+
addConnection(client: WebSocketClientConnection): void;
|
|
42
|
+
/**
|
|
43
|
+
* Adds a client connection wrapper to operate with
|
|
44
|
+
* WebSocket client connections in other runtimes.
|
|
45
|
+
*/
|
|
46
|
+
private onRemoteConnection;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* A wrapper class to operate with WebSocket client connections
|
|
50
|
+
* from other runtimes. This class maintains 1-1 public API
|
|
51
|
+
* compatibility to the `WebSocketClientConnection` but relies
|
|
52
|
+
* on the given `BroadcastChannel` to communicate instructions
|
|
53
|
+
* with the client connections from other runtimes.
|
|
54
|
+
*/
|
|
55
|
+
declare class WebSocketRemoteClientConnection implements WebSocketClientConnectionProtocol {
|
|
56
|
+
readonly id: string;
|
|
57
|
+
readonly url: URL;
|
|
58
|
+
private channel;
|
|
59
|
+
constructor(id: string, url: URL, channel: BroadcastChannel);
|
|
60
|
+
send(data: WebSocketData): void;
|
|
61
|
+
close(code?: number | undefined, reason?: string | undefined): void;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export { type WebSocketBroadcastChannelMessage, WebSocketClientManager, WebSocketRemoteClientConnection, kAddByClientId };
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var WebSocketClientManager_exports = {};
|
|
20
|
+
__export(WebSocketClientManager_exports, {
|
|
21
|
+
WebSocketClientManager: () => WebSocketClientManager,
|
|
22
|
+
WebSocketRemoteClientConnection: () => WebSocketRemoteClientConnection,
|
|
23
|
+
kAddByClientId: () => kAddByClientId
|
|
24
|
+
});
|
|
25
|
+
module.exports = __toCommonJS(WebSocketClientManager_exports);
|
|
26
|
+
const kAddByClientId = Symbol("kAddByClientId");
|
|
27
|
+
class WebSocketClientManager {
|
|
28
|
+
constructor(channel) {
|
|
29
|
+
this.channel = channel;
|
|
30
|
+
this.clients = /* @__PURE__ */ new Set();
|
|
31
|
+
this.channel.addEventListener("message", (message) => {
|
|
32
|
+
const { type, payload } = message.data;
|
|
33
|
+
switch (type) {
|
|
34
|
+
case "connection:open": {
|
|
35
|
+
this.onRemoteConnection(payload.clientId, new URL(payload.url));
|
|
36
|
+
break;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* All active WebSocket client connections.
|
|
43
|
+
*/
|
|
44
|
+
clients;
|
|
45
|
+
/**
|
|
46
|
+
* Adds the given `WebSocket` client connection to the set
|
|
47
|
+
* of all connections. The given connection is always the complete
|
|
48
|
+
* connection object because `addConnection()` is called only
|
|
49
|
+
* for the opened connections in the same runtime.
|
|
50
|
+
*/
|
|
51
|
+
addConnection(client) {
|
|
52
|
+
this.clients.add(client);
|
|
53
|
+
this.channel.postMessage({
|
|
54
|
+
type: "connection:open",
|
|
55
|
+
payload: {
|
|
56
|
+
clientId: client.id,
|
|
57
|
+
url: client.url.toString()
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
const handleExtraneousMessage = (message) => {
|
|
61
|
+
const { type, payload } = message.data;
|
|
62
|
+
if (typeof payload === "object" && "clientId" in payload && payload.clientId !== client.id) {
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
switch (type) {
|
|
66
|
+
case "extraneous:send": {
|
|
67
|
+
client.send(payload.data);
|
|
68
|
+
break;
|
|
69
|
+
}
|
|
70
|
+
case "extraneous:close": {
|
|
71
|
+
client.close(payload.code, payload.reason);
|
|
72
|
+
break;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
const abortController = new AbortController();
|
|
77
|
+
this.channel.addEventListener("message", handleExtraneousMessage, {
|
|
78
|
+
signal: abortController.signal
|
|
79
|
+
});
|
|
80
|
+
client.addEventListener("close", () => abortController.abort(), {
|
|
81
|
+
once: true
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Adds a client connection wrapper to operate with
|
|
86
|
+
* WebSocket client connections in other runtimes.
|
|
87
|
+
*/
|
|
88
|
+
onRemoteConnection(id, url) {
|
|
89
|
+
this.clients.add(
|
|
90
|
+
// Create a connection-compatible instance that can
|
|
91
|
+
// operate with this client from a different runtime
|
|
92
|
+
// using the BroadcastChannel messages.
|
|
93
|
+
new WebSocketRemoteClientConnection(id, url, this.channel)
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
class WebSocketRemoteClientConnection {
|
|
98
|
+
constructor(id, url, channel) {
|
|
99
|
+
this.id = id;
|
|
100
|
+
this.url = url;
|
|
101
|
+
this.channel = channel;
|
|
102
|
+
}
|
|
103
|
+
send(data) {
|
|
104
|
+
this.channel.postMessage({
|
|
105
|
+
type: "extraneous:send",
|
|
106
|
+
payload: {
|
|
107
|
+
clientId: this.id,
|
|
108
|
+
data
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
close(code, reason) {
|
|
113
|
+
this.channel.postMessage({
|
|
114
|
+
type: "extraneous:close",
|
|
115
|
+
payload: {
|
|
116
|
+
clientId: this.id,
|
|
117
|
+
code,
|
|
118
|
+
reason
|
|
119
|
+
}
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
//# sourceMappingURL=WebSocketClientManager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/core/ws/WebSocketClientManager.ts"],"sourcesContent":["import type {\n WebSocketData,\n WebSocketClientConnection,\n WebSocketClientConnectionProtocol,\n} from '@mswjs/interceptors/WebSocket'\n\nexport type WebSocketBroadcastChannelMessage =\n | {\n type: 'connection:open'\n payload: {\n clientId: string\n url: string\n }\n }\n | {\n type: 'extraneous:send'\n payload: {\n clientId: string\n data: WebSocketData\n }\n }\n | {\n type: 'extraneous:close'\n payload: {\n clientId: string\n code?: number\n reason?: string\n }\n }\n\nexport const kAddByClientId = Symbol('kAddByClientId')\n\n/**\n * A manager responsible for accumulating WebSocket client\n * connections across different browser runtimes.\n */\nexport class WebSocketClientManager {\n /**\n * All active WebSocket client connections.\n */\n public clients: Set<WebSocketClientConnectionProtocol>\n\n constructor(private channel: BroadcastChannel) {\n this.clients = new Set()\n\n this.channel.addEventListener('message', (message) => {\n const { type, payload } = message.data as WebSocketBroadcastChannelMessage\n\n switch (type) {\n case 'connection:open': {\n // When another runtime notifies about a new connection,\n // create a connection wrapper class and add it to the set.\n this.onRemoteConnection(payload.clientId, new URL(payload.url))\n break\n }\n }\n })\n }\n\n /**\n * Adds the given `WebSocket` client connection to the set\n * of all connections. The given connection is always the complete\n * connection object because `addConnection()` is called only\n * for the opened connections in the same runtime.\n */\n public addConnection(client: WebSocketClientConnection): void {\n this.clients.add(client)\n\n // Signal to other runtimes about this connection.\n this.channel.postMessage({\n type: 'connection:open',\n payload: {\n clientId: client.id,\n url: client.url.toString(),\n },\n } as WebSocketBroadcastChannelMessage)\n\n // Instruct the current client how to handle events\n // coming from other runtimes (e.g. when calling `.broadcast()`).\n const handleExtraneousMessage = (\n message: MessageEvent<WebSocketBroadcastChannelMessage>,\n ) => {\n const { type, payload } = message.data\n\n // Ignore broadcasted messages for other clients.\n if (\n typeof payload === 'object' &&\n 'clientId' in payload &&\n payload.clientId !== client.id\n ) {\n return\n }\n\n switch (type) {\n case 'extraneous:send': {\n client.send(payload.data)\n break\n }\n\n case 'extraneous:close': {\n client.close(payload.code, payload.reason)\n break\n }\n }\n }\n\n const abortController = new AbortController()\n\n this.channel.addEventListener('message', handleExtraneousMessage, {\n signal: abortController.signal,\n })\n\n // Once closed, this connection cannot be operated on.\n // This must include the extraneous runtimes as well.\n client.addEventListener('close', () => abortController.abort(), {\n once: true,\n })\n }\n\n /**\n * Adds a client connection wrapper to operate with\n * WebSocket client connections in other runtimes.\n */\n private onRemoteConnection(id: string, url: URL): void {\n this.clients.add(\n // Create a connection-compatible instance that can\n // operate with this client from a different runtime\n // using the BroadcastChannel messages.\n new WebSocketRemoteClientConnection(id, url, this.channel),\n )\n }\n}\n\n/**\n * A wrapper class to operate with WebSocket client connections\n * from other runtimes. This class maintains 1-1 public API\n * compatibility to the `WebSocketClientConnection` but relies\n * on the given `BroadcastChannel` to communicate instructions\n * with the client connections from other runtimes.\n */\nexport class WebSocketRemoteClientConnection\n implements WebSocketClientConnectionProtocol\n{\n constructor(\n public readonly id: string,\n public readonly url: URL,\n private channel: BroadcastChannel,\n ) {}\n\n send(data: WebSocketData): void {\n this.channel.postMessage({\n type: 'extraneous:send',\n payload: {\n clientId: this.id,\n data,\n },\n } as WebSocketBroadcastChannelMessage)\n }\n\n close(code?: number | undefined, reason?: string | undefined): void {\n this.channel.postMessage({\n type: 'extraneous:close',\n payload: {\n clientId: this.id,\n code,\n reason,\n },\n } as WebSocketBroadcastChannelMessage)\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA8BO,MAAM,iBAAiB,OAAO,gBAAgB;AAM9C,MAAM,uBAAuB;AAAA,EAMlC,YAAoB,SAA2B;AAA3B;AAClB,SAAK,UAAU,oBAAI,IAAI;AAEvB,SAAK,QAAQ,iBAAiB,WAAW,CAAC,YAAY;AACpD,YAAM,EAAE,MAAM,QAAQ,IAAI,QAAQ;AAElC,cAAQ,MAAM;AAAA,QACZ,KAAK,mBAAmB;AAGtB,eAAK,mBAAmB,QAAQ,UAAU,IAAI,IAAI,QAAQ,GAAG,CAAC;AAC9D;AAAA,QACF;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAjBO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAyBA,cAAc,QAAyC;AAC5D,SAAK,QAAQ,IAAI,MAAM;AAGvB,SAAK,QAAQ,YAAY;AAAA,MACvB,MAAM;AAAA,MACN,SAAS;AAAA,QACP,UAAU,OAAO;AAAA,QACjB,KAAK,OAAO,IAAI,SAAS;AAAA,MAC3B;AAAA,IACF,CAAqC;AAIrC,UAAM,0BAA0B,CAC9B,YACG;AACH,YAAM,EAAE,MAAM,QAAQ,IAAI,QAAQ;AAGlC,UACE,OAAO,YAAY,YACnB,cAAc,WACd,QAAQ,aAAa,OAAO,IAC5B;AACA;AAAA,MACF;AAEA,cAAQ,MAAM;AAAA,QACZ,KAAK,mBAAmB;AACtB,iBAAO,KAAK,QAAQ,IAAI;AACxB;AAAA,QACF;AAAA,QAEA,KAAK,oBAAoB;AACvB,iBAAO,MAAM,QAAQ,MAAM,QAAQ,MAAM;AACzC;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,UAAM,kBAAkB,IAAI,gBAAgB;AAE5C,SAAK,QAAQ,iBAAiB,WAAW,yBAAyB;AAAA,MAChE,QAAQ,gBAAgB;AAAA,IAC1B,CAAC;AAID,WAAO,iBAAiB,SAAS,MAAM,gBAAgB,MAAM,GAAG;AAAA,MAC9D,MAAM;AAAA,IACR,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,mBAAmB,IAAY,KAAgB;AACrD,SAAK,QAAQ;AAAA;AAAA;AAAA;AAAA,MAIX,IAAI,gCAAgC,IAAI,KAAK,KAAK,OAAO;AAAA,IAC3D;AAAA,EACF;AACF;AASO,MAAM,gCAEb;AAAA,EACE,YACkB,IACA,KACR,SACR;AAHgB;AACA;AACR;AAAA,EACP;AAAA,EAEH,KAAK,MAA2B;AAC9B,SAAK,QAAQ,YAAY;AAAA,MACvB,MAAM;AAAA,MACN,SAAS;AAAA,QACP,UAAU,KAAK;AAAA,QACf;AAAA,MACF;AAAA,IACF,CAAqC;AAAA,EACvC;AAAA,EAEA,MAAM,MAA2B,QAAmC;AAClE,SAAK,QAAQ,YAAY;AAAA,MACvB,MAAM;AAAA,MACN,SAAS;AAAA,QACP,UAAU,KAAK;AAAA,QACf;AAAA,QACA;AAAA,MACF;AAAA,IACF,CAAqC;AAAA,EACvC;AACF;","names":[]}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
const kAddByClientId = Symbol("kAddByClientId");
|
|
2
|
+
class WebSocketClientManager {
|
|
3
|
+
constructor(channel) {
|
|
4
|
+
this.channel = channel;
|
|
5
|
+
this.clients = /* @__PURE__ */ new Set();
|
|
6
|
+
this.channel.addEventListener("message", (message) => {
|
|
7
|
+
const { type, payload } = message.data;
|
|
8
|
+
switch (type) {
|
|
9
|
+
case "connection:open": {
|
|
10
|
+
this.onRemoteConnection(payload.clientId, new URL(payload.url));
|
|
11
|
+
break;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* All active WebSocket client connections.
|
|
18
|
+
*/
|
|
19
|
+
clients;
|
|
20
|
+
/**
|
|
21
|
+
* Adds the given `WebSocket` client connection to the set
|
|
22
|
+
* of all connections. The given connection is always the complete
|
|
23
|
+
* connection object because `addConnection()` is called only
|
|
24
|
+
* for the opened connections in the same runtime.
|
|
25
|
+
*/
|
|
26
|
+
addConnection(client) {
|
|
27
|
+
this.clients.add(client);
|
|
28
|
+
this.channel.postMessage({
|
|
29
|
+
type: "connection:open",
|
|
30
|
+
payload: {
|
|
31
|
+
clientId: client.id,
|
|
32
|
+
url: client.url.toString()
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
const handleExtraneousMessage = (message) => {
|
|
36
|
+
const { type, payload } = message.data;
|
|
37
|
+
if (typeof payload === "object" && "clientId" in payload && payload.clientId !== client.id) {
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
switch (type) {
|
|
41
|
+
case "extraneous:send": {
|
|
42
|
+
client.send(payload.data);
|
|
43
|
+
break;
|
|
44
|
+
}
|
|
45
|
+
case "extraneous:close": {
|
|
46
|
+
client.close(payload.code, payload.reason);
|
|
47
|
+
break;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
const abortController = new AbortController();
|
|
52
|
+
this.channel.addEventListener("message", handleExtraneousMessage, {
|
|
53
|
+
signal: abortController.signal
|
|
54
|
+
});
|
|
55
|
+
client.addEventListener("close", () => abortController.abort(), {
|
|
56
|
+
once: true
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Adds a client connection wrapper to operate with
|
|
61
|
+
* WebSocket client connections in other runtimes.
|
|
62
|
+
*/
|
|
63
|
+
onRemoteConnection(id, url) {
|
|
64
|
+
this.clients.add(
|
|
65
|
+
// Create a connection-compatible instance that can
|
|
66
|
+
// operate with this client from a different runtime
|
|
67
|
+
// using the BroadcastChannel messages.
|
|
68
|
+
new WebSocketRemoteClientConnection(id, url, this.channel)
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
class WebSocketRemoteClientConnection {
|
|
73
|
+
constructor(id, url, channel) {
|
|
74
|
+
this.id = id;
|
|
75
|
+
this.url = url;
|
|
76
|
+
this.channel = channel;
|
|
77
|
+
}
|
|
78
|
+
send(data) {
|
|
79
|
+
this.channel.postMessage({
|
|
80
|
+
type: "extraneous:send",
|
|
81
|
+
payload: {
|
|
82
|
+
clientId: this.id,
|
|
83
|
+
data
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
close(code, reason) {
|
|
88
|
+
this.channel.postMessage({
|
|
89
|
+
type: "extraneous:close",
|
|
90
|
+
payload: {
|
|
91
|
+
clientId: this.id,
|
|
92
|
+
code,
|
|
93
|
+
reason
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
export {
|
|
99
|
+
WebSocketClientManager,
|
|
100
|
+
WebSocketRemoteClientConnection,
|
|
101
|
+
kAddByClientId
|
|
102
|
+
};
|
|
103
|
+
//# sourceMappingURL=WebSocketClientManager.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/core/ws/WebSocketClientManager.ts"],"sourcesContent":["import type {\n WebSocketData,\n WebSocketClientConnection,\n WebSocketClientConnectionProtocol,\n} from '@mswjs/interceptors/WebSocket'\n\nexport type WebSocketBroadcastChannelMessage =\n | {\n type: 'connection:open'\n payload: {\n clientId: string\n url: string\n }\n }\n | {\n type: 'extraneous:send'\n payload: {\n clientId: string\n data: WebSocketData\n }\n }\n | {\n type: 'extraneous:close'\n payload: {\n clientId: string\n code?: number\n reason?: string\n }\n }\n\nexport const kAddByClientId = Symbol('kAddByClientId')\n\n/**\n * A manager responsible for accumulating WebSocket client\n * connections across different browser runtimes.\n */\nexport class WebSocketClientManager {\n /**\n * All active WebSocket client connections.\n */\n public clients: Set<WebSocketClientConnectionProtocol>\n\n constructor(private channel: BroadcastChannel) {\n this.clients = new Set()\n\n this.channel.addEventListener('message', (message) => {\n const { type, payload } = message.data as WebSocketBroadcastChannelMessage\n\n switch (type) {\n case 'connection:open': {\n // When another runtime notifies about a new connection,\n // create a connection wrapper class and add it to the set.\n this.onRemoteConnection(payload.clientId, new URL(payload.url))\n break\n }\n }\n })\n }\n\n /**\n * Adds the given `WebSocket` client connection to the set\n * of all connections. The given connection is always the complete\n * connection object because `addConnection()` is called only\n * for the opened connections in the same runtime.\n */\n public addConnection(client: WebSocketClientConnection): void {\n this.clients.add(client)\n\n // Signal to other runtimes about this connection.\n this.channel.postMessage({\n type: 'connection:open',\n payload: {\n clientId: client.id,\n url: client.url.toString(),\n },\n } as WebSocketBroadcastChannelMessage)\n\n // Instruct the current client how to handle events\n // coming from other runtimes (e.g. when calling `.broadcast()`).\n const handleExtraneousMessage = (\n message: MessageEvent<WebSocketBroadcastChannelMessage>,\n ) => {\n const { type, payload } = message.data\n\n // Ignore broadcasted messages for other clients.\n if (\n typeof payload === 'object' &&\n 'clientId' in payload &&\n payload.clientId !== client.id\n ) {\n return\n }\n\n switch (type) {\n case 'extraneous:send': {\n client.send(payload.data)\n break\n }\n\n case 'extraneous:close': {\n client.close(payload.code, payload.reason)\n break\n }\n }\n }\n\n const abortController = new AbortController()\n\n this.channel.addEventListener('message', handleExtraneousMessage, {\n signal: abortController.signal,\n })\n\n // Once closed, this connection cannot be operated on.\n // This must include the extraneous runtimes as well.\n client.addEventListener('close', () => abortController.abort(), {\n once: true,\n })\n }\n\n /**\n * Adds a client connection wrapper to operate with\n * WebSocket client connections in other runtimes.\n */\n private onRemoteConnection(id: string, url: URL): void {\n this.clients.add(\n // Create a connection-compatible instance that can\n // operate with this client from a different runtime\n // using the BroadcastChannel messages.\n new WebSocketRemoteClientConnection(id, url, this.channel),\n )\n }\n}\n\n/**\n * A wrapper class to operate with WebSocket client connections\n * from other runtimes. This class maintains 1-1 public API\n * compatibility to the `WebSocketClientConnection` but relies\n * on the given `BroadcastChannel` to communicate instructions\n * with the client connections from other runtimes.\n */\nexport class WebSocketRemoteClientConnection\n implements WebSocketClientConnectionProtocol\n{\n constructor(\n public readonly id: string,\n public readonly url: URL,\n private channel: BroadcastChannel,\n ) {}\n\n send(data: WebSocketData): void {\n this.channel.postMessage({\n type: 'extraneous:send',\n payload: {\n clientId: this.id,\n data,\n },\n } as WebSocketBroadcastChannelMessage)\n }\n\n close(code?: number | undefined, reason?: string | undefined): void {\n this.channel.postMessage({\n type: 'extraneous:close',\n payload: {\n clientId: this.id,\n code,\n reason,\n },\n } as WebSocketBroadcastChannelMessage)\n }\n}\n"],"mappings":"AA8BO,MAAM,iBAAiB,OAAO,gBAAgB;AAM9C,MAAM,uBAAuB;AAAA,EAMlC,YAAoB,SAA2B;AAA3B;AAClB,SAAK,UAAU,oBAAI,IAAI;AAEvB,SAAK,QAAQ,iBAAiB,WAAW,CAAC,YAAY;AACpD,YAAM,EAAE,MAAM,QAAQ,IAAI,QAAQ;AAElC,cAAQ,MAAM;AAAA,QACZ,KAAK,mBAAmB;AAGtB,eAAK,mBAAmB,QAAQ,UAAU,IAAI,IAAI,QAAQ,GAAG,CAAC;AAC9D;AAAA,QACF;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAjBO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAyBA,cAAc,QAAyC;AAC5D,SAAK,QAAQ,IAAI,MAAM;AAGvB,SAAK,QAAQ,YAAY;AAAA,MACvB,MAAM;AAAA,MACN,SAAS;AAAA,QACP,UAAU,OAAO;AAAA,QACjB,KAAK,OAAO,IAAI,SAAS;AAAA,MAC3B;AAAA,IACF,CAAqC;AAIrC,UAAM,0BAA0B,CAC9B,YACG;AACH,YAAM,EAAE,MAAM,QAAQ,IAAI,QAAQ;AAGlC,UACE,OAAO,YAAY,YACnB,cAAc,WACd,QAAQ,aAAa,OAAO,IAC5B;AACA;AAAA,MACF;AAEA,cAAQ,MAAM;AAAA,QACZ,KAAK,mBAAmB;AACtB,iBAAO,KAAK,QAAQ,IAAI;AACxB;AAAA,QACF;AAAA,QAEA,KAAK,oBAAoB;AACvB,iBAAO,MAAM,QAAQ,MAAM,QAAQ,MAAM;AACzC;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,UAAM,kBAAkB,IAAI,gBAAgB;AAE5C,SAAK,QAAQ,iBAAiB,WAAW,yBAAyB;AAAA,MAChE,QAAQ,gBAAgB;AAAA,IAC1B,CAAC;AAID,WAAO,iBAAiB,SAAS,MAAM,gBAAgB,MAAM,GAAG;AAAA,MAC9D,MAAM;AAAA,IACR,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,mBAAmB,IAAY,KAAgB;AACrD,SAAK,QAAQ;AAAA;AAAA;AAAA;AAAA,MAIX,IAAI,gCAAgC,IAAI,KAAK,KAAK,OAAO;AAAA,IAC3D;AAAA,EACF;AACF;AASO,MAAM,gCAEb;AAAA,EACE,YACkB,IACA,KACR,SACR;AAHgB;AACA;AACR;AAAA,EACP;AAAA,EAEH,KAAK,MAA2B;AAC9B,SAAK,QAAQ,YAAY;AAAA,MACvB,MAAM;AAAA,MACN,SAAS;AAAA,QACP,UAAU,KAAK;AAAA,QACf;AAAA,MACF;AAAA,IACF,CAAqC;AAAA,EACvC;AAAA,EAEA,MAAM,MAA2B,QAAmC;AAClE,SAAK,QAAQ,YAAY;AAAA,MACvB,MAAM;AAAA,MACN,SAAS;AAAA,QACP,UAAU,KAAK;AAAA,QACf;AAAA,QACA;AAAA,MACF;AAAA,IACF,CAAqC;AAAA,EACvC;AACF;","names":[]}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var webSocketInterceptor_exports = {};
|
|
20
|
+
__export(webSocketInterceptor_exports, {
|
|
21
|
+
webSocketInterceptor: () => webSocketInterceptor
|
|
22
|
+
});
|
|
23
|
+
module.exports = __toCommonJS(webSocketInterceptor_exports);
|
|
24
|
+
var import_WebSocket = require("@mswjs/interceptors/WebSocket");
|
|
25
|
+
const webSocketInterceptor = new import_WebSocket.WebSocketInterceptor();
|
|
26
|
+
//# sourceMappingURL=webSocketInterceptor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/core/ws/webSocketInterceptor.ts"],"sourcesContent":["import { WebSocketInterceptor } from '@mswjs/interceptors/WebSocket'\n\nexport const webSocketInterceptor = new WebSocketInterceptor()\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,uBAAqC;AAE9B,MAAM,uBAAuB,IAAI,sCAAqB;","names":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/core/ws/webSocketInterceptor.ts"],"sourcesContent":["import { WebSocketInterceptor } from '@mswjs/interceptors/WebSocket'\n\nexport const webSocketInterceptor = new WebSocketInterceptor()\n"],"mappings":"AAAA,SAAS,4BAA4B;AAE9B,MAAM,uBAAuB,IAAI,qBAAqB;","names":[]}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { WebSocketClientConnectionProtocol, WebSocketData } from '@mswjs/interceptors/WebSocket';
|
|
2
|
+
import { WebSocketHandlerEventMap, WebSocketHandler } from '../handlers/WebSocketHandler.mjs';
|
|
3
|
+
import { Path } from '../utils/matching/matchRequestUrl.mjs';
|
|
4
|
+
import 'strict-event-emitter';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Intercepts outgoing WebSocket connections to the given URL.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* const chat = ws.link('wss://chat.example.com')
|
|
11
|
+
* chat.on('connection', ({ client }) => {
|
|
12
|
+
* client.send('hello from server!')
|
|
13
|
+
* })
|
|
14
|
+
*/
|
|
15
|
+
declare function createWebSocketLinkHandler(url: Path): {
|
|
16
|
+
clients: Set<WebSocketClientConnectionProtocol>;
|
|
17
|
+
on<K extends "connection">(event: K, listener: (...args: WebSocketHandlerEventMap[K]) => void): WebSocketHandler;
|
|
18
|
+
/**
|
|
19
|
+
* Broadcasts the given data to all WebSocket clients.
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* const service = ws.link('wss://example.com')
|
|
23
|
+
* service.on('connection', () => {
|
|
24
|
+
* service.broadcast('hello, everyone!')
|
|
25
|
+
* })
|
|
26
|
+
*/
|
|
27
|
+
broadcast(data: WebSocketData): void;
|
|
28
|
+
/**
|
|
29
|
+
* Broadcasts the given data to all WebSocket clients
|
|
30
|
+
* except the ones provided in the `clients` argument.
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* const service = ws.link('wss://example.com')
|
|
34
|
+
* service.on('connection', ({ client }) => {
|
|
35
|
+
* service.broadcastExcept(client, 'hi, the rest of you!')
|
|
36
|
+
* })
|
|
37
|
+
*/
|
|
38
|
+
broadcastExcept(clients: WebSocketClientConnectionProtocol | Array<WebSocketClientConnectionProtocol>, data: WebSocketData): void;
|
|
39
|
+
};
|
|
40
|
+
declare const ws: {
|
|
41
|
+
link: typeof createWebSocketLinkHandler;
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
export { ws };
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { WebSocketClientConnectionProtocol, WebSocketData } from '@mswjs/interceptors/WebSocket';
|
|
2
|
+
import { WebSocketHandlerEventMap, WebSocketHandler } from '../handlers/WebSocketHandler.js';
|
|
3
|
+
import { Path } from '../utils/matching/matchRequestUrl.js';
|
|
4
|
+
import 'strict-event-emitter';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Intercepts outgoing WebSocket connections to the given URL.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* const chat = ws.link('wss://chat.example.com')
|
|
11
|
+
* chat.on('connection', ({ client }) => {
|
|
12
|
+
* client.send('hello from server!')
|
|
13
|
+
* })
|
|
14
|
+
*/
|
|
15
|
+
declare function createWebSocketLinkHandler(url: Path): {
|
|
16
|
+
clients: Set<WebSocketClientConnectionProtocol>;
|
|
17
|
+
on<K extends "connection">(event: K, listener: (...args: WebSocketHandlerEventMap[K]) => void): WebSocketHandler;
|
|
18
|
+
/**
|
|
19
|
+
* Broadcasts the given data to all WebSocket clients.
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* const service = ws.link('wss://example.com')
|
|
23
|
+
* service.on('connection', () => {
|
|
24
|
+
* service.broadcast('hello, everyone!')
|
|
25
|
+
* })
|
|
26
|
+
*/
|
|
27
|
+
broadcast(data: WebSocketData): void;
|
|
28
|
+
/**
|
|
29
|
+
* Broadcasts the given data to all WebSocket clients
|
|
30
|
+
* except the ones provided in the `clients` argument.
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* const service = ws.link('wss://example.com')
|
|
34
|
+
* service.on('connection', ({ client }) => {
|
|
35
|
+
* service.broadcastExcept(client, 'hi, the rest of you!')
|
|
36
|
+
* })
|
|
37
|
+
*/
|
|
38
|
+
broadcastExcept(clients: WebSocketClientConnectionProtocol | Array<WebSocketClientConnectionProtocol>, data: WebSocketData): void;
|
|
39
|
+
};
|
|
40
|
+
declare const ws: {
|
|
41
|
+
link: typeof createWebSocketLinkHandler;
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
export { ws };
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var ws_exports = {};
|
|
20
|
+
__export(ws_exports, {
|
|
21
|
+
ws: () => ws
|
|
22
|
+
});
|
|
23
|
+
module.exports = __toCommonJS(ws_exports);
|
|
24
|
+
var import_outvariant = require("outvariant");
|
|
25
|
+
var import_WebSocketHandler = require("../handlers/WebSocketHandler.js");
|
|
26
|
+
var import_matchRequestUrl = require("../utils/matching/matchRequestUrl.js");
|
|
27
|
+
var import_WebSocketClientManager = require("./WebSocketClientManager.js");
|
|
28
|
+
const wsBroadcastChannel = new BroadcastChannel("msw:ws-client-manager");
|
|
29
|
+
function createWebSocketLinkHandler(url) {
|
|
30
|
+
(0, import_outvariant.invariant)(url, "Expected a WebSocket server URL but got undefined");
|
|
31
|
+
(0, import_outvariant.invariant)(
|
|
32
|
+
(0, import_matchRequestUrl.isPath)(url),
|
|
33
|
+
"Expected a WebSocket server URL but got %s",
|
|
34
|
+
typeof url
|
|
35
|
+
);
|
|
36
|
+
const clientManager = new import_WebSocketClientManager.WebSocketClientManager(wsBroadcastChannel);
|
|
37
|
+
return {
|
|
38
|
+
clients: clientManager.clients,
|
|
39
|
+
on(event, listener) {
|
|
40
|
+
const handler = new import_WebSocketHandler.WebSocketHandler(url);
|
|
41
|
+
handler[import_WebSocketHandler.kEmitter].on("connection", ({ client }) => {
|
|
42
|
+
clientManager.addConnection(client);
|
|
43
|
+
});
|
|
44
|
+
handler[import_WebSocketHandler.kEmitter].on(event, listener);
|
|
45
|
+
return handler;
|
|
46
|
+
},
|
|
47
|
+
/**
|
|
48
|
+
* Broadcasts the given data to all WebSocket clients.
|
|
49
|
+
*
|
|
50
|
+
* @example
|
|
51
|
+
* const service = ws.link('wss://example.com')
|
|
52
|
+
* service.on('connection', () => {
|
|
53
|
+
* service.broadcast('hello, everyone!')
|
|
54
|
+
* })
|
|
55
|
+
*/
|
|
56
|
+
broadcast(data) {
|
|
57
|
+
this.broadcastExcept([], data);
|
|
58
|
+
},
|
|
59
|
+
/**
|
|
60
|
+
* Broadcasts the given data to all WebSocket clients
|
|
61
|
+
* except the ones provided in the `clients` argument.
|
|
62
|
+
*
|
|
63
|
+
* @example
|
|
64
|
+
* const service = ws.link('wss://example.com')
|
|
65
|
+
* service.on('connection', ({ client }) => {
|
|
66
|
+
* service.broadcastExcept(client, 'hi, the rest of you!')
|
|
67
|
+
* })
|
|
68
|
+
*/
|
|
69
|
+
broadcastExcept(clients, data) {
|
|
70
|
+
const ignoreClients = Array.prototype.concat(clients).map((client) => client.id);
|
|
71
|
+
clientManager.clients.forEach((otherClient) => {
|
|
72
|
+
if (!ignoreClients.includes(otherClient.id)) {
|
|
73
|
+
otherClient.send(data);
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
const ws = {
|
|
80
|
+
link: createWebSocketLinkHandler
|
|
81
|
+
};
|
|
82
|
+
//# sourceMappingURL=ws.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/core/ws/ws.ts"],"sourcesContent":["import { invariant } from 'outvariant'\nimport type {\n WebSocketClientConnectionProtocol,\n WebSocketData,\n} from '@mswjs/interceptors/WebSocket'\nimport {\n WebSocketHandler,\n kEmitter,\n type WebSocketHandlerEventMap,\n} from '../handlers/WebSocketHandler'\nimport { Path, isPath } from '../utils/matching/matchRequestUrl'\nimport { WebSocketClientManager } from './WebSocketClientManager'\n\nconst wsBroadcastChannel = new BroadcastChannel('msw:ws-client-manager')\n\n/**\n * Intercepts outgoing WebSocket connections to the given URL.\n *\n * @example\n * const chat = ws.link('wss://chat.example.com')\n * chat.on('connection', ({ client }) => {\n * client.send('hello from server!')\n * })\n */\nfunction createWebSocketLinkHandler(url: Path) {\n invariant(url, 'Expected a WebSocket server URL but got undefined')\n\n invariant(\n isPath(url),\n 'Expected a WebSocket server URL but got %s',\n typeof url,\n )\n\n const clientManager = new WebSocketClientManager(wsBroadcastChannel)\n\n return {\n clients: clientManager.clients,\n on<K extends keyof WebSocketHandlerEventMap>(\n event: K,\n listener: (...args: WebSocketHandlerEventMap[K]) => void,\n ): WebSocketHandler {\n const handler = new WebSocketHandler(url)\n\n // Add the connection event listener for when the\n // handler matches and emits a connection event.\n // When that happens, store that connection in the\n // set of all connections for reference.\n handler[kEmitter].on('connection', ({ client }) => {\n clientManager.addConnection(client)\n })\n\n // The \"handleWebSocketEvent\" function will invoke\n // the \"run()\" method on the WebSocketHandler.\n // If the handler matches, it will emit the \"connection\"\n // event. Attach the user-defined listener to that event.\n handler[kEmitter].on(event, listener)\n\n return handler\n },\n\n /**\n * Broadcasts the given data to all WebSocket clients.\n *\n * @example\n * const service = ws.link('wss://example.com')\n * service.on('connection', () => {\n * service.broadcast('hello, everyone!')\n * })\n */\n broadcast(data: WebSocketData): void {\n // This will invoke \"send()\" on the immediate clients\n // in this runtime and post a message to the broadcast channel\n // to trigger send for the clients in other runtimes.\n this.broadcastExcept([], data)\n },\n\n /**\n * Broadcasts the given data to all WebSocket clients\n * except the ones provided in the `clients` argument.\n *\n * @example\n * const service = ws.link('wss://example.com')\n * service.on('connection', ({ client }) => {\n * service.broadcastExcept(client, 'hi, the rest of you!')\n * })\n */\n broadcastExcept(\n clients:\n | WebSocketClientConnectionProtocol\n | Array<WebSocketClientConnectionProtocol>,\n data: WebSocketData,\n ): void {\n const ignoreClients = Array.prototype\n .concat(clients)\n .map((client) => client.id)\n\n clientManager.clients.forEach((otherClient) => {\n if (!ignoreClients.includes(otherClient.id)) {\n otherClient.send(data)\n }\n })\n },\n }\n}\n\nexport const ws = {\n link: createWebSocketLinkHandler,\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,wBAA0B;AAK1B,8BAIO;AACP,6BAA6B;AAC7B,oCAAuC;AAEvC,MAAM,qBAAqB,IAAI,iBAAiB,uBAAuB;AAWvE,SAAS,2BAA2B,KAAW;AAC7C,mCAAU,KAAK,mDAAmD;AAElE;AAAA,QACE,+BAAO,GAAG;AAAA,IACV;AAAA,IACA,OAAO;AAAA,EACT;AAEA,QAAM,gBAAgB,IAAI,qDAAuB,kBAAkB;AAEnE,SAAO;AAAA,IACL,SAAS,cAAc;AAAA,IACvB,GACE,OACA,UACkB;AAClB,YAAM,UAAU,IAAI,yCAAiB,GAAG;AAMxC,cAAQ,gCAAQ,EAAE,GAAG,cAAc,CAAC,EAAE,OAAO,MAAM;AACjD,sBAAc,cAAc,MAAM;AAAA,MACpC,CAAC;AAMD,cAAQ,gCAAQ,EAAE,GAAG,OAAO,QAAQ;AAEpC,aAAO;AAAA,IACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAWA,UAAU,MAA2B;AAInC,WAAK,gBAAgB,CAAC,GAAG,IAAI;AAAA,IAC/B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAYA,gBACE,SAGA,MACM;AACN,YAAM,gBAAgB,MAAM,UACzB,OAAO,OAAO,EACd,IAAI,CAAC,WAAW,OAAO,EAAE;AAE5B,oBAAc,QAAQ,QAAQ,CAAC,gBAAgB;AAC7C,YAAI,CAAC,cAAc,SAAS,YAAY,EAAE,GAAG;AAC3C,sBAAY,KAAK,IAAI;AAAA,QACvB;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AACF;AAEO,MAAM,KAAK;AAAA,EAChB,MAAM;AACR;","names":[]}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { invariant } from "outvariant";
|
|
2
|
+
import {
|
|
3
|
+
WebSocketHandler,
|
|
4
|
+
kEmitter
|
|
5
|
+
} from '../handlers/WebSocketHandler.mjs';
|
|
6
|
+
import { isPath } from '../utils/matching/matchRequestUrl.mjs';
|
|
7
|
+
import { WebSocketClientManager } from './WebSocketClientManager.mjs';
|
|
8
|
+
const wsBroadcastChannel = new BroadcastChannel("msw:ws-client-manager");
|
|
9
|
+
function createWebSocketLinkHandler(url) {
|
|
10
|
+
invariant(url, "Expected a WebSocket server URL but got undefined");
|
|
11
|
+
invariant(
|
|
12
|
+
isPath(url),
|
|
13
|
+
"Expected a WebSocket server URL but got %s",
|
|
14
|
+
typeof url
|
|
15
|
+
);
|
|
16
|
+
const clientManager = new WebSocketClientManager(wsBroadcastChannel);
|
|
17
|
+
return {
|
|
18
|
+
clients: clientManager.clients,
|
|
19
|
+
on(event, listener) {
|
|
20
|
+
const handler = new WebSocketHandler(url);
|
|
21
|
+
handler[kEmitter].on("connection", ({ client }) => {
|
|
22
|
+
clientManager.addConnection(client);
|
|
23
|
+
});
|
|
24
|
+
handler[kEmitter].on(event, listener);
|
|
25
|
+
return handler;
|
|
26
|
+
},
|
|
27
|
+
/**
|
|
28
|
+
* Broadcasts the given data to all WebSocket clients.
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* const service = ws.link('wss://example.com')
|
|
32
|
+
* service.on('connection', () => {
|
|
33
|
+
* service.broadcast('hello, everyone!')
|
|
34
|
+
* })
|
|
35
|
+
*/
|
|
36
|
+
broadcast(data) {
|
|
37
|
+
this.broadcastExcept([], data);
|
|
38
|
+
},
|
|
39
|
+
/**
|
|
40
|
+
* Broadcasts the given data to all WebSocket clients
|
|
41
|
+
* except the ones provided in the `clients` argument.
|
|
42
|
+
*
|
|
43
|
+
* @example
|
|
44
|
+
* const service = ws.link('wss://example.com')
|
|
45
|
+
* service.on('connection', ({ client }) => {
|
|
46
|
+
* service.broadcastExcept(client, 'hi, the rest of you!')
|
|
47
|
+
* })
|
|
48
|
+
*/
|
|
49
|
+
broadcastExcept(clients, data) {
|
|
50
|
+
const ignoreClients = Array.prototype.concat(clients).map((client) => client.id);
|
|
51
|
+
clientManager.clients.forEach((otherClient) => {
|
|
52
|
+
if (!ignoreClients.includes(otherClient.id)) {
|
|
53
|
+
otherClient.send(data);
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
const ws = {
|
|
60
|
+
link: createWebSocketLinkHandler
|
|
61
|
+
};
|
|
62
|
+
export {
|
|
63
|
+
ws
|
|
64
|
+
};
|
|
65
|
+
//# sourceMappingURL=ws.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/core/ws/ws.ts"],"sourcesContent":["import { invariant } from 'outvariant'\nimport type {\n WebSocketClientConnectionProtocol,\n WebSocketData,\n} from '@mswjs/interceptors/WebSocket'\nimport {\n WebSocketHandler,\n kEmitter,\n type WebSocketHandlerEventMap,\n} from '../handlers/WebSocketHandler'\nimport { Path, isPath } from '../utils/matching/matchRequestUrl'\nimport { WebSocketClientManager } from './WebSocketClientManager'\n\nconst wsBroadcastChannel = new BroadcastChannel('msw:ws-client-manager')\n\n/**\n * Intercepts outgoing WebSocket connections to the given URL.\n *\n * @example\n * const chat = ws.link('wss://chat.example.com')\n * chat.on('connection', ({ client }) => {\n * client.send('hello from server!')\n * })\n */\nfunction createWebSocketLinkHandler(url: Path) {\n invariant(url, 'Expected a WebSocket server URL but got undefined')\n\n invariant(\n isPath(url),\n 'Expected a WebSocket server URL but got %s',\n typeof url,\n )\n\n const clientManager = new WebSocketClientManager(wsBroadcastChannel)\n\n return {\n clients: clientManager.clients,\n on<K extends keyof WebSocketHandlerEventMap>(\n event: K,\n listener: (...args: WebSocketHandlerEventMap[K]) => void,\n ): WebSocketHandler {\n const handler = new WebSocketHandler(url)\n\n // Add the connection event listener for when the\n // handler matches and emits a connection event.\n // When that happens, store that connection in the\n // set of all connections for reference.\n handler[kEmitter].on('connection', ({ client }) => {\n clientManager.addConnection(client)\n })\n\n // The \"handleWebSocketEvent\" function will invoke\n // the \"run()\" method on the WebSocketHandler.\n // If the handler matches, it will emit the \"connection\"\n // event. Attach the user-defined listener to that event.\n handler[kEmitter].on(event, listener)\n\n return handler\n },\n\n /**\n * Broadcasts the given data to all WebSocket clients.\n *\n * @example\n * const service = ws.link('wss://example.com')\n * service.on('connection', () => {\n * service.broadcast('hello, everyone!')\n * })\n */\n broadcast(data: WebSocketData): void {\n // This will invoke \"send()\" on the immediate clients\n // in this runtime and post a message to the broadcast channel\n // to trigger send for the clients in other runtimes.\n this.broadcastExcept([], data)\n },\n\n /**\n * Broadcasts the given data to all WebSocket clients\n * except the ones provided in the `clients` argument.\n *\n * @example\n * const service = ws.link('wss://example.com')\n * service.on('connection', ({ client }) => {\n * service.broadcastExcept(client, 'hi, the rest of you!')\n * })\n */\n broadcastExcept(\n clients:\n | WebSocketClientConnectionProtocol\n | Array<WebSocketClientConnectionProtocol>,\n data: WebSocketData,\n ): void {\n const ignoreClients = Array.prototype\n .concat(clients)\n .map((client) => client.id)\n\n clientManager.clients.forEach((otherClient) => {\n if (!ignoreClients.includes(otherClient.id)) {\n otherClient.send(data)\n }\n })\n },\n }\n}\n\nexport const ws = {\n link: createWebSocketLinkHandler,\n}\n"],"mappings":"AAAA,SAAS,iBAAiB;AAK1B;AAAA,EACE;AAAA,EACA;AAAA,OAEK;AACP,SAAe,cAAc;AAC7B,SAAS,8BAA8B;AAEvC,MAAM,qBAAqB,IAAI,iBAAiB,uBAAuB;AAWvE,SAAS,2BAA2B,KAAW;AAC7C,YAAU,KAAK,mDAAmD;AAElE;AAAA,IACE,OAAO,GAAG;AAAA,IACV;AAAA,IACA,OAAO;AAAA,EACT;AAEA,QAAM,gBAAgB,IAAI,uBAAuB,kBAAkB;AAEnE,SAAO;AAAA,IACL,SAAS,cAAc;AAAA,IACvB,GACE,OACA,UACkB;AAClB,YAAM,UAAU,IAAI,iBAAiB,GAAG;AAMxC,cAAQ,QAAQ,EAAE,GAAG,cAAc,CAAC,EAAE,OAAO,MAAM;AACjD,sBAAc,cAAc,MAAM;AAAA,MACpC,CAAC;AAMD,cAAQ,QAAQ,EAAE,GAAG,OAAO,QAAQ;AAEpC,aAAO;AAAA,IACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAWA,UAAU,MAA2B;AAInC,WAAK,gBAAgB,CAAC,GAAG,IAAI;AAAA,IAC/B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAYA,gBACE,SAGA,MACM;AACN,YAAM,gBAAgB,MAAM,UACzB,OAAO,OAAO,EACd,IAAI,CAAC,WAAW,OAAO,EAAE;AAE5B,oBAAc,QAAQ,QAAQ,CAAC,gBAAgB;AAC7C,YAAI,CAAC,cAAc,SAAS,YAAY,EAAE,GAAG;AAC3C,sBAAY,KAAK,IAAI;AAAA,QACvB;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AACF;AAEO,MAAM,KAAK;AAAA,EAChB,MAAM;AACR;","names":[]}
|