msw 2.3.0-ws.rc-5 → 2.3.0-ws.rc-7

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 (77) hide show
  1. package/README.md +3 -9
  2. package/lib/browser/index.js +160 -62
  3. package/lib/browser/index.js.map +1 -1
  4. package/lib/browser/index.mjs +160 -62
  5. package/lib/browser/index.mjs.map +1 -1
  6. package/lib/core/handlers/WebSocketHandler.js +1 -2
  7. package/lib/core/handlers/WebSocketHandler.js.map +1 -1
  8. package/lib/core/handlers/WebSocketHandler.mjs +1 -2
  9. package/lib/core/handlers/WebSocketHandler.mjs.map +1 -1
  10. package/lib/core/utils/internal/Disposable.d.mts +2 -2
  11. package/lib/core/utils/internal/Disposable.d.ts +2 -2
  12. package/lib/core/utils/internal/Disposable.js +5 -2
  13. package/lib/core/utils/internal/Disposable.js.map +1 -1
  14. package/lib/core/utils/internal/Disposable.mjs +5 -2
  15. package/lib/core/utils/internal/Disposable.mjs.map +1 -1
  16. package/lib/core/utils/internal/devUtils.d.mts +10 -1
  17. package/lib/core/utils/internal/devUtils.d.ts +10 -1
  18. package/lib/core/utils/internal/devUtils.js +7 -0
  19. package/lib/core/utils/internal/devUtils.js.map +1 -1
  20. package/lib/core/utils/internal/devUtils.mjs +7 -0
  21. package/lib/core/utils/internal/devUtils.mjs.map +1 -1
  22. package/lib/core/utils/matching/normalizePath.d.mts +1 -0
  23. package/lib/core/utils/matching/normalizePath.d.ts +1 -0
  24. package/lib/core/utils/matching/normalizePath.js.map +1 -1
  25. package/lib/core/utils/matching/normalizePath.mjs.map +1 -1
  26. package/lib/core/utils/request/onUnhandledRequest.js +3 -3
  27. package/lib/core/utils/request/onUnhandledRequest.js.map +1 -1
  28. package/lib/core/utils/request/onUnhandledRequest.mjs +4 -4
  29. package/lib/core/utils/request/onUnhandledRequest.mjs.map +1 -1
  30. package/lib/core/utils/url/cleanUrl.d.mts +2 -1
  31. package/lib/core/utils/url/cleanUrl.d.ts +2 -1
  32. package/lib/core/utils/url/cleanUrl.js +3 -0
  33. package/lib/core/utils/url/cleanUrl.js.map +1 -1
  34. package/lib/core/utils/url/cleanUrl.mjs +3 -0
  35. package/lib/core/utils/url/cleanUrl.mjs.map +1 -1
  36. package/lib/core/ws/WebSocketClientManager.d.mts +9 -15
  37. package/lib/core/ws/WebSocketClientManager.d.ts +9 -15
  38. package/lib/core/ws/WebSocketClientManager.js +73 -34
  39. package/lib/core/ws/WebSocketClientManager.js.map +1 -1
  40. package/lib/core/ws/WebSocketClientManager.mjs +73 -34
  41. package/lib/core/ws/WebSocketClientManager.mjs.map +1 -1
  42. package/lib/core/ws.js +4 -2
  43. package/lib/core/ws.js.map +1 -1
  44. package/lib/core/ws.mjs +4 -2
  45. package/lib/core/ws.mjs.map +1 -1
  46. package/lib/iife/index.js +278 -113
  47. package/lib/iife/index.js.map +1 -1
  48. package/lib/mockServiceWorker.js +1 -1
  49. package/lib/native/index.js +5 -0
  50. package/lib/native/index.js.map +1 -1
  51. package/lib/native/index.mjs +6 -1
  52. package/lib/native/index.mjs.map +1 -1
  53. package/lib/node/index.js +5 -0
  54. package/lib/node/index.js.map +1 -1
  55. package/lib/node/index.mjs +6 -1
  56. package/lib/node/index.mjs.map +1 -1
  57. package/package.json +17 -5
  58. package/src/browser/setupWorker/start/createStartHandler.ts +6 -0
  59. package/src/browser/setupWorker/stop/createStop.ts +4 -0
  60. package/src/core/handlers/WebSocketHandler.ts +1 -2
  61. package/src/core/utils/internal/Disposable.ts +6 -3
  62. package/src/core/utils/internal/devUtils.test.ts +21 -0
  63. package/src/core/utils/internal/devUtils.ts +13 -0
  64. package/src/core/utils/matching/matchRequestUrl.test.ts +11 -0
  65. package/src/core/utils/matching/normalizePath.test.ts +7 -1
  66. package/src/core/utils/matching/normalizePath.ts +1 -0
  67. package/src/core/utils/request/onUnhandledRequest.test.ts +30 -4
  68. package/src/core/utils/request/onUnhandledRequest.ts +4 -4
  69. package/src/core/utils/url/cleanUrl.test.ts +8 -3
  70. package/src/core/utils/url/cleanUrl.ts +9 -1
  71. package/src/core/utils/url/getAbsoluteUrl.node.test.ts +3 -3
  72. package/src/core/utils/url/getAbsoluteUrl.test.ts +5 -5
  73. package/src/core/utils/url/isAbsoluteUrl.test.ts +7 -7
  74. package/src/core/ws/WebSocketClientManager.test.ts +43 -45
  75. package/src/core/ws/WebSocketClientManager.ts +107 -44
  76. package/src/core/ws.ts +4 -2
  77. package/src/node/SetupServerCommonApi.ts +7 -1
package/README.md CHANGED
@@ -17,15 +17,9 @@
17
17
  <p align="center">Mock Service Worker (MSW) is a seamless REST/GraphQL API mocking library for browser and Node.js.</p>
18
18
 
19
19
  <p align="center">
20
- <a href="https://www.npmjs.com/package/msw" target="_blank">
21
- <img src="https://img.shields.io/npm/v/msw.svg?style=for-the-badge&label=Latest&color=black" alt="Package version" />
22
- </a>
23
- <a href="https://www.npmjs.com/package/msw" target="_blank">
24
- <img src="https://img.shields.io/npm/dm/msw?style=for-the-badge&color=black" alt="Downloads per month" />
25
- </a>
26
- <a href="https://kettanaito.com/discord" target="_blank">
27
- <img src="https://img.shields.io/badge/chat-online-green?style=for-the-badge&color=black" alt="Discord server" />
28
- </a>
20
+ <a href="https://www.npmjs.com/package/msw" target="_blank"><img src="https://img.shields.io/npm/v/msw.svg?style=for-the-badge&label=Latest&color=black" alt="Package version" /></a>
21
+ <a href="https://www.npmjs.com/package/msw" target="_blank"><img src="https://img.shields.io/npm/dm/msw?style=for-the-badge&color=black" alt="Downloads per month" /></a>
22
+ <a href="https://kettanaito.com/discord" target="_blank"><img src="https://img.shields.io/badge/chat-online-green?style=for-the-badge&color=black" alt="Discord server" /></a>
29
23
  </p>
30
24
 
31
25
  <br />
@@ -124,6 +124,7 @@ function isNodeProcess() {
124
124
 
125
125
  // src/browser/setupWorker/start/createStartHandler.ts
126
126
  var import_devUtils7 = require("../core/utils/internal/devUtils.js");
127
+ var import_WebSocketClientManager = require("../core/ws/WebSocketClientManager.js");
127
128
 
128
129
  // node_modules/.pnpm/@open-draft+until@2.1.0/node_modules/@open-draft/until/lib/index.mjs
129
130
  var until = async (promise) => {
@@ -397,7 +398,7 @@ You can also automate this process and make the worker script update automatical
397
398
  }
398
399
  }
399
400
 
400
- // node_modules/.pnpm/@mswjs+interceptors@0.27.1/node_modules/@mswjs/interceptors/lib/browser/chunk-UJZOJSMP.mjs
401
+ // node_modules/.pnpm/@mswjs+interceptors@0.30.0/node_modules/@mswjs/interceptors/lib/browser/chunk-6HYIRFX2.mjs
401
402
  var encoder = new TextEncoder();
402
403
  function encodeBuffer(text) {
403
404
  return encoder.encode(text);
@@ -412,6 +413,17 @@ function toArrayBuffer(array) {
412
413
  array.byteOffset + array.byteLength
413
414
  );
414
415
  }
416
+
417
+ // node_modules/.pnpm/@mswjs+interceptors@0.30.0/node_modules/@mswjs/interceptors/lib/browser/chunk-OMISYKWR.mjs
418
+ var IS_PATCHED_MODULE = Symbol("isPatchedModule");
419
+ function isPropertyAccessible(obj, key) {
420
+ try {
421
+ obj[key];
422
+ return true;
423
+ } catch (e) {
424
+ return false;
425
+ }
426
+ }
415
427
  var RESPONSE_STATUS_CODES_WITHOUT_BODY = /* @__PURE__ */ new Set([
416
428
  101,
417
429
  103,
@@ -422,9 +434,27 @@ var RESPONSE_STATUS_CODES_WITHOUT_BODY = /* @__PURE__ */ new Set([
422
434
  function isResponseWithoutBody(status) {
423
435
  return RESPONSE_STATUS_CODES_WITHOUT_BODY.has(status);
424
436
  }
425
-
426
- // node_modules/.pnpm/@mswjs+interceptors@0.27.1/node_modules/@mswjs/interceptors/lib/browser/chunk-HAGW22AN.mjs
427
- var IS_PATCHED_MODULE = Symbol("isPatchedModule");
437
+ function createServerErrorResponse(body) {
438
+ return new Response(
439
+ JSON.stringify(
440
+ body instanceof Error ? {
441
+ name: body.name,
442
+ message: body.message,
443
+ stack: body.stack
444
+ } : body
445
+ ),
446
+ {
447
+ status: 500,
448
+ statusText: "Unhandled Exception",
449
+ headers: {
450
+ "Content-Type": "application/json"
451
+ }
452
+ }
453
+ );
454
+ }
455
+ function isResponseError(response) {
456
+ return isPropertyAccessible(response, "type") && response.type === "error";
457
+ }
428
458
 
429
459
  // node_modules/.pnpm/@open-draft+logger@0.3.0/node_modules/@open-draft/logger/lib/index.mjs
430
460
  var __defProp2 = Object.defineProperty;
@@ -863,7 +893,7 @@ var _Emitter = class {
863
893
  var Emitter = _Emitter;
864
894
  Emitter.defaultMaxListeners = 10;
865
895
 
866
- // node_modules/.pnpm/@mswjs+interceptors@0.27.1/node_modules/@mswjs/interceptors/lib/browser/chunk-QED3Q6Z2.mjs
896
+ // node_modules/.pnpm/@mswjs+interceptors@0.30.0/node_modules/@mswjs/interceptors/lib/browser/chunk-QED3Q6Z2.mjs
867
897
  var INTERNAL_REQUEST_ID_HEADER_NAME = "x-interceptors-internal-request-id";
868
898
  function getGlobalSymbol(symbol) {
869
899
  return (
@@ -1011,7 +1041,7 @@ function createRequestId() {
1011
1041
  return Math.random().toString(16).slice(2);
1012
1042
  }
1013
1043
 
1014
- // node_modules/.pnpm/@mswjs+interceptors@0.27.1/node_modules/@mswjs/interceptors/lib/browser/index.mjs
1044
+ // node_modules/.pnpm/@mswjs+interceptors@0.30.0/node_modules/@mswjs/interceptors/lib/browser/index.mjs
1015
1045
  var BatchInterceptor = class extends Interceptor {
1016
1046
  constructor(options) {
1017
1047
  BatchInterceptor.symbol = Symbol(options.name);
@@ -1147,6 +1177,7 @@ Please consider using a custom "serviceWorker.url" option to point to the actual
1147
1177
  context.workerChannel.send("CLIENT_CLOSED");
1148
1178
  }
1149
1179
  window.clearInterval(context.keepAliveInterval);
1180
+ localStorage.removeItem(import_WebSocketClientManager.MSW_WEBSOCKET_CLIENTS_KEY);
1150
1181
  });
1151
1182
  await checkWorkerIntegrity(context).catch((error2) => {
1152
1183
  import_devUtils7.devUtils.error(
@@ -1185,6 +1216,7 @@ Please consider using a custom "serviceWorker.url" option to point to the actual
1185
1216
 
1186
1217
  // src/browser/setupWorker/stop/createStop.ts
1187
1218
  var import_devUtils9 = require("../core/utils/internal/devUtils.js");
1219
+ var import_WebSocketClientManager2 = require("../core/ws/WebSocketClientManager.js");
1188
1220
 
1189
1221
  // src/browser/setupWorker/stop/utils/printStopMessage.ts
1190
1222
  var import_devUtils8 = require("../core/utils/internal/devUtils.js");
@@ -1210,6 +1242,7 @@ var createStop = (context) => {
1210
1242
  context.workerChannel.send("MOCK_DEACTIVATE");
1211
1243
  context.isMockingEnabled = false;
1212
1244
  window.clearInterval(context.keepAliveInterval);
1245
+ localStorage.removeItem(import_WebSocketClientManager2.MSW_WEBSOCKET_CLIENTS_KEY);
1213
1246
  printStopMessage({ quiet: context.startOptions?.quiet });
1214
1247
  };
1215
1248
  };
@@ -1295,7 +1328,7 @@ var DeferredPromise = class extends Promise {
1295
1328
  }
1296
1329
  };
1297
1330
 
1298
- // node_modules/.pnpm/@mswjs+interceptors@0.27.1/node_modules/@mswjs/interceptors/lib/browser/chunk-OUWBQF3Z.mjs
1331
+ // node_modules/.pnpm/@mswjs+interceptors@0.30.0/node_modules/@mswjs/interceptors/lib/browser/chunk-OUWBQF3Z.mjs
1299
1332
  var RequestController = class {
1300
1333
  constructor(request) {
1301
1334
  this.request = request;
@@ -1333,15 +1366,7 @@ async function emitAsync(emitter, eventName, ...data) {
1333
1366
  }
1334
1367
  }
1335
1368
 
1336
- // node_modules/.pnpm/@mswjs+interceptors@0.27.1/node_modules/@mswjs/interceptors/lib/browser/chunk-3FNUI33J.mjs
1337
- function isPropertyAccessible(obj, key) {
1338
- try {
1339
- obj[key];
1340
- return true;
1341
- } catch (e) {
1342
- return false;
1343
- }
1344
- }
1369
+ // node_modules/.pnpm/@mswjs+interceptors@0.30.0/node_modules/@mswjs/interceptors/lib/browser/chunk-MAEPOYB6.mjs
1345
1370
  function canParseUrl(url) {
1346
1371
  try {
1347
1372
  new URL(url);
@@ -1394,64 +1419,113 @@ var _FetchInterceptor = class extends Interceptor {
1394
1419
  { once: true }
1395
1420
  );
1396
1421
  }
1397
- const resolverResult = await until(async () => {
1398
- const listenersFinished = emitAsync(this.emitter, "request", {
1399
- request: interactiveRequest,
1400
- requestId
1422
+ const responsePromise = new DeferredPromise();
1423
+ const respondWith = (response) => {
1424
+ this.logger.info("responding with a mock response:", response);
1425
+ if (this.emitter.listenerCount("response") > 0) {
1426
+ this.logger.info('emitting the "response" event...');
1427
+ const responseClone = response.clone();
1428
+ this.emitter.emit("response", {
1429
+ response: responseClone,
1430
+ isMockedResponse: true,
1431
+ request: interactiveRequest,
1432
+ requestId
1433
+ });
1434
+ }
1435
+ Object.defineProperty(response, "url", {
1436
+ writable: false,
1437
+ enumerable: true,
1438
+ configurable: false,
1439
+ value: request.url
1401
1440
  });
1402
- await Promise.race([
1403
- requestAborted,
1404
- // Put the listeners invocation Promise in the same race condition
1405
- // with the request abort Promise because otherwise awaiting the listeners
1406
- // would always yield some response (or undefined).
1407
- listenersFinished,
1408
- requestController.responsePromise
1409
- ]);
1410
- this.logger.info("all request listeners have been resolved!");
1411
- const mockedResponse2 = await requestController.responsePromise;
1412
- this.logger.info("event.respondWith called with:", mockedResponse2);
1413
- return mockedResponse2;
1414
- });
1441
+ responsePromise.resolve(response);
1442
+ };
1443
+ const errorWith = (reason) => {
1444
+ responsePromise.reject(reason);
1445
+ };
1446
+ const resolverResult = await until(
1447
+ async () => {
1448
+ const listenersFinished = emitAsync(this.emitter, "request", {
1449
+ request: interactiveRequest,
1450
+ requestId
1451
+ });
1452
+ await Promise.race([
1453
+ requestAborted,
1454
+ // Put the listeners invocation Promise in the same race condition
1455
+ // with the request abort Promise because otherwise awaiting the listeners
1456
+ // would always yield some response (or undefined).
1457
+ listenersFinished,
1458
+ requestController.responsePromise
1459
+ ]);
1460
+ this.logger.info("all request listeners have been resolved!");
1461
+ const mockedResponse2 = await requestController.responsePromise;
1462
+ this.logger.info("event.respondWith called with:", mockedResponse2);
1463
+ return mockedResponse2;
1464
+ }
1465
+ );
1415
1466
  if (requestAborted.state === "rejected") {
1416
- return Promise.reject(requestAborted.rejectionReason);
1467
+ this.logger.info(
1468
+ "request has been aborted:",
1469
+ requestAborted.rejectionReason
1470
+ );
1471
+ responsePromise.reject(requestAborted.rejectionReason);
1472
+ return responsePromise;
1417
1473
  }
1418
1474
  if (resolverResult.error) {
1419
- return Promise.reject(createNetworkError(resolverResult.error));
1475
+ this.logger.info(
1476
+ "request listerner threw an error:",
1477
+ resolverResult.error
1478
+ );
1479
+ if (resolverResult.error instanceof Response) {
1480
+ if (isResponseError(resolverResult.error)) {
1481
+ errorWith(createNetworkError(resolverResult.error));
1482
+ } else {
1483
+ respondWith(resolverResult.error);
1484
+ }
1485
+ }
1486
+ if (this.emitter.listenerCount("unhandledException") > 0) {
1487
+ await emitAsync(this.emitter, "unhandledException", {
1488
+ error: resolverResult.error,
1489
+ request,
1490
+ requestId,
1491
+ controller: {
1492
+ respondWith,
1493
+ errorWith
1494
+ }
1495
+ });
1496
+ if (responsePromise.state !== "pending") {
1497
+ return responsePromise;
1498
+ }
1499
+ }
1500
+ respondWith(createServerErrorResponse(resolverResult.error));
1501
+ return responsePromise;
1420
1502
  }
1421
1503
  const mockedResponse = resolverResult.data;
1422
1504
  if (mockedResponse && !((_a = request.signal) == null ? void 0 : _a.aborted)) {
1423
1505
  this.logger.info("received mocked response:", mockedResponse);
1424
- if (isPropertyAccessible(mockedResponse, "type") && mockedResponse.type === "error") {
1506
+ if (isResponseError(mockedResponse)) {
1425
1507
  this.logger.info(
1426
1508
  "received a network error response, rejecting the request promise..."
1427
1509
  );
1428
- return Promise.reject(createNetworkError(mockedResponse));
1510
+ errorWith(createNetworkError(mockedResponse));
1511
+ } else {
1512
+ respondWith(mockedResponse);
1429
1513
  }
1430
- const responseClone = mockedResponse.clone();
1431
- this.emitter.emit("response", {
1432
- response: responseClone,
1433
- isMockedResponse: true,
1434
- request: interactiveRequest,
1435
- requestId
1436
- });
1437
- Object.defineProperty(mockedResponse, "url", {
1438
- writable: false,
1439
- enumerable: true,
1440
- configurable: false,
1441
- value: request.url
1442
- });
1443
- return mockedResponse;
1514
+ return responsePromise;
1444
1515
  }
1445
1516
  this.logger.info("no mocked response received!");
1446
1517
  return pureFetch(request).then((response) => {
1447
- const responseClone = response.clone();
1448
- this.logger.info("original fetch performed", responseClone);
1449
- this.emitter.emit("response", {
1450
- response: responseClone,
1451
- isMockedResponse: false,
1452
- request: interactiveRequest,
1453
- requestId
1454
- });
1518
+ this.logger.info("original fetch performed", response);
1519
+ if (this.emitter.listenerCount("response") > 0) {
1520
+ this.logger.info('emitting the "response" event...');
1521
+ const responseClone = response.clone();
1522
+ this.emitter.emit("response", {
1523
+ response: responseClone,
1524
+ isMockedResponse: false,
1525
+ request: interactiveRequest,
1526
+ requestId
1527
+ });
1528
+ }
1455
1529
  return response;
1456
1530
  });
1457
1531
  };
@@ -1480,7 +1554,7 @@ function createNetworkError(cause) {
1480
1554
  });
1481
1555
  }
1482
1556
 
1483
- // node_modules/.pnpm/@mswjs+interceptors@0.27.1/node_modules/@mswjs/interceptors/lib/browser/chunk-VYFS2IF2.mjs
1557
+ // node_modules/.pnpm/@mswjs+interceptors@0.30.0/node_modules/@mswjs/interceptors/lib/browser/chunk-732REFPX.mjs
1484
1558
  function concatArrayBuffer(left, right) {
1485
1559
  const result = new Uint8Array(left.byteLength + right.byteLength);
1486
1560
  result.set(left, 0);
@@ -2131,7 +2205,31 @@ function createXMLHttpRequestProxy({
2131
2205
  "request listener threw an exception, aborting request...",
2132
2206
  resolverResult.error
2133
2207
  );
2134
- xhrRequestController.errorWith(resolverResult.error);
2208
+ if (resolverResult.error instanceof Response) {
2209
+ if (isResponseError(resolverResult.error)) {
2210
+ xhrRequestController.errorWith(new TypeError("Network error"));
2211
+ } else {
2212
+ this.respondWith(resolverResult.error);
2213
+ }
2214
+ return;
2215
+ }
2216
+ if (emitter.listenerCount("unhandledException") > 0) {
2217
+ await emitAsync(emitter, "unhandledException", {
2218
+ error: resolverResult.error,
2219
+ request,
2220
+ requestId,
2221
+ controller: {
2222
+ respondWith: xhrRequestController.respondWith.bind(xhrRequestController),
2223
+ errorWith: xhrRequestController.errorWith.bind(xhrRequestController)
2224
+ }
2225
+ });
2226
+ if (originalRequest.readyState > XMLHttpRequest.OPENED) {
2227
+ return;
2228
+ }
2229
+ }
2230
+ xhrRequestController.respondWith(
2231
+ createServerErrorResponse(resolverResult.error)
2232
+ );
2135
2233
  return;
2136
2234
  }
2137
2235
  const mockedResponse = resolverResult.data;
@@ -2141,7 +2239,7 @@ function createXMLHttpRequestProxy({
2141
2239
  mockedResponse.status,
2142
2240
  mockedResponse.statusText
2143
2241
  );
2144
- if (mockedResponse.type === "error") {
2242
+ if (isResponseError(mockedResponse)) {
2145
2243
  this.logger.info(
2146
2244
  "received a network error response, rejecting the request promise..."
2147
2245
  );