@zimic/interceptor 1.5.1 → 1.5.2-canary.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 (42) hide show
  1. package/dist/{chunk-3WCEMV5U.js → chunk-6YD4TBYJ.js} +13 -4
  2. package/dist/chunk-6YD4TBYJ.js.map +1 -0
  3. package/dist/{chunk-YQNDAJTN.mjs → chunk-MCLPYYCY.mjs} +13 -4
  4. package/dist/chunk-MCLPYYCY.mjs.map +1 -0
  5. package/dist/cli.js +16 -16
  6. package/dist/cli.js.map +1 -1
  7. package/dist/cli.mjs +2 -2
  8. package/dist/cli.mjs.map +1 -1
  9. package/dist/http.d.ts +24 -8
  10. package/dist/http.js +368 -289
  11. package/dist/http.js.map +1 -1
  12. package/dist/http.mjs +367 -288
  13. package/dist/http.mjs.map +1 -1
  14. package/dist/server.js +6 -6
  15. package/dist/server.mjs +1 -1
  16. package/package.json +10 -10
  17. package/src/http/errors/HttpTimesCheckError.ts +9 -9
  18. package/src/http/index.ts +6 -1
  19. package/src/http/interceptor/HttpInterceptorImplementation.ts +74 -21
  20. package/src/http/interceptor/HttpInterceptorStore.ts +11 -13
  21. package/src/http/interceptor/LocalHttpInterceptor.ts +1 -10
  22. package/src/http/interceptor/RemoteHttpInterceptor.ts +16 -22
  23. package/src/http/interceptor/errors/UnknownHttpInterceptorPlatformError.ts +3 -1
  24. package/src/http/interceptor/factory.ts +3 -0
  25. package/src/http/interceptor/types/options.ts +1 -1
  26. package/src/http/interceptorWorker/HttpInterceptorWorker.ts +14 -3
  27. package/src/http/interceptorWorker/LocalHttpInterceptorWorker.ts +25 -93
  28. package/src/http/requestHandler/HttpRequestHandlerImplementation.ts +5 -9
  29. package/src/http/requestHandler/LocalHttpRequestHandler.ts +2 -5
  30. package/src/http/requestHandler/RemoteHttpRequestHandler.ts +17 -20
  31. package/src/http/requestHandler/types/public.ts +3 -8
  32. package/src/http/requestHandler/types/requests.ts +31 -3
  33. package/src/http/utils/logging.ts +54 -0
  34. package/src/interceptor/LocalMSWWorkerStore.ts +123 -0
  35. package/src/{http/interceptorWorker → interceptor}/types/msw.ts +1 -2
  36. package/src/server/utils/auth.ts +1 -1
  37. package/src/utils/fetch.ts +2 -2
  38. package/src/utils/logging.ts +0 -54
  39. package/src/utils/webSocket/WebSocketHandler.ts +1 -1
  40. package/dist/chunk-3WCEMV5U.js.map +0 -1
  41. package/dist/chunk-YQNDAJTN.mjs.map +0 -1
  42. /package/src/{http/interceptorWorker → interceptor}/errors/UnregisteredBrowserServiceWorkerError.ts +0 -0
package/dist/http.js CHANGED
@@ -1,13 +1,13 @@
1
1
  'use strict';
2
2
 
3
3
  var http = require('@zimic/http');
4
- var color2 = require('picocolors');
4
+ var color = require('picocolors');
5
5
  var msw = require('msw');
6
6
  var ClientSocket = require('isomorphic-ws');
7
7
 
8
8
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
9
9
 
10
- var color2__default = /*#__PURE__*/_interopDefault(color2);
10
+ var color__default = /*#__PURE__*/_interopDefault(color);
11
11
  var ClientSocket__default = /*#__PURE__*/_interopDefault(ClientSocket);
12
12
 
13
13
  // src/http/index.ts
@@ -30,8 +30,25 @@ var NotRunningHttpInterceptorError = class extends Error {
30
30
  };
31
31
  var NotRunningHttpInterceptorError_default = NotRunningHttpInterceptorError;
32
32
 
33
+ // ../zimic-utils/dist/validation.mjs
34
+ var ValidationError = class extends TypeError {
35
+ constructor(message) {
36
+ super(message);
37
+ this.name = "ValidationError";
38
+ }
39
+ };
40
+ var ValidationError_default = ValidationError;
41
+ function assertTypeOf(field, value, expectedType, options) {
42
+ const actualType = typeof value;
43
+ if (actualType !== expectedType && !(options?.nullable && value === null) && !(options?.optional && value === void 0)) {
44
+ const receivedType = value === null ? "null" : actualType;
45
+ throw new ValidationError_default(`Expected ${field} to be ${expectedType}, but got ${receivedType}.`);
46
+ }
47
+ }
48
+ var assertTypeOf_default = assertTypeOf;
49
+
33
50
  // src/http/interceptor/errors/UnknownHttpInterceptorPlatformError.ts
34
- var UnknownHttpInterceptorPlatformError = class extends Error {
51
+ var UnknownHttpInterceptorPlatformError = class extends ValidationError_default {
35
52
  /* istanbul ignore next -- @preserve
36
53
  * Ignoring because checking unknown platforms is currently not possible in our Vitest setup. */
37
54
  constructor() {
@@ -72,7 +89,7 @@ var RequestSavingSafeLimitExceededError_default = RequestSavingSafeLimitExceeded
72
89
  // src/cli/browser/shared/constants.ts
73
90
  var SERVICE_WORKER_FILE_NAME = "mockServiceWorker.js";
74
91
 
75
- // src/http/interceptorWorker/errors/UnregisteredBrowserServiceWorkerError.ts
92
+ // src/interceptor/errors/UnregisteredBrowserServiceWorkerError.ts
76
93
  var UnregisteredBrowserServiceWorkerError = class extends Error {
77
94
  constructor() {
78
95
  super(
@@ -237,130 +254,31 @@ function jsonEquals(value, otherValue) {
237
254
  });
238
255
  }
239
256
  var jsonEquals_default = jsonEquals;
240
-
241
- // ../zimic-utils/dist/chunk-W66SQPEM.mjs
242
- function createCachedDynamicImport(importModuleDynamically) {
243
- let cachedImportResult;
244
- return async function importModuleDynamicallyWithCache() {
245
- cachedImportResult ??= await importModuleDynamically();
246
- return cachedImportResult;
247
- };
248
- }
249
- var createCachedDynamicImport_default = createCachedDynamicImport;
250
-
251
- // ../zimic-utils/dist/logging.mjs
252
- var Logger = class _Logger {
253
- prefix;
254
- raw;
255
- constructor(options = {}) {
256
- const { prefix } = options;
257
- this.prefix = prefix;
258
- this.raw = prefix ? new _Logger({ ...options, prefix: void 0 }) : this;
259
- }
260
- logWithLevel(level, ...messages) {
261
- if (this.prefix) {
262
- console[level](this.prefix, ...messages);
263
- } else {
264
- console[level](...messages);
265
- }
266
- }
267
- info(...messages) {
268
- this.logWithLevel("log", ...messages);
269
- }
270
- warn(...messages) {
271
- this.logWithLevel("warn", ...messages);
272
- }
273
- error(...messages) {
274
- this.logWithLevel("error", ...messages);
275
- }
276
- table(headers, rows) {
277
- const columnLengths = headers.map((header) => {
278
- let maxValueLength = header.title.length;
279
- for (const row of rows) {
280
- const value = row[header.property];
281
- if (value.length > maxValueLength) {
282
- maxValueLength = value.length;
283
- }
284
- }
285
- return maxValueLength;
286
- });
287
- const formattedRows = [];
288
- const horizontalLine = columnLengths.map((length) => "\u2500".repeat(length));
289
- formattedRows.push(horizontalLine, []);
290
- for (let headerIndex = 0; headerIndex < headers.length; headerIndex++) {
291
- const header = headers[headerIndex];
292
- const columnLength = columnLengths[headerIndex];
293
- const value = header.title;
294
- formattedRows.at(-1)?.push(value.padEnd(columnLength, " "));
295
- }
296
- formattedRows.push(horizontalLine);
297
- for (const row of rows) {
298
- formattedRows.push([]);
299
- for (let headerIndex = 0; headerIndex < headers.length; headerIndex++) {
300
- const header = headers[headerIndex];
301
- const columnLength = columnLengths[headerIndex];
302
- const value = row[header.property];
303
- formattedRows.at(-1)?.push(value.padEnd(columnLength, " "));
304
- }
305
- }
306
- formattedRows.push(horizontalLine);
307
- const formattedTable = formattedRows.map((row, index) => {
308
- const isFirstLine = index === 0;
309
- if (isFirstLine) {
310
- return `\u250C\u2500${row.join("\u2500\u252C\u2500")}\u2500\u2510`;
311
- }
312
- const isLineAfterHeaders = index === 2;
313
- if (isLineAfterHeaders) {
314
- return `\u251C\u2500${row.join("\u2500\u253C\u2500")}\u2500\u2524`;
315
- }
316
- const isLastLine = index === formattedRows.length - 1;
317
- if (isLastLine) {
318
- return `\u2514\u2500${row.join("\u2500\u2534\u2500")}\u2500\u2518`;
319
- }
320
- return `\u2502 ${row.join(" \u2502 ")} \u2502`;
321
- }).join("\n");
322
- this.logWithLevel("log", formattedTable);
323
- }
324
- };
325
- var Logger_default = Logger;
326
-
327
- // src/utils/environment.ts
328
- function isServerSide() {
329
- return typeof process !== "undefined" && typeof process.versions !== "undefined";
330
- }
331
- function isClientSide() {
332
- return typeof window !== "undefined" && typeof document !== "undefined";
333
- }
334
-
335
- // src/utils/logging.ts
336
- var logger = new Logger_default({
337
- prefix: color2__default.default.cyan("[@zimic/interceptor]")
338
- });
339
- function stringifyJSONToLog(value) {
257
+ function stringifyHttpJSONToLog(value) {
340
258
  return JSON.stringify(
341
259
  value,
342
260
  (_key, value2) => {
343
- return stringifyValueToLog(value2, {
261
+ return stringifyHttpValueToLog(value2, {
344
262
  fallback: (value3) => value3
345
263
  });
346
264
  },
347
265
  2
348
266
  ).replace(/\n\s*/g, " ").replace(/"(File { name: '.*?', type: '.*?', size: \d*? })"/g, "$1").replace(/"(Blob { type: '.*?', size: \d*? })"/g, "$1");
349
267
  }
350
- function stringifyValueToLog(value, options = {}) {
351
- const { fallback = stringifyJSONToLog, includeClassName } = options;
268
+ function stringifyHttpValueToLog(value, options = {}) {
269
+ const { fallback = stringifyHttpJSONToLog, includeClassName } = options;
352
270
  if (value === null || value === void 0 || typeof value !== "object") {
353
271
  return String(value);
354
272
  }
355
273
  if (value instanceof http.HttpHeaders) {
356
- return stringifyValueToLog(value.toObject());
274
+ return stringifyHttpValueToLog(value.toObject());
357
275
  }
358
- if (value instanceof http.HttpHeaders || value instanceof http.HttpSearchParams) {
276
+ if (value instanceof http.HttpSearchParams) {
359
277
  const prefix = includeClassName?.searchParams ?? false ? "URLSearchParams " : "";
360
- return `${prefix}${stringifyValueToLog(value.toObject())}`;
278
+ return `${prefix}${stringifyHttpValueToLog(value.toObject())}`;
361
279
  }
362
280
  if (value instanceof http.HttpFormData) {
363
- return `FormData ${stringifyValueToLog(value.toObject())}`;
281
+ return `FormData ${stringifyHttpValueToLog(value.toObject())}`;
364
282
  }
365
283
  if (value instanceof File) {
366
284
  return `File { name: '${value.name}', type: '${value.type}', size: ${value.size} }`;
@@ -370,23 +288,6 @@ function stringifyValueToLog(value, options = {}) {
370
288
  }
371
289
  return fallback(value);
372
290
  }
373
- var importUtil = createCachedDynamicImport_default(() => import('util'));
374
- async function formatValueToLog(value, options = {}) {
375
- if (isClientSide()) {
376
- return value;
377
- }
378
- const { colors = true } = options;
379
- const util = await importUtil();
380
- return util.inspect(value, {
381
- colors,
382
- compact: true,
383
- depth: Infinity,
384
- maxArrayLength: Infinity,
385
- maxStringLength: Infinity,
386
- breakLength: Infinity,
387
- sorted: true
388
- });
389
- }
390
291
 
391
292
  // src/http/errors/HttpTimesCheckError.ts
392
293
  function createMessageHeader({
@@ -410,8 +311,8 @@ function createMessageHeader({
410
311
 
411
312
  Requests evaluated by this handler:
412
313
 
413
- ${color2__default.default.green("- Expected")}
414
- ${color2__default.default.red("+ Received")}`
314
+ ${color__default.default.green("- Expected")}
315
+ ${color__default.default.red("+ Received")}`
415
316
  ].filter((part) => part !== false).join("");
416
317
  }
417
318
  function createMessageDiffs({ requestSaving, unmatchedRequestGroups }) {
@@ -423,35 +324,35 @@ function createMessageDiffs({ requestSaving, unmatchedRequestGroups }) {
423
324
  const messageParts = [`${requestNumber}: ${request.method} ${request.url}`];
424
325
  if (diff.computed) {
425
326
  messageParts.push("Computed restriction:");
426
- const stringifiedExpected = stringifyValueToLog(diff.computed.expected);
427
- const stringifiedReceived = stringifyValueToLog(diff.computed.received);
428
- messageParts.push(` ${color2__default.default.green(`- return ${stringifiedExpected}`)}`);
429
- messageParts.push(` ${color2__default.default.red(`+ return ${stringifiedReceived}`)}`);
327
+ const stringifiedExpected = stringifyHttpValueToLog(diff.computed.expected);
328
+ const stringifiedReceived = stringifyHttpValueToLog(diff.computed.received);
329
+ messageParts.push(` ${color__default.default.green(`- return ${stringifiedExpected}`)}`);
330
+ messageParts.push(` ${color__default.default.red(`+ return ${stringifiedReceived}`)}`);
430
331
  }
431
332
  if (diff.headers) {
432
333
  messageParts.push("Headers:");
433
- const stringifiedExpected = stringifyValueToLog(diff.headers.expected);
434
- const stringifiedReceived = stringifyValueToLog(diff.headers.received);
435
- messageParts.push(` ${color2__default.default.green(`- ${stringifiedExpected}`)}`);
436
- messageParts.push(` ${color2__default.default.red(`+ ${stringifiedReceived}`)}`);
334
+ const stringifiedExpected = stringifyHttpValueToLog(diff.headers.expected);
335
+ const stringifiedReceived = stringifyHttpValueToLog(diff.headers.received);
336
+ messageParts.push(` ${color__default.default.green(`- ${stringifiedExpected}`)}`);
337
+ messageParts.push(` ${color__default.default.red(`+ ${stringifiedReceived}`)}`);
437
338
  }
438
339
  if (diff.searchParams) {
439
340
  messageParts.push("Search params:");
440
- const stringifiedExpected = stringifyValueToLog(diff.searchParams.expected);
441
- const stringifiedReceived = stringifyValueToLog(diff.searchParams.received);
442
- messageParts.push(` ${color2__default.default.green(`- ${stringifiedExpected}`)}`);
443
- messageParts.push(` ${color2__default.default.red(`+ ${stringifiedReceived}`)}`);
341
+ const stringifiedExpected = stringifyHttpValueToLog(diff.searchParams.expected);
342
+ const stringifiedReceived = stringifyHttpValueToLog(diff.searchParams.received);
343
+ messageParts.push(` ${color__default.default.green(`- ${stringifiedExpected}`)}`);
344
+ messageParts.push(` ${color__default.default.red(`+ ${stringifiedReceived}`)}`);
444
345
  }
445
346
  if (diff.body) {
446
347
  messageParts.push("Body:");
447
- const stringifiedExpected = stringifyValueToLog(diff.body.expected, {
348
+ const stringifiedExpected = stringifyHttpValueToLog(diff.body.expected, {
448
349
  includeClassName: { searchParams: true }
449
350
  });
450
- const stringifiedReceived = stringifyValueToLog(diff.body.received, {
351
+ const stringifiedReceived = stringifyHttpValueToLog(diff.body.received, {
451
352
  includeClassName: { searchParams: true }
452
353
  });
453
- messageParts.push(` ${color2__default.default.green(`- ${stringifiedExpected}`)}`);
454
- messageParts.push(` ${color2__default.default.red(`+ ${stringifiedReceived}`)}`);
354
+ messageParts.push(` ${color__default.default.green(`- ${stringifiedExpected}`)}`);
355
+ messageParts.push(` ${color__default.default.red(`+ ${stringifiedReceived}`)}`);
455
356
  }
456
357
  return messageParts.join("\n ");
457
358
  }).join("\n\n");
@@ -481,6 +382,16 @@ var HttpTimesCheckError = class extends TimesCheckError {
481
382
  };
482
383
  var HttpTimesCheckError_default = HttpTimesCheckError;
483
384
 
385
+ // ../zimic-utils/dist/chunk-W66SQPEM.mjs
386
+ function createCachedDynamicImport(importModuleDynamically) {
387
+ let cachedImportResult;
388
+ return async function importModuleDynamicallyWithCache() {
389
+ cachedImportResult ??= await importModuleDynamically();
390
+ return cachedImportResult;
391
+ };
392
+ }
393
+ var createCachedDynamicImport_default = createCachedDynamicImport;
394
+
484
395
  // ../zimic-utils/dist/time.mjs
485
396
  function waitForDelay(milliseconds) {
486
397
  return new Promise((resolve) => {
@@ -489,6 +400,14 @@ function waitForDelay(milliseconds) {
489
400
  }
490
401
  var waitForDelay_default = waitForDelay;
491
402
 
403
+ // src/utils/environment.ts
404
+ function isServerSide() {
405
+ return typeof process !== "undefined" && typeof process.versions !== "undefined";
406
+ }
407
+ function isClientSide() {
408
+ return typeof window !== "undefined" && typeof document !== "undefined";
409
+ }
410
+
492
411
  // src/utils/data.ts
493
412
  async function convertReadableStreamToBlob(stream, options) {
494
413
  const chunks = [];
@@ -1032,6 +951,102 @@ function methodCanHaveResponseBody(method) {
1032
951
  return HTTP_METHODS_WITH_RESPONSE_BODY.has(method);
1033
952
  }
1034
953
 
954
+ // ../zimic-utils/dist/logging.mjs
955
+ var Logger = class _Logger {
956
+ prefix;
957
+ raw;
958
+ constructor(options = {}) {
959
+ const { prefix } = options;
960
+ this.prefix = prefix;
961
+ this.raw = prefix ? new _Logger({ ...options, prefix: void 0 }) : this;
962
+ }
963
+ logWithLevel(level, ...messages) {
964
+ if (this.prefix) {
965
+ console[level](this.prefix, ...messages);
966
+ } else {
967
+ console[level](...messages);
968
+ }
969
+ }
970
+ info(...messages) {
971
+ this.logWithLevel("log", ...messages);
972
+ }
973
+ warn(...messages) {
974
+ this.logWithLevel("warn", ...messages);
975
+ }
976
+ error(...messages) {
977
+ this.logWithLevel("error", ...messages);
978
+ }
979
+ table(headers, rows) {
980
+ const columnLengths = headers.map((header) => {
981
+ let maxValueLength = header.title.length;
982
+ for (const row of rows) {
983
+ const value = row[header.property];
984
+ if (value.length > maxValueLength) {
985
+ maxValueLength = value.length;
986
+ }
987
+ }
988
+ return maxValueLength;
989
+ });
990
+ const formattedRows = [];
991
+ const horizontalLine = columnLengths.map((length) => "\u2500".repeat(length));
992
+ formattedRows.push(horizontalLine, []);
993
+ for (let headerIndex = 0; headerIndex < headers.length; headerIndex++) {
994
+ const header = headers[headerIndex];
995
+ const columnLength = columnLengths[headerIndex];
996
+ const value = header.title;
997
+ formattedRows.at(-1)?.push(value.padEnd(columnLength, " "));
998
+ }
999
+ formattedRows.push(horizontalLine);
1000
+ for (const row of rows) {
1001
+ formattedRows.push([]);
1002
+ for (let headerIndex = 0; headerIndex < headers.length; headerIndex++) {
1003
+ const header = headers[headerIndex];
1004
+ const columnLength = columnLengths[headerIndex];
1005
+ const value = row[header.property];
1006
+ formattedRows.at(-1)?.push(value.padEnd(columnLength, " "));
1007
+ }
1008
+ }
1009
+ formattedRows.push(horizontalLine);
1010
+ const formattedTable = formattedRows.map((row, index) => {
1011
+ const isFirstLine = index === 0;
1012
+ if (isFirstLine) {
1013
+ return `\u250C\u2500${row.join("\u2500\u252C\u2500")}\u2500\u2510`;
1014
+ }
1015
+ const isLineAfterHeaders = index === 2;
1016
+ if (isLineAfterHeaders) {
1017
+ return `\u251C\u2500${row.join("\u2500\u253C\u2500")}\u2500\u2524`;
1018
+ }
1019
+ const isLastLine = index === formattedRows.length - 1;
1020
+ if (isLastLine) {
1021
+ return `\u2514\u2500${row.join("\u2500\u2534\u2500")}\u2500\u2518`;
1022
+ }
1023
+ return `\u2502 ${row.join(" \u2502 ")} \u2502`;
1024
+ }).join("\n");
1025
+ this.logWithLevel("log", formattedTable);
1026
+ }
1027
+ };
1028
+ var Logger_default = Logger;
1029
+ var logger = new Logger_default({
1030
+ prefix: color__default.default.cyan("[@zimic/interceptor]")
1031
+ });
1032
+ var importUtil = createCachedDynamicImport_default(() => import('util'));
1033
+ async function formatValueToLog(value, options = {}) {
1034
+ if (isClientSide()) {
1035
+ return value;
1036
+ }
1037
+ const { colors = true } = options;
1038
+ const util = await importUtil();
1039
+ return util.inspect(value, {
1040
+ colors,
1041
+ compact: true,
1042
+ depth: Infinity,
1043
+ maxArrayLength: Infinity,
1044
+ maxStringLength: Infinity,
1045
+ breakLength: Infinity,
1046
+ sorted: true
1047
+ });
1048
+ }
1049
+
1035
1050
  // src/http/requestHandler/types/requests.ts
1036
1051
  var HTTP_INTERCEPTOR_REQUEST_HIDDEN_PROPERTIES = Object.freeze(
1037
1052
  /* @__PURE__ */ new Set([
@@ -1070,7 +1085,13 @@ var HttpInterceptorWorker = class _HttpInterceptorWorker {
1070
1085
  startingPromise;
1071
1086
  stoppingPromise;
1072
1087
  runningInterceptors = [];
1088
+ get numberOfRunningInterceptors() {
1089
+ return this.runningInterceptors.length;
1090
+ }
1073
1091
  async sharedStart(internalStart) {
1092
+ if (this.stoppingPromise) {
1093
+ await this.stoppingPromise;
1094
+ }
1074
1095
  if (this.isRunning) {
1075
1096
  return;
1076
1097
  }
@@ -1099,9 +1120,12 @@ var HttpInterceptorWorker = class _HttpInterceptorWorker {
1099
1120
  const stoppingResult = internalStop();
1100
1121
  if (stoppingResult instanceof Promise) {
1101
1122
  this.stoppingPromise = stoppingResult;
1102
- await this.stoppingPromise;
1123
+ try {
1124
+ await this.stoppingPromise;
1125
+ } finally {
1126
+ this.stoppingPromise = void 0;
1127
+ }
1103
1128
  }
1104
- this.stoppingPromise = void 0;
1105
1129
  }
1106
1130
  async logUnhandledRequestIfNecessary(request, strategy) {
1107
1131
  if (strategy?.log) {
@@ -1339,7 +1363,7 @@ var HttpInterceptorWorker = class _HttpInterceptorWorker {
1339
1363
  formatValueToLog(request.body)
1340
1364
  ]);
1341
1365
  logger[action === "bypass" ? "warn" : "error"](
1342
- `${action === "bypass" ? "Warning:" : "Error:"} Request was not handled and was ${action === "bypass" ? color2__default.default.yellow("bypassed") : color2__default.default.red("rejected")}.
1366
+ `${action === "bypass" ? "Warning:" : "Error:"} Request was not handled and was ${action === "bypass" ? color__default.default.yellow("bypassed") : color__default.default.red("rejected")}.
1343
1367
 
1344
1368
  `,
1345
1369
  `${request.method} ${request.url}`,
@@ -1356,16 +1380,16 @@ var HttpInterceptorWorker = class _HttpInterceptorWorker {
1356
1380
  var HttpInterceptorWorker_default = HttpInterceptorWorker;
1357
1381
 
1358
1382
  // src/http/requestHandler/RemoteHttpRequestHandler.ts
1359
- var UNSYNCED_PROPERTIES = /* @__PURE__ */ new Set(["then"]);
1383
+ var PENDING_PROPERTIES = /* @__PURE__ */ new Set(["then"]);
1360
1384
  var RemoteHttpRequestHandler = class {
1361
1385
  type = "remote";
1362
1386
  implementation;
1363
1387
  syncPromises = [];
1364
- unsynced;
1388
+ pending;
1365
1389
  synced;
1366
1390
  constructor(interceptor, method, path) {
1367
1391
  this.implementation = new HttpRequestHandlerImplementation_default(interceptor, method, path, this);
1368
- this.unsynced = this;
1392
+ this.pending = this;
1369
1393
  this.synced = this.createSyncedProxy();
1370
1394
  }
1371
1395
  createSyncedProxy() {
@@ -1385,7 +1409,7 @@ var RemoteHttpRequestHandler = class {
1385
1409
  });
1386
1410
  }
1387
1411
  shouldBeHiddenPropertyWhenSynced(property) {
1388
- return UNSYNCED_PROPERTIES.has(property);
1412
+ return PENDING_PROPERTIES.has(property);
1389
1413
  }
1390
1414
  get method() {
1391
1415
  return this.implementation.method;
@@ -1395,16 +1419,16 @@ var RemoteHttpRequestHandler = class {
1395
1419
  }
1396
1420
  with(restriction) {
1397
1421
  this.implementation.with(restriction);
1398
- return this.unsynced;
1422
+ return this.pending;
1399
1423
  }
1400
1424
  delay(minMilliseconds, maxMilliseconds) {
1401
1425
  this.implementation.delay(minMilliseconds, maxMilliseconds);
1402
- return this.unsynced;
1426
+ return this.pending;
1403
1427
  }
1404
1428
  respond(declaration) {
1405
- const newUnsyncedThis = this.unsynced;
1406
- newUnsyncedThis.implementation.respond(declaration);
1407
- return newUnsyncedThis;
1429
+ const pending = this.pending;
1430
+ pending.implementation.respond(declaration);
1431
+ return pending;
1408
1432
  }
1409
1433
  times(minNumberOfRequests, maxNumberOfRequests) {
1410
1434
  this.implementation.times(minNumberOfRequests, maxNumberOfRequests);
@@ -1422,7 +1446,7 @@ var RemoteHttpRequestHandler = class {
1422
1446
  }
1423
1447
  clear() {
1424
1448
  this.implementation.clear();
1425
- return this.unsynced;
1449
+ return this.pending;
1426
1450
  }
1427
1451
  get requests() {
1428
1452
  return this.implementation.requests;
@@ -1454,7 +1478,7 @@ var RemoteHttpRequestHandler = class {
1454
1478
  const promisesToWait = new Set(this.syncPromises);
1455
1479
  return Promise.all(promisesToWait).then(() => {
1456
1480
  this.syncPromises = this.syncPromises.filter((promise) => !promisesToWait.has(promise));
1457
- return this.isSynced ? this.synced : this.unsynced;
1481
+ return this.isSynced ? this.synced : this.pending;
1458
1482
  }).then(onFulfilled, onRejected);
1459
1483
  }
1460
1484
  catch(onRejected) {
@@ -1475,6 +1499,9 @@ var HttpInterceptorImplementation = class {
1475
1499
  createWorker;
1476
1500
  deleteWorker;
1477
1501
  worker;
1502
+ startPromise;
1503
+ numberOfPendingStarts = 0;
1504
+ lifecycleQueue = Promise.resolve();
1478
1505
  requestSaving;
1479
1506
  numberOfSavedRequests = 0;
1480
1507
  onUnhandledRequest;
@@ -1508,7 +1535,7 @@ var HttpInterceptorImplementation = class {
1508
1535
  return this.#baseURL;
1509
1536
  }
1510
1537
  set baseURL(newBaseURL) {
1511
- if (this.isRunning) {
1538
+ if (this.isRunning || this.isStarting) {
1512
1539
  throw new RunningHttpInterceptorError_default(
1513
1540
  "Did you forget to call `await interceptor.stop()` before changing the base URL?"
1514
1541
  );
@@ -1532,27 +1559,67 @@ var HttpInterceptorImplementation = class {
1532
1559
  get platform() {
1533
1560
  return this.worker?.platform ?? null;
1534
1561
  }
1535
- async start() {
1562
+ start() {
1563
+ if (this.startPromise) {
1564
+ return this.startPromise;
1565
+ }
1566
+ this.numberOfPendingStarts++;
1567
+ const startPromise = this.enqueueLifecycleOperation(() => this.startOnce()).finally(() => {
1568
+ this.numberOfPendingStarts--;
1569
+ const isLastStartPromise = this.startPromise === startPromise;
1570
+ if (isLastStartPromise) {
1571
+ this.startPromise = void 0;
1572
+ }
1573
+ });
1574
+ this.startPromise = startPromise;
1575
+ return startPromise;
1576
+ }
1577
+ async startOnce() {
1578
+ if (this.isRunning) {
1579
+ return;
1580
+ }
1536
1581
  try {
1537
1582
  this.worker = this.createWorker();
1538
- await this.worker.start();
1539
1583
  this.worker.registerRunningInterceptor(this);
1584
+ await this.worker.start();
1540
1585
  this.markAsRunning(true);
1541
1586
  } catch (error) {
1542
- await this.stop();
1587
+ await this.stopWorker();
1543
1588
  throw error;
1544
1589
  }
1545
1590
  }
1546
- async stop() {
1591
+ get isStarting() {
1592
+ return this.numberOfPendingStarts > 0;
1593
+ }
1594
+ async stop(options) {
1595
+ this.startPromise = void 0;
1596
+ await this.enqueueLifecycleOperation(() => this.stopOnce(options));
1597
+ }
1598
+ async stopOnce(options) {
1599
+ if (!this.isRunning) {
1600
+ return;
1601
+ }
1602
+ await options.beforeStop?.();
1603
+ await this.stopWorker();
1604
+ }
1605
+ async stopWorker() {
1547
1606
  this.worker?.unregisterRunningInterceptor(this);
1548
- const isLastRunningInterceptor = this.numberOfRunningInterceptors === 0 || this.numberOfRunningInterceptors === 1;
1607
+ const isLastRunningInterceptor = this.worker?.numberOfRunningInterceptors === 0;
1549
1608
  if (isLastRunningInterceptor) {
1550
1609
  await this.worker?.stop();
1551
- this.deleteWorker();
1610
+ const isStillLastRunningInterceptor = this.worker?.numberOfRunningInterceptors === 0;
1611
+ if (isStillLastRunningInterceptor) {
1612
+ this.deleteWorker();
1613
+ }
1552
1614
  }
1553
1615
  this.markAsRunning(false);
1554
1616
  this.worker = void 0;
1555
1617
  }
1618
+ enqueueLifecycleOperation(operation) {
1619
+ const operationPromise = this.lifecycleQueue.then(operation);
1620
+ this.lifecycleQueue = operationPromise.catch(() => void 0);
1621
+ return operationPromise;
1622
+ }
1556
1623
  markAsRunning(isRunning) {
1557
1624
  if (this.workerOrThrow.type === "local") {
1558
1625
  this.store.markLocalInterceptorAsRunning(this, isRunning);
@@ -1561,16 +1628,6 @@ var HttpInterceptorImplementation = class {
1561
1628
  }
1562
1629
  this.isRunning = isRunning;
1563
1630
  }
1564
- get numberOfRunningInterceptors() {
1565
- if (!this.isRunning) {
1566
- return 0;
1567
- }
1568
- if (this.workerOrThrow.type === "local") {
1569
- return this.store.numberOfRunningLocalInterceptors;
1570
- } else {
1571
- return this.store.numberOfRunningRemoteInterceptors(this.baseURL);
1572
- }
1573
- }
1574
1631
  get(path) {
1575
1632
  return this.createHttpRequestHandler("GET", path);
1576
1633
  }
@@ -1719,13 +1776,91 @@ var HttpInterceptorImplementation = class {
1719
1776
  }
1720
1777
  };
1721
1778
  var HttpInterceptorImplementation_default = HttpInterceptorImplementation;
1779
+
1780
+ // src/interceptor/LocalMSWWorkerStore.ts
1722
1781
  var importMSWNode = createCachedDynamicImport_default(() => import('msw/node'));
1723
1782
  var importMSWBrowser = createCachedDynamicImport_default(() => import('msw/browser'));
1724
- var LocalHttpInterceptorWorker = class _LocalHttpInterceptorWorker extends HttpInterceptorWorker_default {
1725
- // Re-creating MSW workers may cause issues, so we should keep a single worker instance, even if all interceptor
1726
- // workers are stopped. See https://github.com/mswjs/msw/issues/2597.
1783
+ var LocalMSWWorkerStore = class _LocalMSWWorkerStore {
1727
1784
  static mswWorker;
1785
+ static creatingMSWWorkerPromise;
1786
+ static startingMSWWorkerPromise;
1787
+ static numberOfRunningWorkers = 0;
1728
1788
  static isMSWWorkerRunning = false;
1789
+ class = _LocalMSWWorkerStore;
1790
+ get mswWorker() {
1791
+ return this.class.mswWorker;
1792
+ }
1793
+ async getMSWWorkerOrCreate(options) {
1794
+ if (this.class.mswWorker) {
1795
+ return this.class.mswWorker;
1796
+ }
1797
+ this.class.creatingMSWWorkerPromise ??= this.createMSWWorker(options).then((mswWorker) => {
1798
+ this.class.mswWorker = mswWorker;
1799
+ return mswWorker;
1800
+ }).finally(() => {
1801
+ this.class.creatingMSWWorkerPromise = void 0;
1802
+ });
1803
+ return this.class.creatingMSWWorkerPromise;
1804
+ }
1805
+ async createMSWWorker(options) {
1806
+ if (isServerSide()) {
1807
+ const mswNode = await importMSWNode();
1808
+ if ("setupServer" in mswNode) {
1809
+ return mswNode.setupServer();
1810
+ }
1811
+ }
1812
+ if (isClientSide()) {
1813
+ const mswBrowser = await importMSWBrowser();
1814
+ if ("setupWorker" in mswBrowser) {
1815
+ return mswBrowser.setupWorker();
1816
+ }
1817
+ }
1818
+ throw options.createUnknownPlatformError();
1819
+ }
1820
+ async startMSWWorker(mswWorker, sharedOptions) {
1821
+ if (!this.class.isMSWWorkerRunning) {
1822
+ this.class.startingMSWWorkerPromise ??= this.startMSWWorkerOnce(mswWorker, sharedOptions).then(() => {
1823
+ this.class.isMSWWorkerRunning = true;
1824
+ }).finally(() => {
1825
+ this.class.startingMSWWorkerPromise = void 0;
1826
+ });
1827
+ await this.class.startingMSWWorkerPromise;
1828
+ }
1829
+ this.class.numberOfRunningWorkers++;
1830
+ }
1831
+ async startMSWWorkerOnce(mswWorker, sharedOptions) {
1832
+ if (this.isInternalBrowserWorker(mswWorker)) {
1833
+ try {
1834
+ await mswWorker.start({ ...sharedOptions, quiet: true });
1835
+ } catch (error) {
1836
+ if (UnregisteredBrowserServiceWorkerError_default.matchesRawError(error)) {
1837
+ throw new UnregisteredBrowserServiceWorkerError_default();
1838
+ } else {
1839
+ throw error;
1840
+ }
1841
+ }
1842
+ } else {
1843
+ mswWorker.listen(sharedOptions);
1844
+ }
1845
+ }
1846
+ stopMSWWorker(mswWorker) {
1847
+ this.class.numberOfRunningWorkers = Math.max(this.class.numberOfRunningWorkers - 1, 0);
1848
+ if (this.class.numberOfRunningWorkers > 0) {
1849
+ return;
1850
+ }
1851
+ if (this.isInternalBrowserWorker(mswWorker)) ; else {
1852
+ mswWorker.close();
1853
+ this.class.isMSWWorkerRunning = false;
1854
+ }
1855
+ }
1856
+ isInternalBrowserWorker(worker) {
1857
+ return "start" in worker && "stop" in worker;
1858
+ }
1859
+ };
1860
+ var LocalMSWWorkerStore_default = LocalMSWWorkerStore;
1861
+
1862
+ // src/http/interceptorWorker/LocalHttpInterceptorWorker.ts
1863
+ var LocalHttpInterceptorWorker = class extends HttpInterceptorWorker_default {
1729
1864
  mswHttpHandler;
1730
1865
  httpHandlersByMethod = {
1731
1866
  GET: [],
@@ -1736,39 +1871,28 @@ var LocalHttpInterceptorWorker = class _LocalHttpInterceptorWorker extends HttpI
1736
1871
  HEAD: [],
1737
1872
  OPTIONS: []
1738
1873
  };
1874
+ store = new LocalMSWWorkerStore_default();
1739
1875
  constructor(_options) {
1740
1876
  super();
1741
1877
  }
1742
- get class() {
1743
- return _LocalHttpInterceptorWorker;
1744
- }
1745
1878
  get type() {
1746
1879
  return "local";
1747
1880
  }
1748
1881
  get mswWorkerOrThrow() {
1749
- if (!this.class.mswWorker) {
1882
+ if (!this.store.mswWorker) {
1750
1883
  throw new NotRunningHttpInterceptorError_default();
1751
1884
  }
1752
- return this.class.mswWorker;
1885
+ return this.store.mswWorker;
1753
1886
  }
1754
1887
  async getMSWWorkerOrCreate() {
1755
- this.class.mswWorker ??= await this.createMSWWorker();
1756
- return this.class.mswWorker;
1757
- }
1758
- async createMSWWorker() {
1759
- if (isServerSide()) {
1760
- const mswNode = await importMSWNode();
1761
- if ("setupServer" in mswNode) {
1762
- return mswNode.setupServer();
1763
- }
1764
- }
1765
- if (isClientSide()) {
1766
- const mswBrowser = await importMSWBrowser();
1767
- if ("setupWorker" in mswBrowser) {
1768
- return mswBrowser.setupWorker();
1769
- }
1770
- }
1771
- throw new UnknownHttpInterceptorPlatformError_default();
1888
+ return this.store.getMSWWorkerOrCreate({
1889
+ createUnknownPlatformError: (
1890
+ // The unknown platform error is created here to prevent the store from relying on HTTP-specific resources.
1891
+ /* istanbul ignore next -- @preserve
1892
+ * Unknown runtime platforms are not part of the package test matrix. */
1893
+ () => new UnknownHttpInterceptorPlatformError_default()
1894
+ )
1895
+ });
1772
1896
  }
1773
1897
  async start() {
1774
1898
  await super.sharedStart(async () => {
@@ -1784,54 +1908,33 @@ var LocalHttpInterceptorWorker = class _LocalHttpInterceptorWorker extends HttpI
1784
1908
  mswWorker.use(this.mswHttpHandler);
1785
1909
  if (this.isInternalBrowserWorker(mswWorker)) {
1786
1910
  this.platform = "browser";
1787
- if (!this.class.isMSWWorkerRunning) {
1788
- await this.startInBrowser(mswWorker, sharedOptions);
1789
- this.class.isMSWWorkerRunning = true;
1790
- }
1791
1911
  } else {
1792
1912
  this.platform = "node";
1793
- this.startInNode(mswWorker, sharedOptions);
1794
- this.class.isMSWWorkerRunning = true;
1913
+ }
1914
+ try {
1915
+ await this.store.startMSWWorker(mswWorker, sharedOptions);
1916
+ } catch (error) {
1917
+ const newMSWHandlers = mswWorker.listHandlers().filter((handler) => handler !== this.mswHttpHandler);
1918
+ mswWorker.resetHandlers(...newMSWHandlers);
1919
+ this.mswHttpHandler = void 0;
1920
+ throw error;
1795
1921
  }
1796
1922
  this.isRunning = true;
1797
1923
  });
1798
1924
  }
1799
- async startInBrowser(mswWorker, sharedOptions) {
1800
- try {
1801
- await mswWorker.start({ ...sharedOptions, quiet: true });
1802
- } catch (error) {
1803
- this.handleBrowserWorkerStartError(error);
1804
- }
1805
- }
1806
- handleBrowserWorkerStartError(error) {
1807
- if (UnregisteredBrowserServiceWorkerError_default.matchesRawError(error)) {
1808
- throw new UnregisteredBrowserServiceWorkerError_default();
1809
- } else {
1810
- throw error;
1811
- }
1812
- }
1813
- startInNode(mswWorker, sharedOptions) {
1814
- mswWorker.listen(sharedOptions);
1815
- }
1816
1925
  async stop() {
1817
1926
  await super.sharedStop(async () => {
1818
1927
  const mswWorker = await this.getMSWWorkerOrCreate();
1819
1928
  this.clearHandlers();
1820
1929
  const newMSWHandlers = mswWorker.listHandlers().filter((handler) => handler !== this.mswHttpHandler);
1821
1930
  mswWorker.resetHandlers(...newMSWHandlers);
1822
- if (this.isInternalBrowserWorker(mswWorker)) ; else {
1823
- this.stopInNode(mswWorker);
1824
- this.class.isMSWWorkerRunning = false;
1825
- }
1931
+ this.store.stopMSWWorker(mswWorker);
1826
1932
  this.mswHttpHandler = void 0;
1827
1933
  this.isRunning = false;
1828
1934
  });
1829
1935
  }
1830
- stopInNode(mswWorker) {
1831
- mswWorker.close();
1832
- }
1833
1936
  isInternalBrowserWorker(worker) {
1834
- return "start" in worker && "stop" in worker;
1937
+ return this.store.isInternalBrowserWorker(worker);
1835
1938
  }
1836
1939
  hasInternalBrowserWorker() {
1837
1940
  return this.isInternalBrowserWorker(this.mswWorkerOrThrow);
@@ -2562,24 +2665,15 @@ var RemoteHttpInterceptorWorker = class extends HttpInterceptorWorker_default {
2562
2665
  };
2563
2666
  var RemoteHttpInterceptorWorker_default = RemoteHttpInterceptorWorker;
2564
2667
 
2565
- // src/http/interceptorWorker/factory.ts
2566
- function createHttpInterceptorWorker(options) {
2567
- if (options.type === "local") {
2568
- return new LocalHttpInterceptorWorker_default(options);
2569
- } else {
2570
- return new RemoteHttpInterceptorWorker_default(options);
2571
- }
2572
- }
2573
-
2574
2668
  // src/http/interceptor/HttpInterceptorStore.ts
2575
2669
  var HttpInterceptorStore = class _HttpInterceptorStore {
2576
- static _localWorker;
2577
- static runningLocalInterceptors = /* @__PURE__ */ new Set();
2670
+ static localWorker;
2578
2671
  static remoteWorkers = /* @__PURE__ */ new Map();
2672
+ static runningLocalInterceptors = /* @__PURE__ */ new Set();
2579
2673
  static runningRemoteInterceptors = /* @__PURE__ */ new Map();
2580
2674
  class = _HttpInterceptorStore;
2581
2675
  get localWorker() {
2582
- return this.class._localWorker;
2676
+ return this.class.localWorker;
2583
2677
  }
2584
2678
  getRemoteWorkerKey(baseURL, options) {
2585
2679
  const key = [`${baseURL.origin}${baseURL.pathname}`];
@@ -2588,7 +2682,7 @@ var HttpInterceptorStore = class _HttpInterceptorStore {
2588
2682
  }
2589
2683
  return key.join(":");
2590
2684
  }
2591
- remoteWorker(baseURL, options) {
2685
+ getRemoteWorker(baseURL, options) {
2592
2686
  const remoteWorkerKey = this.getRemoteWorkerKey(baseURL, options);
2593
2687
  return this.class.remoteWorkers.get(remoteWorkerKey);
2594
2688
  }
@@ -2620,16 +2714,16 @@ var HttpInterceptorStore = class _HttpInterceptorStore {
2620
2714
  return runningInterceptors;
2621
2715
  }
2622
2716
  getOrCreateLocalWorker(workerOptions) {
2623
- const existingWorker = this.class._localWorker;
2717
+ const existingWorker = this.class.localWorker;
2624
2718
  if (existingWorker) {
2625
2719
  return existingWorker;
2626
2720
  }
2627
- const createdWorker = createHttpInterceptorWorker({ ...workerOptions, type: "local" });
2628
- this.class._localWorker = createdWorker;
2721
+ const createdWorker = new LocalHttpInterceptorWorker_default({ ...workerOptions, type: "local" });
2722
+ this.class.localWorker = createdWorker;
2629
2723
  return createdWorker;
2630
2724
  }
2631
2725
  deleteLocalWorker() {
2632
- this.class._localWorker = void 0;
2726
+ this.class.localWorker = void 0;
2633
2727
  }
2634
2728
  getOrCreateRemoteWorker(workerOptions) {
2635
2729
  const remoteWorkerKey = this.getRemoteWorkerKey(workerOptions.serverURL, { auth: workerOptions.auth });
@@ -2637,7 +2731,7 @@ var HttpInterceptorStore = class _HttpInterceptorStore {
2637
2731
  if (existingWorker) {
2638
2732
  return existingWorker;
2639
2733
  }
2640
- const createdWorker = createHttpInterceptorWorker({ ...workerOptions, type: "remote" });
2734
+ const createdWorker = new RemoteHttpInterceptorWorker_default({ ...workerOptions, type: "remote" });
2641
2735
  this.class.remoteWorkers.set(remoteWorkerKey, createdWorker);
2642
2736
  return createdWorker;
2643
2737
  }
@@ -2692,17 +2786,10 @@ var LocalHttpInterceptor = class {
2692
2786
  return this.implementation.isRunning;
2693
2787
  }
2694
2788
  async start() {
2695
- if (this.isRunning) {
2696
- return;
2697
- }
2698
2789
  await this.implementation.start();
2699
2790
  }
2700
2791
  async stop() {
2701
- if (!this.isRunning) {
2702
- return;
2703
- }
2704
- this.clear();
2705
- await this.implementation.stop();
2792
+ await this.implementation.stop({ beforeStop: () => this.clear() });
2706
2793
  }
2707
2794
  get = ((path) => {
2708
2795
  return this.implementation.get(path);
@@ -2740,24 +2827,24 @@ var RemoteHttpInterceptor = class {
2740
2827
  implementation;
2741
2828
  #auth;
2742
2829
  constructor(options) {
2743
- this.#auth = options.auth;
2744
2830
  const baseURL = new URL(options.baseURL);
2745
2831
  this.implementation = new HttpInterceptorImplementation_default({
2746
2832
  store: this.store,
2747
2833
  baseURL,
2748
2834
  createWorker: () => {
2749
2835
  return this.store.getOrCreateRemoteWorker({
2750
- serverURL: baseURL,
2836
+ serverURL: this.implementation.baseURL,
2751
2837
  auth: this.#auth
2752
2838
  });
2753
2839
  },
2754
2840
  deleteWorker: () => {
2755
- this.store.deleteRemoteWorker(baseURL, { auth: options.auth });
2841
+ this.store.deleteRemoteWorker(this.implementation.baseURL, { auth: this.#auth });
2756
2842
  },
2757
2843
  Handler: RemoteHttpRequestHandler_default,
2758
2844
  onUnhandledRequest: options.onUnhandledRequest,
2759
2845
  requestSaving: options.requestSaving
2760
2846
  });
2847
+ this.auth = options.auth;
2761
2848
  }
2762
2849
  get type() {
2763
2850
  return "remote";
@@ -2779,21 +2866,25 @@ var RemoteHttpInterceptor = class {
2779
2866
  }
2780
2867
  set auth(auth) {
2781
2868
  const cannotChangeAuthWhileRunningMessage = "Did you forget to call `await interceptor.stop()` before changing the authentication parameters?";
2782
- if (this.isRunning) {
2869
+ if (this.isRunning || this.implementation.isStarting) {
2783
2870
  throw new RunningHttpInterceptorError_default(cannotChangeAuthWhileRunningMessage);
2784
2871
  }
2785
2872
  if (!auth) {
2786
2873
  this.#auth = void 0;
2787
2874
  return;
2788
2875
  }
2789
- this.#auth = new Proxy(auth, {
2790
- set: (target, property, value) => {
2791
- if (this.isRunning) {
2792
- throw new RunningHttpInterceptorError_default(cannotChangeAuthWhileRunningMessage);
2876
+ this.#auth = new Proxy(
2877
+ { ...auth },
2878
+ // Copy object to ensure it's not mutated later without going though the proxy.
2879
+ {
2880
+ set: (target, property, value) => {
2881
+ if (this.isRunning || this.implementation.isStarting) {
2882
+ throw new RunningHttpInterceptorError_default(cannotChangeAuthWhileRunningMessage);
2883
+ }
2884
+ return Reflect.set(target, property, value);
2793
2885
  }
2794
- return Reflect.set(target, property, value);
2795
2886
  }
2796
- });
2887
+ );
2797
2888
  }
2798
2889
  get onUnhandledRequest() {
2799
2890
  return this.implementation.onUnhandledRequest;
@@ -2808,17 +2899,10 @@ var RemoteHttpInterceptor = class {
2808
2899
  return this.implementation.isRunning;
2809
2900
  }
2810
2901
  async start() {
2811
- if (this.isRunning) {
2812
- return;
2813
- }
2814
2902
  await this.implementation.start();
2815
2903
  }
2816
2904
  async stop() {
2817
- if (!this.isRunning) {
2818
- return;
2819
- }
2820
- await this.clear();
2821
- await this.implementation.stop();
2905
+ await this.implementation.stop({ beforeStop: () => this.clear() });
2822
2906
  }
2823
2907
  get = ((path) => {
2824
2908
  return this.implementation.get(path);
@@ -2865,6 +2949,7 @@ function isRemoteHttpInterceptorOptions(options) {
2865
2949
  return options.type === "remote";
2866
2950
  }
2867
2951
  function createHttpInterceptor(options) {
2952
+ assertTypeOf_default("options.baseURL", options.baseURL, "string");
2868
2953
  const type = options.type;
2869
2954
  if (isLocalHttpInterceptorOptions(options)) {
2870
2955
  return new LocalHttpInterceptor_default(options);
@@ -2888,19 +2973,12 @@ var InvalidJSONError = class extends http.InvalidJSONError {
2888
2973
  * This is just a type guard to ensure the value is valid. In practice, this condition should never be true. */
2889
2974
  /* istanbul ignore next -- @preserve
2890
2975
  * Ignoring because there will always be a handler for the given method and path at this point. */
2891
- /* istanbul ignore if -- @preserve
2892
- * Trying to access the internal worker when it does not exist should not happen. */
2893
- /* istanbul ignore else -- @preserve
2894
- * We still check if we actually imported the server module in case our `isServerSide()` check returns true, but
2895
- * the environment actually resolves the browser module. */
2896
2976
  /* istanbul ignore else -- @preserve */
2977
+ /* istanbul ignore next -- @preserve */
2897
2978
  /* istanbul ignore else -- @preserve
2898
- * We still check if we actually imported the browser module in case our `isClientSide()` check returns true, but
2899
- * the environment actually resolves the server module. */
2900
- /* istanbul ignore next -- @preserve
2901
- * Ignoring because checking unknown platforms is not configured in our test setup. */
2902
- /* istanbul ignore else -- @preserve
2903
- * Since we start the internal worker once and do not stop it, tests may not be able exercise this branch. */
2979
+ * Browser worker start errors other than unregistered service workers come from MSW internals. */
2980
+ /* istanbul ignore if -- @preserve
2981
+ * Trying to access the internal worker when it does not exist should not happen. */
2904
2982
  /* istanbul ignore else -- @preserve
2905
2983
  * An unauthorized close event is the only one we expect to happen here. */
2906
2984
  /* istanbul ignore else -- @preserve
@@ -2914,6 +2992,8 @@ var InvalidJSONError = class extends http.InvalidJSONError {
2914
2992
  * would reach a timeout and not be responded. The empty set serves as a fallback. */
2915
2993
  /* istanbul ignore if -- @preserve
2916
2994
  * Aborting requests is highly non-deterministic because it depends on specific timing of socket events. */
2995
+ /* istanbul ignore next -- @preserve
2996
+ * Ignoring because checking unknown platforms is not configured in our test setup. */
2917
2997
  /* istanbul ignore next -- @preserve
2918
2998
  *
2919
2999
  * If the socket is closed before receiving a response, the message is aborted with an error. This can happen if
@@ -2922,7 +3002,6 @@ var InvalidJSONError = class extends http.InvalidJSONError {
2922
3002
  * necessary.
2923
3003
  *
2924
3004
  * Due to the rare nature of this edge case, we can't reliably reproduce it in tests. */
2925
- /* istanbul ignore next -- @preserve */
2926
3005
 
2927
3006
  exports.DisabledRequestSavingError = DisabledRequestSavingError_default;
2928
3007
  exports.HttpTimesCheckError = HttpTimesCheckError_default;