msw 2.3.0-ws.rc-5 → 2.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (189) hide show
  1. package/cli/init.js +0 -0
  2. package/config/scripts/postinstall.js +0 -0
  3. package/lib/browser/index.d.mts +6 -7
  4. package/lib/browser/index.d.ts +6 -7
  5. package/lib/browser/index.js +156 -81
  6. package/lib/browser/index.js.map +1 -1
  7. package/lib/browser/index.mjs +156 -81
  8. package/lib/browser/index.mjs.map +1 -1
  9. package/lib/core/{GraphQLHandler-DGyzNtRQ.d.ts → GraphQLHandler-COiPfZ8k.d.ts} +1 -1
  10. package/lib/core/{GraphQLHandler-CzcXr7At.d.mts → GraphQLHandler-Dq_WRbKe.d.mts} +1 -1
  11. package/lib/core/{HttpResponse-BOzDwzB6.d.ts → HttpResponse-B07UKAkU.d.ts} +2 -2
  12. package/lib/core/{HttpResponse-CSyJ1cbO.d.mts → HttpResponse-C7niBMwb.d.mts} +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 +12 -15
  16. package/lib/core/SetupApi.d.ts +12 -15
  17. package/lib/core/SetupApi.js +1 -3
  18. package/lib/core/SetupApi.js.map +1 -1
  19. package/lib/core/SetupApi.mjs +1 -3
  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/http.d.mts +1 -1
  32. package/lib/core/http.d.ts +1 -1
  33. package/lib/core/index.d.mts +2 -5
  34. package/lib/core/index.d.ts +2 -5
  35. package/lib/core/index.js +1 -5
  36. package/lib/core/index.js.map +1 -1
  37. package/lib/core/index.mjs +1 -7
  38. package/lib/core/index.mjs.map +1 -1
  39. package/lib/core/passthrough.d.mts +1 -1
  40. package/lib/core/passthrough.d.ts +1 -1
  41. package/lib/core/utils/HttpResponse/decorators.d.mts +1 -1
  42. package/lib/core/utils/HttpResponse/decorators.d.ts +1 -1
  43. package/lib/core/utils/executeHandlers.d.mts +1 -1
  44. package/lib/core/utils/executeHandlers.d.ts +1 -1
  45. package/lib/core/utils/executeHandlers.js +0 -4
  46. package/lib/core/utils/executeHandlers.js.map +1 -1
  47. package/lib/core/utils/executeHandlers.mjs +0 -6
  48. package/lib/core/utils/executeHandlers.mjs.map +1 -1
  49. package/lib/core/utils/handleRequest.d.mts +2 -2
  50. package/lib/core/utils/handleRequest.d.ts +2 -2
  51. package/lib/core/utils/handleRequest.js.map +1 -1
  52. package/lib/core/utils/handleRequest.mjs.map +1 -1
  53. package/lib/core/utils/internal/Disposable.d.mts +2 -2
  54. package/lib/core/utils/internal/Disposable.d.ts +2 -2
  55. package/lib/core/utils/internal/Disposable.js +5 -2
  56. package/lib/core/utils/internal/Disposable.js.map +1 -1
  57. package/lib/core/utils/internal/Disposable.mjs +5 -2
  58. package/lib/core/utils/internal/Disposable.mjs.map +1 -1
  59. package/lib/core/utils/internal/devUtils.d.mts +10 -1
  60. package/lib/core/utils/internal/devUtils.d.ts +10 -1
  61. package/lib/core/utils/internal/devUtils.js +7 -0
  62. package/lib/core/utils/internal/devUtils.js.map +1 -1
  63. package/lib/core/utils/internal/devUtils.mjs +7 -0
  64. package/lib/core/utils/internal/devUtils.mjs.map +1 -1
  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/logging/getTimestamp.d.mts +1 -4
  72. package/lib/core/utils/logging/getTimestamp.d.ts +1 -4
  73. package/lib/core/utils/logging/getTimestamp.js +2 -6
  74. package/lib/core/utils/logging/getTimestamp.js.map +1 -1
  75. package/lib/core/utils/logging/getTimestamp.mjs +2 -6
  76. package/lib/core/utils/logging/getTimestamp.mjs.map +1 -1
  77. package/lib/core/utils/matching/matchRequestUrl.d.mts +1 -2
  78. package/lib/core/utils/matching/matchRequestUrl.d.ts +1 -2
  79. package/lib/core/utils/matching/matchRequestUrl.js +0 -4
  80. package/lib/core/utils/matching/matchRequestUrl.js.map +1 -1
  81. package/lib/core/utils/matching/matchRequestUrl.mjs +0 -4
  82. package/lib/core/utils/matching/matchRequestUrl.mjs.map +1 -1
  83. package/lib/core/utils/request/onUnhandledRequest.js +3 -3
  84. package/lib/core/utils/request/onUnhandledRequest.js.map +1 -1
  85. package/lib/core/utils/request/onUnhandledRequest.mjs +4 -4
  86. package/lib/core/utils/request/onUnhandledRequest.mjs.map +1 -1
  87. package/lib/iife/index.js +177 -1063
  88. package/lib/iife/index.js.map +1 -1
  89. package/lib/mockServiceWorker.js +1 -1
  90. package/lib/native/index.d.mts +5 -6
  91. package/lib/native/index.d.ts +5 -6
  92. package/lib/native/index.js +5 -13
  93. package/lib/native/index.js.map +1 -1
  94. package/lib/native/index.mjs +6 -14
  95. package/lib/native/index.mjs.map +1 -1
  96. package/lib/node/index.d.mts +7 -8
  97. package/lib/node/index.d.ts +7 -8
  98. package/lib/node/index.js +5 -13
  99. package/lib/node/index.js.map +1 -1
  100. package/lib/node/index.mjs +6 -14
  101. package/lib/node/index.mjs.map +1 -1
  102. package/package.json +36 -29
  103. package/src/browser/setupWorker/glossary.ts +10 -10
  104. package/src/browser/setupWorker/setupWorker.ts +3 -34
  105. package/src/core/SetupApi.ts +20 -28
  106. package/src/core/index.ts +1 -8
  107. package/src/core/utils/executeHandlers.ts +2 -6
  108. package/src/core/utils/handleRequest.ts +2 -1
  109. package/src/core/utils/internal/Disposable.ts +6 -3
  110. package/src/core/utils/internal/devUtils.test.ts +21 -0
  111. package/src/core/utils/internal/devUtils.ts +13 -0
  112. package/src/core/utils/logging/getTimestamp.test.ts +6 -20
  113. package/src/core/utils/logging/getTimestamp.ts +6 -11
  114. package/src/core/utils/matching/matchRequestUrl.test.ts +0 -44
  115. package/src/core/utils/matching/matchRequestUrl.ts +0 -4
  116. package/src/core/utils/request/onUnhandledRequest.test.ts +30 -4
  117. package/src/core/utils/request/onUnhandledRequest.ts +4 -4
  118. package/src/node/SetupServerApi.ts +7 -8
  119. package/src/node/SetupServerCommonApi.ts +8 -15
  120. package/src/node/glossary.ts +7 -5
  121. package/src/node/setupServer.ts +1 -2
  122. package/lib/core/handlers/WebSocketHandler.d.mts +0 -32
  123. package/lib/core/handlers/WebSocketHandler.d.ts +0 -32
  124. package/lib/core/handlers/WebSocketHandler.js +0 -62
  125. package/lib/core/handlers/WebSocketHandler.js.map +0 -1
  126. package/lib/core/handlers/WebSocketHandler.mjs +0 -44
  127. package/lib/core/handlers/WebSocketHandler.mjs.map +0 -1
  128. package/lib/core/ws/WebSocketClientManager.d.mts +0 -64
  129. package/lib/core/ws/WebSocketClientManager.d.ts +0 -64
  130. package/lib/core/ws/WebSocketClientManager.js +0 -123
  131. package/lib/core/ws/WebSocketClientManager.js.map +0 -1
  132. package/lib/core/ws/WebSocketClientManager.mjs +0 -103
  133. package/lib/core/ws/WebSocketClientManager.mjs.map +0 -1
  134. package/lib/core/ws/handleWebSocketEvent.d.mts +0 -16
  135. package/lib/core/ws/handleWebSocketEvent.d.ts +0 -16
  136. package/lib/core/ws/handleWebSocketEvent.js +0 -56
  137. package/lib/core/ws/handleWebSocketEvent.js.map +0 -1
  138. package/lib/core/ws/handleWebSocketEvent.mjs +0 -36
  139. package/lib/core/ws/handleWebSocketEvent.mjs.map +0 -1
  140. package/lib/core/ws/utils/attachWebSocketLogger.d.mts +0 -34
  141. package/lib/core/ws/utils/attachWebSocketLogger.d.ts +0 -34
  142. package/lib/core/ws/utils/attachWebSocketLogger.js +0 -217
  143. package/lib/core/ws/utils/attachWebSocketLogger.js.map +0 -1
  144. package/lib/core/ws/utils/attachWebSocketLogger.mjs +0 -197
  145. package/lib/core/ws/utils/attachWebSocketLogger.mjs.map +0 -1
  146. package/lib/core/ws/utils/getMessageLength.d.mts +0 -11
  147. package/lib/core/ws/utils/getMessageLength.d.ts +0 -11
  148. package/lib/core/ws/utils/getMessageLength.js +0 -33
  149. package/lib/core/ws/utils/getMessageLength.js.map +0 -1
  150. package/lib/core/ws/utils/getMessageLength.mjs +0 -13
  151. package/lib/core/ws/utils/getMessageLength.mjs.map +0 -1
  152. package/lib/core/ws/utils/getPublicData.d.mts +0 -5
  153. package/lib/core/ws/utils/getPublicData.d.ts +0 -5
  154. package/lib/core/ws/utils/getPublicData.js +0 -36
  155. package/lib/core/ws/utils/getPublicData.js.map +0 -1
  156. package/lib/core/ws/utils/getPublicData.mjs +0 -16
  157. package/lib/core/ws/utils/getPublicData.mjs.map +0 -1
  158. package/lib/core/ws/utils/truncateMessage.d.mts +0 -3
  159. package/lib/core/ws/utils/truncateMessage.d.ts +0 -3
  160. package/lib/core/ws/utils/truncateMessage.js +0 -31
  161. package/lib/core/ws/utils/truncateMessage.js.map +0 -1
  162. package/lib/core/ws/utils/truncateMessage.mjs +0 -11
  163. package/lib/core/ws/utils/truncateMessage.mjs.map +0 -1
  164. package/lib/core/ws/webSocketInterceptor.d.mts +0 -5
  165. package/lib/core/ws/webSocketInterceptor.d.ts +0 -5
  166. package/lib/core/ws/webSocketInterceptor.js +0 -26
  167. package/lib/core/ws/webSocketInterceptor.js.map +0 -1
  168. package/lib/core/ws/webSocketInterceptor.mjs +0 -6
  169. package/lib/core/ws/webSocketInterceptor.mjs.map +0 -1
  170. package/lib/core/ws.d.mts +0 -49
  171. package/lib/core/ws.d.ts +0 -49
  172. package/lib/core/ws.js +0 -63
  173. package/lib/core/ws.js.map +0 -1
  174. package/lib/core/ws.mjs +0 -46
  175. package/lib/core/ws.mjs.map +0 -1
  176. package/src/core/handlers/WebSocketHandler.ts +0 -71
  177. package/src/core/ws/WebSocketClientManager.test.ts +0 -159
  178. package/src/core/ws/WebSocketClientManager.ts +0 -170
  179. package/src/core/ws/handleWebSocketEvent.ts +0 -56
  180. package/src/core/ws/utils/attachWebSocketLogger.ts +0 -269
  181. package/src/core/ws/utils/getMessageLength.test.ts +0 -16
  182. package/src/core/ws/utils/getMessageLength.ts +0 -19
  183. package/src/core/ws/utils/getPublicData.test.ts +0 -38
  184. package/src/core/ws/utils/getPublicData.ts +0 -17
  185. package/src/core/ws/utils/truncateMessage.test.ts +0 -12
  186. package/src/core/ws/utils/truncateMessage.ts +0 -9
  187. package/src/core/ws/webSocketInterceptor.ts +0 -3
  188. package/src/core/ws.test.ts +0 -23
  189. package/src/core/ws.ts +0 -122
package/lib/core/ws.js DELETED
@@ -1,63 +0,0 @@
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("./ws/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 to be a valid path 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
- broadcast(data) {
48
- this.broadcastExcept([], data);
49
- },
50
- broadcastExcept(clients, data) {
51
- const ignoreClients = Array.prototype.concat(clients).map((client) => client.id);
52
- clientManager.clients.forEach((otherClient) => {
53
- if (!ignoreClients.includes(otherClient.id)) {
54
- otherClient.send(data);
55
- }
56
- });
57
- }
58
- };
59
- }
60
- const ws = {
61
- link: createWebSocketLinkHandler
62
- };
63
- //# sourceMappingURL=ws.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/core/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 './ws/WebSocketClientManager'\n\nconst wsBroadcastChannel = new BroadcastChannel('msw:ws-client-manager')\n\nexport type WebSocketLink = {\n /**\n * A set of all WebSocket clients connected\n * to this link.\n */\n clients: Set<WebSocketClientConnectionProtocol>\n\n on<EventType extends keyof WebSocketHandlerEventMap>(\n event: EventType,\n listener: (...args: WebSocketHandlerEventMap[EventType]) => void,\n ): WebSocketHandler\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\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}\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): WebSocketLink {\n invariant(url, 'Expected a WebSocket server URL but got undefined')\n\n invariant(\n isPath(url),\n 'Expected a WebSocket server URL to be a valid path but got %s',\n typeof url,\n )\n\n const clientManager = new WebSocketClientManager(wsBroadcastChannel)\n\n return {\n clients: clientManager.clients,\n on(event, listener) {\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 broadcast(data) {\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 broadcastExcept(clients, data) {\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;AAoDvE,SAAS,2BAA2B,KAA0B;AAC5D,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,GAAG,OAAO,UAAU;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,IAEA,UAAU,MAAM;AAId,WAAK,gBAAgB,CAAC,GAAG,IAAI;AAAA,IAC/B;AAAA,IAEA,gBAAgB,SAAS,MAAM;AAC7B,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":[]}
package/lib/core/ws.mjs DELETED
@@ -1,46 +0,0 @@
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 './ws/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 to be a valid path 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
- broadcast(data) {
28
- this.broadcastExcept([], data);
29
- },
30
- broadcastExcept(clients, data) {
31
- const ignoreClients = Array.prototype.concat(clients).map((client) => client.id);
32
- clientManager.clients.forEach((otherClient) => {
33
- if (!ignoreClients.includes(otherClient.id)) {
34
- otherClient.send(data);
35
- }
36
- });
37
- }
38
- };
39
- }
40
- const ws = {
41
- link: createWebSocketLinkHandler
42
- };
43
- export {
44
- ws
45
- };
46
- //# sourceMappingURL=ws.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/core/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 './ws/WebSocketClientManager'\n\nconst wsBroadcastChannel = new BroadcastChannel('msw:ws-client-manager')\n\nexport type WebSocketLink = {\n /**\n * A set of all WebSocket clients connected\n * to this link.\n */\n clients: Set<WebSocketClientConnectionProtocol>\n\n on<EventType extends keyof WebSocketHandlerEventMap>(\n event: EventType,\n listener: (...args: WebSocketHandlerEventMap[EventType]) => void,\n ): WebSocketHandler\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\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}\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): WebSocketLink {\n invariant(url, 'Expected a WebSocket server URL but got undefined')\n\n invariant(\n isPath(url),\n 'Expected a WebSocket server URL to be a valid path but got %s',\n typeof url,\n )\n\n const clientManager = new WebSocketClientManager(wsBroadcastChannel)\n\n return {\n clients: clientManager.clients,\n on(event, listener) {\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 broadcast(data) {\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 broadcastExcept(clients, data) {\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;AAoDvE,SAAS,2BAA2B,KAA0B;AAC5D,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,GAAG,OAAO,UAAU;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,IAEA,UAAU,MAAM;AAId,WAAK,gBAAgB,CAAC,GAAG,IAAI;AAAA,IAC/B;AAAA,IAEA,gBAAgB,SAAS,MAAM;AAC7B,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":[]}
@@ -1,71 +0,0 @@
1
- import { Emitter } from 'strict-event-emitter'
2
- import type { WebSocketConnectionData } from '@mswjs/interceptors/WebSocket'
3
- import {
4
- type Match,
5
- type Path,
6
- type PathParams,
7
- matchRequestUrl,
8
- } from '../utils/matching/matchRequestUrl'
9
- import { getCallFrame } from '../utils/internal/getCallFrame'
10
-
11
- type WebSocketHandlerParsedResult = {
12
- match: Match
13
- }
14
-
15
- export type WebSocketHandlerEventMap = {
16
- connection: [args: WebSocketHandlerConnection]
17
- }
18
-
19
- interface WebSocketHandlerConnection extends WebSocketConnectionData {
20
- params: PathParams
21
- }
22
-
23
- export const kEmitter = Symbol('kEmitter')
24
- export const kDispatchEvent = Symbol('kDispatchEvent')
25
- export const kSender = Symbol('kSender')
26
-
27
- export class WebSocketHandler {
28
- public callFrame?: string
29
-
30
- protected [kEmitter]: Emitter<WebSocketHandlerEventMap>
31
-
32
- constructor(private readonly url: Path) {
33
- this[kEmitter] = new Emitter()
34
- this.callFrame = getCallFrame(new Error())
35
- }
36
-
37
- public parse(args: {
38
- event: MessageEvent<WebSocketConnectionData>
39
- }): WebSocketHandlerParsedResult {
40
- const connection = args.event.data
41
- const match = matchRequestUrl(connection.client.url, this.url)
42
-
43
- return {
44
- match,
45
- }
46
- }
47
-
48
- public predicate(args: {
49
- event: MessageEvent<WebSocketConnectionData>
50
- parsedResult: WebSocketHandlerParsedResult
51
- }): boolean {
52
- return args.parsedResult.match.matches
53
- }
54
-
55
- async [kDispatchEvent](
56
- event: MessageEvent<WebSocketConnectionData>,
57
- ): Promise<void> {
58
- const parsedResult = this.parse({ event })
59
- const connection = event.data
60
-
61
- const resolvedConnection: WebSocketHandlerConnection = {
62
- client: connection.client,
63
- server: connection.server,
64
- params: parsedResult.match.params || {},
65
- }
66
-
67
- // Emit the connection event on the handler.
68
- // This is what the developer adds listeners for.
69
- this[kEmitter].emit('connection', resolvedConnection)
70
- }
71
- }
@@ -1,159 +0,0 @@
1
- /**
2
- * @vitest-environment node-websocket
3
- */
4
- import { randomUUID } from 'node:crypto'
5
- import {
6
- WebSocketClientConnection,
7
- WebSocketTransport,
8
- } from '@mswjs/interceptors/WebSocket'
9
- import {
10
- WebSocketClientManager,
11
- WebSocketBroadcastChannelMessage,
12
- WebSocketRemoteClientConnection,
13
- } from './WebSocketClientManager'
14
-
15
- const channel = new BroadcastChannel('test:channel')
16
- vi.spyOn(channel, 'postMessage')
17
-
18
- const socket = new WebSocket('ws://localhost')
19
- const transport = {
20
- onOutgoing: vi.fn(),
21
- onIncoming: vi.fn(),
22
- onClose: vi.fn(),
23
- send: vi.fn(),
24
- close: vi.fn(),
25
- } satisfies WebSocketTransport
26
-
27
- afterEach(() => {
28
- vi.resetAllMocks()
29
- })
30
-
31
- it('adds a client from this runtime to the list of clients', () => {
32
- const manager = new WebSocketClientManager(channel)
33
- const connection = new WebSocketClientConnection(socket, transport)
34
-
35
- manager.addConnection(connection)
36
-
37
- // Must add the client to the list of clients.
38
- expect(Array.from(manager.clients.values())).toEqual([connection])
39
-
40
- // Must emit the connection open event to notify other runtimes.
41
- expect(channel.postMessage).toHaveBeenCalledWith({
42
- type: 'connection:open',
43
- payload: {
44
- clientId: connection.id,
45
- url: socket.url,
46
- },
47
- } satisfies WebSocketBroadcastChannelMessage)
48
- })
49
-
50
- it('adds a client from another runtime to the list of clients', async () => {
51
- const clientId = randomUUID()
52
- const url = new URL('ws://localhost')
53
- const manager = new WebSocketClientManager(channel)
54
-
55
- channel.dispatchEvent(
56
- new MessageEvent<WebSocketBroadcastChannelMessage>('message', {
57
- data: {
58
- type: 'connection:open',
59
- payload: {
60
- clientId,
61
- url: url.href,
62
- },
63
- },
64
- }),
65
- )
66
-
67
- await vi.waitFor(() => {
68
- expect(Array.from(manager.clients.values())).toEqual([
69
- new WebSocketRemoteClientConnection(clientId, url, channel),
70
- ])
71
- })
72
- })
73
-
74
- it('replays a "send" event coming from another runtime', async () => {
75
- const manager = new WebSocketClientManager(channel)
76
- const connection = new WebSocketClientConnection(socket, transport)
77
- manager.addConnection(connection)
78
- vi.spyOn(connection, 'send')
79
-
80
- // Emulate another runtime signaling this connection to receive data.
81
- channel.dispatchEvent(
82
- new MessageEvent<WebSocketBroadcastChannelMessage>('message', {
83
- data: {
84
- type: 'extraneous:send',
85
- payload: {
86
- clientId: connection.id,
87
- data: 'hello',
88
- },
89
- },
90
- }),
91
- )
92
-
93
- await vi.waitFor(() => {
94
- // Must execute the requested operation on the connection.
95
- expect(connection.send).toHaveBeenCalledWith('hello')
96
- expect(connection.send).toHaveBeenCalledTimes(1)
97
- })
98
- })
99
-
100
- it('replays a "close" event coming from another runtime', async () => {
101
- const manager = new WebSocketClientManager(channel)
102
- const connection = new WebSocketClientConnection(socket, transport)
103
- manager.addConnection(connection)
104
- vi.spyOn(connection, 'close')
105
-
106
- // Emulate another runtime signaling this connection to close.
107
- channel.dispatchEvent(
108
- new MessageEvent<WebSocketBroadcastChannelMessage>('message', {
109
- data: {
110
- type: 'extraneous:close',
111
- payload: {
112
- clientId: connection.id,
113
- code: 1000,
114
- reason: 'Normal closure',
115
- },
116
- },
117
- }),
118
- )
119
-
120
- await vi.waitFor(() => {
121
- // Must execute the requested operation on the connection.
122
- expect(connection.close).toHaveBeenCalledWith(1000, 'Normal closure')
123
- expect(connection.close).toHaveBeenCalledTimes(1)
124
- })
125
- })
126
-
127
- it('removes the extraneous message listener when the connection closes', async () => {
128
- const manager = new WebSocketClientManager(channel)
129
- const connection = new WebSocketClientConnection(socket, transport)
130
- vi.spyOn(connection, 'close').mockImplementationOnce(() => {
131
- /**
132
- * @note This is a nasty hack so we don't have to uncouple
133
- * the connection from transport. Creating a mock transport
134
- * is difficult because it relies on the `WebSocketOverride` class.
135
- * All we care here is that closing the connection triggers
136
- * the transport closure, which it always does.
137
- */
138
- connection['transport'].onClose()
139
- })
140
- vi.spyOn(connection, 'send')
141
-
142
- manager.addConnection(connection)
143
- connection.close()
144
-
145
- // Signals from other runtimes have no effect on the closed connection.
146
- channel.dispatchEvent(
147
- new MessageEvent<WebSocketBroadcastChannelMessage>('message', {
148
- data: {
149
- type: 'extraneous:send',
150
- payload: {
151
- clientId: connection.id,
152
- data: 'hello',
153
- },
154
- },
155
- }),
156
- )
157
-
158
- expect(connection.send).not.toHaveBeenCalled()
159
- })
@@ -1,170 +0,0 @@
1
- import type {
2
- WebSocketData,
3
- WebSocketClientConnection,
4
- WebSocketClientConnectionProtocol,
5
- } from '@mswjs/interceptors/WebSocket'
6
-
7
- export type WebSocketBroadcastChannelMessage =
8
- | {
9
- type: 'connection:open'
10
- payload: {
11
- clientId: string
12
- url: string
13
- }
14
- }
15
- | {
16
- type: 'extraneous:send'
17
- payload: {
18
- clientId: string
19
- data: WebSocketData
20
- }
21
- }
22
- | {
23
- type: 'extraneous:close'
24
- payload: {
25
- clientId: string
26
- code?: number
27
- reason?: string
28
- }
29
- }
30
-
31
- export const kAddByClientId = Symbol('kAddByClientId')
32
-
33
- /**
34
- * A manager responsible for accumulating WebSocket client
35
- * connections across different browser runtimes.
36
- */
37
- export class WebSocketClientManager {
38
- /**
39
- * All active WebSocket client connections.
40
- */
41
- public clients: Set<WebSocketClientConnectionProtocol>
42
-
43
- constructor(private channel: BroadcastChannel) {
44
- this.clients = new Set()
45
-
46
- this.channel.addEventListener('message', (message) => {
47
- const { type, payload } = message.data as WebSocketBroadcastChannelMessage
48
-
49
- switch (type) {
50
- case 'connection:open': {
51
- // When another runtime notifies about a new connection,
52
- // create a connection wrapper class and add it to the set.
53
- this.onRemoteConnection(payload.clientId, new URL(payload.url))
54
- break
55
- }
56
- }
57
- })
58
- }
59
-
60
- /**
61
- * Adds the given `WebSocket` client connection to the set
62
- * of all connections. The given connection is always the complete
63
- * connection object because `addConnection()` is called only
64
- * for the opened connections in the same runtime.
65
- */
66
- public addConnection(client: WebSocketClientConnection): void {
67
- this.clients.add(client)
68
-
69
- // Signal to other runtimes about this connection.
70
- this.channel.postMessage({
71
- type: 'connection:open',
72
- payload: {
73
- clientId: client.id,
74
- url: client.url.toString(),
75
- },
76
- } as WebSocketBroadcastChannelMessage)
77
-
78
- // Instruct the current client how to handle events
79
- // coming from other runtimes (e.g. when calling `.broadcast()`).
80
- const handleExtraneousMessage = (
81
- message: MessageEvent<WebSocketBroadcastChannelMessage>,
82
- ) => {
83
- const { type, payload } = message.data
84
-
85
- // Ignore broadcasted messages for other clients.
86
- if (
87
- typeof payload === 'object' &&
88
- 'clientId' in payload &&
89
- payload.clientId !== client.id
90
- ) {
91
- return
92
- }
93
-
94
- switch (type) {
95
- case 'extraneous:send': {
96
- client.send(payload.data)
97
- break
98
- }
99
-
100
- case 'extraneous:close': {
101
- client.close(payload.code, payload.reason)
102
- break
103
- }
104
- }
105
- }
106
-
107
- const abortController = new AbortController()
108
-
109
- this.channel.addEventListener('message', handleExtraneousMessage, {
110
- signal: abortController.signal,
111
- })
112
-
113
- // Once closed, this connection cannot be operated on.
114
- // This must include the extraneous runtimes as well.
115
- client.addEventListener('close', () => abortController.abort(), {
116
- once: true,
117
- })
118
- }
119
-
120
- /**
121
- * Adds a client connection wrapper to operate with
122
- * WebSocket client connections in other runtimes.
123
- */
124
- private onRemoteConnection(id: string, url: URL): void {
125
- this.clients.add(
126
- // Create a connection-compatible instance that can
127
- // operate with this client from a different runtime
128
- // using the BroadcastChannel messages.
129
- new WebSocketRemoteClientConnection(id, url, this.channel),
130
- )
131
- }
132
- }
133
-
134
- /**
135
- * A wrapper class to operate with WebSocket client connections
136
- * from other runtimes. This class maintains 1-1 public API
137
- * compatibility to the `WebSocketClientConnection` but relies
138
- * on the given `BroadcastChannel` to communicate instructions
139
- * with the client connections from other runtimes.
140
- */
141
- export class WebSocketRemoteClientConnection
142
- implements WebSocketClientConnectionProtocol
143
- {
144
- constructor(
145
- public readonly id: string,
146
- public readonly url: URL,
147
- private channel: BroadcastChannel,
148
- ) {}
149
-
150
- send(data: WebSocketData): void {
151
- this.channel.postMessage({
152
- type: 'extraneous:send',
153
- payload: {
154
- clientId: this.id,
155
- data,
156
- },
157
- } as WebSocketBroadcastChannelMessage)
158
- }
159
-
160
- close(code?: number | undefined, reason?: string | undefined): void {
161
- this.channel.postMessage({
162
- type: 'extraneous:close',
163
- payload: {
164
- clientId: this.id,
165
- code,
166
- reason,
167
- },
168
- } as WebSocketBroadcastChannelMessage)
169
- }
170
- }
@@ -1,56 +0,0 @@
1
- import type { WebSocketConnectionData } from '@mswjs/interceptors/lib/browser/interceptors/WebSocket'
2
- import { RequestHandler } from '../handlers/RequestHandler'
3
- import { WebSocketHandler, kDispatchEvent } from '../handlers/WebSocketHandler'
4
- import { webSocketInterceptor } from './webSocketInterceptor'
5
-
6
- interface HandleWebSocketEventOptions {
7
- getHandlers: () => Array<RequestHandler | WebSocketHandler>
8
- onMockedConnection: (connection: WebSocketConnectionData) => void
9
- onPassthroughConnection: (onnection: WebSocketConnectionData) => void
10
- }
11
-
12
- export function handleWebSocketEvent(options: HandleWebSocketEventOptions) {
13
- webSocketInterceptor.on('connection', (connection) => {
14
- const handlers = options.getHandlers()
15
-
16
- const connectionEvent = new MessageEvent('connection', {
17
- data: connection,
18
- })
19
-
20
- // First, filter only those WebSocket handlers that
21
- // match the "ws.link()" endpoint predicate. Don't dispatch
22
- // anything yet so the logger can be attached to the connection
23
- // before it potentially sends events.
24
- const matchingHandlers = handlers.filter<WebSocketHandler>(
25
- (handler): handler is WebSocketHandler => {
26
- if (handler instanceof WebSocketHandler) {
27
- return handler.predicate({
28
- event: connectionEvent,
29
- parsedResult: handler.parse({
30
- event: connectionEvent,
31
- }),
32
- })
33
- }
34
-
35
- return false
36
- },
37
- )
38
-
39
- if (matchingHandlers.length > 0) {
40
- options?.onMockedConnection(connection)
41
-
42
- // Iterate over the handlers and forward the connection
43
- // event to WebSocket event handlers. This is equivalent
44
- // to dispatching that event onto multiple listeners.
45
- for (const handler of matchingHandlers) {
46
- handler[kDispatchEvent](connectionEvent)
47
- }
48
- } else {
49
- options?.onPassthroughConnection(connection)
50
-
51
- // If none of the "ws" handlers matched,
52
- // establish the WebSocket connection as-is.
53
- connection.server.connect()
54
- }
55
- })
56
- }