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.
Files changed (129) hide show
  1. package/cli/init.js +0 -0
  2. package/config/scripts/postinstall.js +0 -0
  3. package/lib/browser/index.d.mts +7 -6
  4. package/lib/browser/index.d.ts +7 -6
  5. package/lib/browser/index.js +32 -15
  6. package/lib/browser/index.js.map +1 -1
  7. package/lib/browser/index.mjs +32 -15
  8. package/lib/browser/index.mjs.map +1 -1
  9. package/lib/core/{GraphQLHandler-jOzqbxSK.d.ts → GraphQLHandler-Cbu12sb0.d.ts} +1 -1
  10. package/lib/core/{GraphQLHandler-AenIUdwE.d.mts → GraphQLHandler-QGQY_9Rc.d.mts} +1 -1
  11. package/lib/core/{HttpResponse-wcp03c7-.d.mts → HttpResponse-BWB1yDNM.d.mts} +2 -2
  12. package/lib/core/{HttpResponse-_514VQ9z.d.ts → HttpResponse-DeJBWGN5.d.ts} +2 -2
  13. package/lib/core/HttpResponse.d.mts +1 -1
  14. package/lib/core/HttpResponse.d.ts +1 -1
  15. package/lib/core/SetupApi.d.mts +15 -12
  16. package/lib/core/SetupApi.d.ts +15 -12
  17. package/lib/core/SetupApi.js +3 -1
  18. package/lib/core/SetupApi.js.map +1 -1
  19. package/lib/core/SetupApi.mjs +3 -1
  20. package/lib/core/SetupApi.mjs.map +1 -1
  21. package/lib/core/getResponse.d.mts +1 -1
  22. package/lib/core/getResponse.d.ts +1 -1
  23. package/lib/core/graphql.d.mts +2 -2
  24. package/lib/core/graphql.d.ts +2 -2
  25. package/lib/core/handlers/GraphQLHandler.d.mts +2 -2
  26. package/lib/core/handlers/GraphQLHandler.d.ts +2 -2
  27. package/lib/core/handlers/HttpHandler.d.mts +1 -1
  28. package/lib/core/handlers/HttpHandler.d.ts +1 -1
  29. package/lib/core/handlers/RequestHandler.d.mts +1 -1
  30. package/lib/core/handlers/RequestHandler.d.ts +1 -1
  31. package/lib/core/handlers/WebSocketHandler.d.mts +38 -0
  32. package/lib/core/handlers/WebSocketHandler.d.ts +38 -0
  33. package/lib/core/handlers/WebSocketHandler.js +65 -0
  34. package/lib/core/handlers/WebSocketHandler.js.map +1 -0
  35. package/lib/core/handlers/WebSocketHandler.mjs +47 -0
  36. package/lib/core/handlers/WebSocketHandler.mjs.map +1 -0
  37. package/lib/core/http.d.mts +1 -1
  38. package/lib/core/http.d.ts +1 -1
  39. package/lib/core/index.d.mts +5 -2
  40. package/lib/core/index.d.ts +5 -2
  41. package/lib/core/index.js +3 -1
  42. package/lib/core/index.js.map +1 -1
  43. package/lib/core/index.mjs +3 -1
  44. package/lib/core/index.mjs.map +1 -1
  45. package/lib/core/passthrough.d.mts +1 -1
  46. package/lib/core/passthrough.d.ts +1 -1
  47. package/lib/core/utils/HttpResponse/decorators.d.mts +1 -1
  48. package/lib/core/utils/HttpResponse/decorators.d.ts +1 -1
  49. package/lib/core/utils/executeHandlers.d.mts +1 -1
  50. package/lib/core/utils/executeHandlers.d.ts +1 -1
  51. package/lib/core/utils/executeHandlers.js +4 -0
  52. package/lib/core/utils/executeHandlers.js.map +1 -1
  53. package/lib/core/utils/executeHandlers.mjs +6 -0
  54. package/lib/core/utils/executeHandlers.mjs.map +1 -1
  55. package/lib/core/utils/handleRequest.d.mts +2 -2
  56. package/lib/core/utils/handleRequest.d.ts +2 -2
  57. package/lib/core/utils/handleRequest.js.map +1 -1
  58. package/lib/core/utils/handleRequest.mjs.map +1 -1
  59. package/lib/core/utils/handleWebSocketEvent.d.mts +10 -0
  60. package/lib/core/utils/handleWebSocketEvent.d.ts +10 -0
  61. package/lib/core/utils/handleWebSocketEvent.js +56 -0
  62. package/lib/core/utils/handleWebSocketEvent.js.map +1 -0
  63. package/lib/core/utils/handleWebSocketEvent.mjs +40 -0
  64. package/lib/core/utils/handleWebSocketEvent.mjs.map +1 -0
  65. package/lib/core/utils/internal/parseGraphQLRequest.d.mts +2 -2
  66. package/lib/core/utils/internal/parseGraphQLRequest.d.ts +2 -2
  67. package/lib/core/utils/internal/parseMultipartData.d.mts +1 -1
  68. package/lib/core/utils/internal/parseMultipartData.d.ts +1 -1
  69. package/lib/core/utils/internal/requestHandlerUtils.d.mts +1 -1
  70. package/lib/core/utils/internal/requestHandlerUtils.d.ts +1 -1
  71. package/lib/core/utils/matching/matchRequestUrl.d.mts +2 -1
  72. package/lib/core/utils/matching/matchRequestUrl.d.ts +2 -1
  73. package/lib/core/utils/matching/matchRequestUrl.js +4 -0
  74. package/lib/core/utils/matching/matchRequestUrl.js.map +1 -1
  75. package/lib/core/utils/matching/matchRequestUrl.mjs +4 -0
  76. package/lib/core/utils/matching/matchRequestUrl.mjs.map +1 -1
  77. package/lib/core/ws/WebSocketClientManager.d.mts +64 -0
  78. package/lib/core/ws/WebSocketClientManager.d.ts +64 -0
  79. package/lib/core/ws/WebSocketClientManager.js +123 -0
  80. package/lib/core/ws/WebSocketClientManager.js.map +1 -0
  81. package/lib/core/ws/WebSocketClientManager.mjs +103 -0
  82. package/lib/core/ws/WebSocketClientManager.mjs.map +1 -0
  83. package/lib/core/ws/webSocketInterceptor.d.mts +5 -0
  84. package/lib/core/ws/webSocketInterceptor.d.ts +5 -0
  85. package/lib/core/ws/webSocketInterceptor.js +26 -0
  86. package/lib/core/ws/webSocketInterceptor.js.map +1 -0
  87. package/lib/core/ws/webSocketInterceptor.mjs +6 -0
  88. package/lib/core/ws/webSocketInterceptor.mjs.map +1 -0
  89. package/lib/core/ws/ws.d.mts +44 -0
  90. package/lib/core/ws/ws.d.ts +44 -0
  91. package/lib/core/ws/ws.js +82 -0
  92. package/lib/core/ws/ws.js.map +1 -0
  93. package/lib/core/ws/ws.mjs +65 -0
  94. package/lib/core/ws/ws.mjs.map +1 -0
  95. package/lib/iife/index.js +703 -17
  96. package/lib/iife/index.js.map +1 -1
  97. package/lib/mockServiceWorker.js +1 -1
  98. package/lib/native/index.d.mts +6 -5
  99. package/lib/native/index.d.ts +6 -5
  100. package/lib/native/index.js +7 -0
  101. package/lib/native/index.js.map +1 -1
  102. package/lib/native/index.mjs +7 -0
  103. package/lib/native/index.mjs.map +1 -1
  104. package/lib/node/index.d.mts +8 -7
  105. package/lib/node/index.d.ts +8 -7
  106. package/lib/node/index.js +7 -0
  107. package/lib/node/index.js.map +1 -1
  108. package/lib/node/index.mjs +7 -0
  109. package/lib/node/index.mjs.map +1 -1
  110. package/package.json +29 -24
  111. package/src/browser/setupWorker/glossary.ts +10 -10
  112. package/src/browser/setupWorker/setupWorker.ts +17 -3
  113. package/src/core/SetupApi.ts +28 -20
  114. package/src/core/handlers/WebSocketHandler.ts +89 -0
  115. package/src/core/index.ts +3 -0
  116. package/src/core/utils/executeHandlers.ts +6 -2
  117. package/src/core/utils/handleRequest.ts +1 -2
  118. package/src/core/utils/handleWebSocketEvent.ts +49 -0
  119. package/src/core/utils/matching/matchRequestUrl.test.ts +44 -0
  120. package/src/core/utils/matching/matchRequestUrl.ts +4 -0
  121. package/src/core/ws/WebSocketClientManager.test.ts +159 -0
  122. package/src/core/ws/WebSocketClientManager.ts +170 -0
  123. package/src/core/ws/webSocketInterceptor.ts +3 -0
  124. package/src/core/ws/ws.test.ts +23 -0
  125. package/src/core/ws/ws.ts +108 -0
  126. package/src/node/SetupServerApi.ts +8 -7
  127. package/src/node/SetupServerCommonApi.ts +10 -1
  128. package/src/node/glossary.ts +5 -7
  129. 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,5 @@
1
+ import { WebSocketInterceptor } from '@mswjs/interceptors/WebSocket';
2
+
3
+ declare const webSocketInterceptor: WebSocketInterceptor;
4
+
5
+ export { webSocketInterceptor };
@@ -0,0 +1,5 @@
1
+ import { WebSocketInterceptor } from '@mswjs/interceptors/WebSocket';
2
+
3
+ declare const webSocketInterceptor: WebSocketInterceptor;
4
+
5
+ export { webSocketInterceptor };
@@ -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,6 @@
1
+ import { WebSocketInterceptor } from "@mswjs/interceptors/WebSocket";
2
+ const webSocketInterceptor = new WebSocketInterceptor();
3
+ export {
4
+ webSocketInterceptor
5
+ };
6
+ //# sourceMappingURL=webSocketInterceptor.mjs.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,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":[]}