@zimic/interceptor 0.17.0-canary.2 → 0.17.0-canary.4

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 (60) hide show
  1. package/dist/{chunk-TYHJPU5G.js → chunk-MXHLBRPB.js} +521 -61
  2. package/dist/chunk-MXHLBRPB.js.map +1 -0
  3. package/dist/{chunk-3SKHNQLL.mjs → chunk-OGL76CKO.mjs} +510 -60
  4. package/dist/chunk-OGL76CKO.mjs.map +1 -0
  5. package/dist/cli.js +141 -17
  6. package/dist/cli.js.map +1 -1
  7. package/dist/cli.mjs +137 -13
  8. package/dist/cli.mjs.map +1 -1
  9. package/dist/http.d.ts +23 -2
  10. package/dist/http.js +473 -270
  11. package/dist/http.js.map +1 -1
  12. package/dist/http.mjs +473 -270
  13. package/dist/http.mjs.map +1 -1
  14. package/dist/scripts/postinstall.js +6 -6
  15. package/dist/scripts/postinstall.js.map +1 -1
  16. package/dist/scripts/postinstall.mjs +5 -5
  17. package/dist/scripts/postinstall.mjs.map +1 -1
  18. package/dist/server.d.ts +16 -0
  19. package/dist/server.js +6 -6
  20. package/dist/server.mjs +1 -1
  21. package/package.json +12 -11
  22. package/src/cli/browser/init.ts +5 -6
  23. package/src/cli/cli.ts +140 -55
  24. package/src/cli/server/start.ts +22 -7
  25. package/src/cli/server/token/create.ts +33 -0
  26. package/src/cli/server/token/list.ts +23 -0
  27. package/src/cli/server/token/remove.ts +22 -0
  28. package/src/http/interceptor/HttpInterceptorClient.ts +49 -27
  29. package/src/http/interceptor/HttpInterceptorStore.ts +25 -9
  30. package/src/http/interceptor/LocalHttpInterceptor.ts +6 -3
  31. package/src/http/interceptor/RemoteHttpInterceptor.ts +41 -5
  32. package/src/http/interceptor/errors/RunningHttpInterceptorError.ts +1 -1
  33. package/src/http/interceptor/types/options.ts +15 -0
  34. package/src/http/interceptor/types/public.ts +11 -3
  35. package/src/http/interceptorWorker/HttpInterceptorWorker.ts +14 -16
  36. package/src/http/interceptorWorker/RemoteHttpInterceptorWorker.ts +17 -12
  37. package/src/http/interceptorWorker/types/options.ts +1 -0
  38. package/src/http/requestHandler/errors/TimesCheckError.ts +1 -1
  39. package/src/server/InterceptorServer.ts +52 -8
  40. package/src/server/constants.ts +1 -1
  41. package/src/server/errors/InvalidInterceptorTokenError.ts +13 -0
  42. package/src/server/errors/InvalidInterceptorTokenFileError.ts +13 -0
  43. package/src/server/errors/InvalidInterceptorTokenValueError.ts +13 -0
  44. package/src/server/types/options.ts +9 -0
  45. package/src/server/types/public.ts +9 -0
  46. package/src/server/types/schema.ts +4 -4
  47. package/src/server/utils/auth.ts +304 -0
  48. package/src/server/utils/fetch.ts +3 -1
  49. package/src/utils/data.ts +13 -0
  50. package/src/utils/files.ts +14 -0
  51. package/src/utils/{console.ts → logging.ts} +5 -7
  52. package/src/utils/webSocket.ts +57 -11
  53. package/src/webSocket/WebSocketClient.ts +11 -5
  54. package/src/webSocket/WebSocketHandler.ts +72 -51
  55. package/src/webSocket/WebSocketServer.ts +25 -4
  56. package/src/webSocket/constants.ts +2 -0
  57. package/src/webSocket/errors/UnauthorizedWebSocketConnectionError.ts +11 -0
  58. package/src/webSocket/types.ts +49 -52
  59. package/dist/chunk-3SKHNQLL.mjs.map +0 -1
  60. package/dist/chunk-TYHJPU5G.js.map +0 -1
package/dist/http.mjs CHANGED
@@ -14,7 +14,7 @@ var RunningHttpInterceptorError = class extends Error {
14
14
  __name(this, "RunningHttpInterceptorError");
15
15
  }
16
16
  constructor(additionalMessage) {
17
- super(`The interceptor is running.${additionalMessage}`);
17
+ super(`The interceptor is running. ${additionalMessage}`);
18
18
  this.name = "RunningHttpInterceptorError";
19
19
  }
20
20
  };
@@ -174,6 +174,88 @@ __name(createCachedDynamicImport, "createCachedDynamicImport");
174
174
  __name2(createCachedDynamicImport, "createCachedDynamicImport");
175
175
  var createCachedDynamicImport_default = createCachedDynamicImport;
176
176
 
177
+ // ../zimic-utils/dist/logging/Logger.mjs
178
+ var Logger = class _Logger {
179
+ static {
180
+ __name(this, "_Logger");
181
+ }
182
+ static {
183
+ __name2(this, "Logger");
184
+ }
185
+ prefix;
186
+ raw;
187
+ constructor(options = {}) {
188
+ const { prefix } = options;
189
+ this.prefix = prefix;
190
+ this.raw = prefix ? new _Logger({ ...options, prefix: void 0 }) : this;
191
+ }
192
+ logWithLevel(level, ...messages) {
193
+ if (this.prefix) {
194
+ console[level](this.prefix, ...messages);
195
+ } else {
196
+ console[level](...messages);
197
+ }
198
+ }
199
+ info(...messages) {
200
+ this.logWithLevel("log", ...messages);
201
+ }
202
+ warn(...messages) {
203
+ this.logWithLevel("warn", ...messages);
204
+ }
205
+ error(...messages) {
206
+ this.logWithLevel("error", ...messages);
207
+ }
208
+ table(headers, rows) {
209
+ const columnLengths = headers.map((header) => {
210
+ let maxValueLength = header.title.length;
211
+ for (const row of rows) {
212
+ const value = row[header.property];
213
+ if (value.length > maxValueLength) {
214
+ maxValueLength = value.length;
215
+ }
216
+ }
217
+ return maxValueLength;
218
+ });
219
+ const formattedRows = [];
220
+ const horizontalLine = columnLengths.map((length) => "\u2500".repeat(length));
221
+ formattedRows.push(horizontalLine, []);
222
+ for (let headerIndex = 0; headerIndex < headers.length; headerIndex++) {
223
+ const header = headers[headerIndex];
224
+ const columnLength = columnLengths[headerIndex];
225
+ const value = header.title;
226
+ formattedRows.at(-1)?.push(value.padEnd(columnLength, " "));
227
+ }
228
+ formattedRows.push(horizontalLine);
229
+ for (const row of rows) {
230
+ formattedRows.push([]);
231
+ for (let headerIndex = 0; headerIndex < headers.length; headerIndex++) {
232
+ const header = headers[headerIndex];
233
+ const columnLength = columnLengths[headerIndex];
234
+ const value = row[header.property];
235
+ formattedRows.at(-1)?.push(value.padEnd(columnLength, " "));
236
+ }
237
+ }
238
+ formattedRows.push(horizontalLine);
239
+ const formattedTable = formattedRows.map((row, index) => {
240
+ const isFirstLine = index === 0;
241
+ if (isFirstLine) {
242
+ return `\u250C\u2500${row.join("\u2500\u252C\u2500")}\u2500\u2510`;
243
+ }
244
+ const isLineAfterHeaders = index === 2;
245
+ if (isLineAfterHeaders) {
246
+ return `\u251C\u2500${row.join("\u2500\u253C\u2500")}\u2500\u2524`;
247
+ }
248
+ const isLastLine = index === formattedRows.length - 1;
249
+ if (isLastLine) {
250
+ return `\u2514\u2500${row.join("\u2500\u2534\u2500")}\u2500\u2518`;
251
+ }
252
+ return `\u2502 ${row.join(" \u2502 ")} \u2502`;
253
+ }).join("\n");
254
+ this.logWithLevel("log", formattedTable);
255
+ }
256
+ };
257
+ var Logger_default = Logger;
258
+
177
259
  // src/utils/environment.ts
178
260
  function isServerSide() {
179
261
  return typeof process !== "undefined" && typeof process.versions !== "undefined";
@@ -188,7 +270,10 @@ function isGlobalFileAvailable() {
188
270
  }
189
271
  __name(isGlobalFileAvailable, "isGlobalFileAvailable");
190
272
 
191
- // src/utils/console.ts
273
+ // src/utils/logging.ts
274
+ var logger = new Logger_default({
275
+ prefix: color2.cyan("[@zimic/interceptor]")
276
+ });
192
277
  function stringifyJSONToLog(value) {
193
278
  return JSON.stringify(
194
279
  value,
@@ -243,12 +328,6 @@ async function formatValueToLog(value, options = {}) {
243
328
  });
244
329
  }
245
330
  __name(formatValueToLog, "formatValueToLog");
246
- function logWithPrefix(messageOrMessages, options = {}) {
247
- const { method = "log" } = options;
248
- const messages = Array.isArray(messageOrMessages) ? messageOrMessages : [messageOrMessages];
249
- console[method](color2.cyan("[@zimic/interceptor]"), ...messages);
250
- }
251
- __name(logWithPrefix, "logWithPrefix");
252
331
 
253
332
  // src/http/requestHandler/errors/TimesCheckError.ts
254
333
  function createMessageHeader({
@@ -1173,209 +1252,23 @@ var HttpInterceptorWorker = class _HttpInterceptorWorker {
1173
1252
  formatValueToLog(request.searchParams.toObject()),
1174
1253
  formatValueToLog(request.body)
1175
1254
  ]);
1176
- logWithPrefix(
1177
- [
1178
- `${action === "bypass" ? "Warning:" : "Error:"} Request was not handled and was ${action === "bypass" ? color2.yellow("bypassed") : color2.red("rejected")}.
1255
+ logger[action === "bypass" ? "warn" : "error"](
1256
+ `${action === "bypass" ? "Warning:" : "Error:"} Request was not handled and was ${action === "bypass" ? color2.yellow("bypassed") : color2.red("rejected")}.
1179
1257
 
1180
1258
  `,
1181
- `${request.method} ${request.url}`,
1182
- "\n Headers:",
1183
- formattedHeaders,
1184
- "\n Search params:",
1185
- formattedSearchParams,
1186
- "\n Body:",
1187
- formattedBody,
1188
- "\n\nLearn more: https://github.com/zimicjs/zimic/wiki/api\u2010zimic\u2010interceptor\u2010http#unhandled-requests"
1189
- ],
1190
- { method: action === "bypass" ? "warn" : "error" }
1259
+ `${request.method} ${request.url}`,
1260
+ "\n Headers:",
1261
+ formattedHeaders,
1262
+ "\n Search params:",
1263
+ formattedSearchParams,
1264
+ "\n Body:",
1265
+ formattedBody,
1266
+ "\n\nLearn more: https://github.com/zimicjs/zimic/wiki/api\u2010zimic\u2010interceptor\u2010http#unhandled-requests"
1191
1267
  );
1192
1268
  }
1193
1269
  };
1194
1270
  var HttpInterceptorWorker_default = HttpInterceptorWorker;
1195
1271
 
1196
- // ../zimic-utils/dist/url/validateURLPathParams.mjs
1197
- var DuplicatedPathParamError = class extends Error {
1198
- static {
1199
- __name(this, "DuplicatedPathParamError");
1200
- }
1201
- static {
1202
- __name2(this, "DuplicatedPathParamError");
1203
- }
1204
- constructor(url, paramName) {
1205
- super(
1206
- `The path parameter '${paramName}' appears more than once in the URL '${url.toString()}'. This is not supported. Please make sure that each parameter is unique.`
1207
- );
1208
- this.name = "DuplicatedPathParamError";
1209
- }
1210
- };
1211
- function validateURLPathParams(url) {
1212
- URL_PATH_PARAM_REGEX.lastIndex = 0;
1213
- const matches = url.toString().matchAll(URL_PATH_PARAM_REGEX);
1214
- const uniqueParamNames = /* @__PURE__ */ new Set();
1215
- for (const match of matches) {
1216
- const paramName = match[1];
1217
- if (uniqueParamNames.has(paramName)) {
1218
- throw new DuplicatedPathParamError(url, paramName);
1219
- }
1220
- uniqueParamNames.add(paramName);
1221
- }
1222
- }
1223
- __name(validateURLPathParams, "validateURLPathParams");
1224
- __name2(validateURLPathParams, "validateURLPathParams");
1225
- var validateURLPathParams_default = validateURLPathParams;
1226
- var LocalHttpInterceptorWorker = class extends HttpInterceptorWorker_default {
1227
- static {
1228
- __name(this, "LocalHttpInterceptorWorker");
1229
- }
1230
- internalWorker;
1231
- defaultHttpHandler;
1232
- httpHandlerGroups = [];
1233
- constructor(_options) {
1234
- super();
1235
- this.defaultHttpHandler = http.all("*", async (context) => {
1236
- const request = context.request;
1237
- return this.bypassOrRejectUnhandledRequest(request);
1238
- });
1239
- }
1240
- get type() {
1241
- return "local";
1242
- }
1243
- get internalWorkerOrThrow() {
1244
- if (!this.internalWorker) {
1245
- throw new NotRunningHttpInterceptorError_default();
1246
- }
1247
- return this.internalWorker;
1248
- }
1249
- get internalWorkerOrCreate() {
1250
- this.internalWorker ??= this.createInternalWorker();
1251
- return this.internalWorker;
1252
- }
1253
- createInternalWorker() {
1254
- if (isServerSide() && "setupServer" in mswNode) {
1255
- return mswNode.setupServer(this.defaultHttpHandler);
1256
- }
1257
- if (isClientSide() && "setupWorker" in mswBrowser) {
1258
- return mswBrowser.setupWorker(this.defaultHttpHandler);
1259
- }
1260
- throw new UnknownHttpInterceptorPlatformError_default();
1261
- }
1262
- async start() {
1263
- await super.sharedStart(async () => {
1264
- const internalWorker = this.internalWorkerOrCreate;
1265
- const sharedOptions = {
1266
- onUnhandledRequest: "bypass"
1267
- };
1268
- if (this.isInternalBrowserWorker(internalWorker)) {
1269
- this.platform = "browser";
1270
- await this.startInBrowser(internalWorker, sharedOptions);
1271
- } else {
1272
- this.platform = "node";
1273
- this.startInNode(internalWorker, sharedOptions);
1274
- }
1275
- this.isRunning = true;
1276
- });
1277
- }
1278
- async startInBrowser(internalWorker, sharedOptions) {
1279
- try {
1280
- await internalWorker.start({ ...sharedOptions, quiet: true });
1281
- } catch (error) {
1282
- this.handleBrowserWorkerStartError(error);
1283
- }
1284
- }
1285
- handleBrowserWorkerStartError(error) {
1286
- if (UnregisteredBrowserServiceWorkerError_default.matchesRawError(error)) {
1287
- throw new UnregisteredBrowserServiceWorkerError_default();
1288
- }
1289
- throw error;
1290
- }
1291
- startInNode(internalWorker, sharedOptions) {
1292
- internalWorker.listen(sharedOptions);
1293
- }
1294
- async stop() {
1295
- await super.sharedStop(() => {
1296
- const internalWorker = this.internalWorkerOrCreate;
1297
- if (this.isInternalBrowserWorker(internalWorker)) {
1298
- this.stopInBrowser(internalWorker);
1299
- } else {
1300
- this.stopInNode(internalWorker);
1301
- }
1302
- this.clearHandlers();
1303
- this.internalWorker = void 0;
1304
- this.isRunning = false;
1305
- });
1306
- }
1307
- stopInBrowser(internalWorker) {
1308
- internalWorker.stop();
1309
- }
1310
- stopInNode(internalWorker) {
1311
- internalWorker.close();
1312
- }
1313
- isInternalBrowserWorker(worker) {
1314
- return "start" in worker && "stop" in worker;
1315
- }
1316
- hasInternalBrowserWorker() {
1317
- return this.isInternalBrowserWorker(this.internalWorkerOrThrow);
1318
- }
1319
- hasInternalNodeWorker() {
1320
- return !this.hasInternalBrowserWorker();
1321
- }
1322
- use(interceptor, method, rawURL, createResponse) {
1323
- const lowercaseMethod = method.toLowerCase();
1324
- const url = new URL(rawURL);
1325
- excludeURLParams_default(url);
1326
- validateURLPathParams_default(url);
1327
- const httpHandler = http[lowercaseMethod](url.toString(), async (context) => {
1328
- const request = context.request;
1329
- const requestClone = request.clone();
1330
- let response = null;
1331
- try {
1332
- response = await createResponse({ ...context, request });
1333
- } catch (error) {
1334
- console.error(error);
1335
- }
1336
- if (!response) {
1337
- return this.bypassOrRejectUnhandledRequest(requestClone);
1338
- }
1339
- if (context.request.method === "HEAD") {
1340
- return new Response(null, {
1341
- status: response.status,
1342
- statusText: response.statusText,
1343
- headers: response.headers
1344
- });
1345
- }
1346
- return response;
1347
- });
1348
- this.internalWorkerOrThrow.use(httpHandler);
1349
- this.httpHandlerGroups.push({ interceptor, httpHandler });
1350
- }
1351
- async bypassOrRejectUnhandledRequest(request) {
1352
- const requestClone = request.clone();
1353
- const strategy = await super.getUnhandledRequestStrategy(request, "local");
1354
- await super.logUnhandledRequestIfNecessary(requestClone, strategy);
1355
- if (strategy?.action === "reject") {
1356
- return Response.error();
1357
- } else {
1358
- return passthrough();
1359
- }
1360
- }
1361
- clearHandlers() {
1362
- this.internalWorkerOrThrow.resetHandlers();
1363
- this.httpHandlerGroups = [];
1364
- }
1365
- clearInterceptorHandlers(interceptor) {
1366
- const groupToRemoveIndex = this.httpHandlerGroups.findIndex((group) => group.interceptor === interceptor);
1367
- removeArrayIndex(this.httpHandlerGroups, groupToRemoveIndex);
1368
- this.internalWorkerOrThrow.resetHandlers();
1369
- for (const { httpHandler } of this.httpHandlerGroups) {
1370
- this.internalWorkerOrThrow.use(httpHandler);
1371
- }
1372
- }
1373
- get interceptorsWithHandlers() {
1374
- return this.httpHandlerGroups.map((group) => group.interceptor);
1375
- }
1376
- };
1377
- var LocalHttpInterceptorWorker_default = LocalHttpInterceptorWorker;
1378
-
1379
1272
  // src/http/requestHandler/RemoteHttpRequestHandler.ts
1380
1273
  var PENDING_PROPERTIES = /* @__PURE__ */ new Set(["then"]);
1381
1274
  var RemoteHttpRequestHandler = class {
@@ -1485,9 +1378,11 @@ var HttpInterceptorClient = class {
1485
1378
  static {
1486
1379
  __name(this, "HttpInterceptorClient");
1487
1380
  }
1488
- worker;
1489
1381
  store;
1490
1382
  _baseURL;
1383
+ createWorker;
1384
+ deleteWorker;
1385
+ worker;
1491
1386
  requestSaving;
1492
1387
  numberOfSavedRequests = 0;
1493
1388
  onUnhandledRequest;
@@ -1503,9 +1398,10 @@ var HttpInterceptorClient = class {
1503
1398
  OPTIONS: /* @__PURE__ */ new Map()
1504
1399
  };
1505
1400
  constructor(options) {
1506
- this.worker = options.worker;
1507
1401
  this.store = options.store;
1508
1402
  this.baseURL = options.baseURL;
1403
+ this.createWorker = options.createWorker;
1404
+ this.deleteWorker = options.deleteWorker;
1509
1405
  this.requestSaving = {
1510
1406
  enabled: options.requestSaving?.enabled ?? this.getDefaultRequestSavingEnabled(),
1511
1407
  safeLimit: options.requestSaving?.safeLimit ?? DEFAULT_REQUEST_SAVING_SAFE_LIMIT
@@ -1535,32 +1431,49 @@ var HttpInterceptorClient = class {
1535
1431
  }
1536
1432
  return this.baseURL.href;
1537
1433
  }
1434
+ get workerOrThrow() {
1435
+ if (!this.worker) {
1436
+ throw new NotRunningHttpInterceptorError_default();
1437
+ }
1438
+ return this.worker;
1439
+ }
1538
1440
  get platform() {
1539
- return this.worker.platform;
1441
+ return this.worker?.platform ?? null;
1540
1442
  }
1541
1443
  async start() {
1542
- await this.worker.start();
1543
- this.worker.registerRunningInterceptor(this);
1544
- this.markAsRunning(true);
1444
+ try {
1445
+ this.worker = this.createWorker();
1446
+ await this.worker.start();
1447
+ this.worker.registerRunningInterceptor(this);
1448
+ this.markAsRunning(true);
1449
+ } catch (error) {
1450
+ await this.stop();
1451
+ throw error;
1452
+ }
1545
1453
  }
1546
1454
  async stop() {
1547
- this.markAsRunning(false);
1548
- this.worker.unregisterRunningInterceptor(this);
1549
- const wasLastRunningInterceptor = this.numberOfRunningInterceptors() === 0;
1550
- if (wasLastRunningInterceptor) {
1551
- await this.worker.stop();
1455
+ this.worker?.unregisterRunningInterceptor(this);
1456
+ const isLastRunningInterceptor = this.numberOfRunningInterceptors === 0 || this.numberOfRunningInterceptors === 1;
1457
+ if (isLastRunningInterceptor) {
1458
+ await this.worker?.stop();
1459
+ this.deleteWorker();
1552
1460
  }
1461
+ this.markAsRunning(false);
1462
+ this.worker = void 0;
1553
1463
  }
1554
1464
  markAsRunning(isRunning) {
1555
- if (this.worker instanceof LocalHttpInterceptorWorker_default) {
1465
+ if (this.workerOrThrow.type === "local") {
1556
1466
  this.store.markLocalInterceptorAsRunning(this, isRunning);
1557
1467
  } else {
1558
1468
  this.store.markRemoteInterceptorAsRunning(this, isRunning, this.baseURL);
1559
1469
  }
1560
1470
  this.isRunning = isRunning;
1561
1471
  }
1562
- numberOfRunningInterceptors() {
1563
- if (this.worker instanceof LocalHttpInterceptorWorker_default) {
1472
+ get numberOfRunningInterceptors() {
1473
+ if (!this.isRunning) {
1474
+ return 0;
1475
+ }
1476
+ if (this.workerOrThrow.type === "local") {
1564
1477
  return this.store.numberOfRunningLocalInterceptors;
1565
1478
  } else {
1566
1479
  return this.store.numberOfRunningRemoteInterceptors(this.baseURL);
@@ -1609,7 +1522,7 @@ var HttpInterceptorClient = class {
1609
1522
  this.handlerClientsByMethod[handler.method].set(handler.path, handlerClients);
1610
1523
  const url = joinURL_default(this.baseURLAsString, handler.path);
1611
1524
  const urlRegex = createRegExpFromURL_default(url);
1612
- const registrationResult = this.worker.use(this, handler.method, url, async (context) => {
1525
+ const registrationResult = this.workerOrThrow.use(this, handler.method, url, async (context) => {
1613
1526
  const response = await this.handleInterceptedRequest(
1614
1527
  urlRegex,
1615
1528
  handler.method,
@@ -1668,10 +1581,9 @@ var HttpInterceptorClient = class {
1668
1581
  }
1669
1582
  }
1670
1583
  clear(options = {}) {
1671
- if (!this.isRunning) {
1672
- throw new NotRunningHttpInterceptorError_default();
1673
- }
1674
- const clearResults = [];
1584
+ const clearResults = [
1585
+ this.workerOrThrow.clearInterceptorHandlers(this)
1586
+ ];
1675
1587
  for (const method of HTTP_METHODS) {
1676
1588
  const newClearResults = this.clearMethodHandlers(method);
1677
1589
  for (const result of newClearResults) {
@@ -1680,8 +1592,6 @@ var HttpInterceptorClient = class {
1680
1592
  const handlersByPath = this.handlerClientsByMethod[method];
1681
1593
  handlersByPath.clear();
1682
1594
  }
1683
- const clearResult = this.worker.clearInterceptorHandlers(this);
1684
- clearResults.push(clearResult);
1685
1595
  if (options.onCommitSuccess) {
1686
1596
  void Promise.all(clearResults).then(options.onCommitSuccess, options.onCommitError);
1687
1597
  }
@@ -1699,6 +1609,189 @@ var HttpInterceptorClient = class {
1699
1609
  };
1700
1610
  var HttpInterceptorClient_default = HttpInterceptorClient;
1701
1611
 
1612
+ // ../zimic-utils/dist/url/validateURLPathParams.mjs
1613
+ var DuplicatedPathParamError = class extends Error {
1614
+ static {
1615
+ __name(this, "DuplicatedPathParamError");
1616
+ }
1617
+ static {
1618
+ __name2(this, "DuplicatedPathParamError");
1619
+ }
1620
+ constructor(url, paramName) {
1621
+ super(
1622
+ `The path parameter '${paramName}' appears more than once in the URL '${url.toString()}'. This is not supported. Please make sure that each parameter is unique.`
1623
+ );
1624
+ this.name = "DuplicatedPathParamError";
1625
+ }
1626
+ };
1627
+ function validateURLPathParams(url) {
1628
+ URL_PATH_PARAM_REGEX.lastIndex = 0;
1629
+ const matches = url.toString().matchAll(URL_PATH_PARAM_REGEX);
1630
+ const uniqueParamNames = /* @__PURE__ */ new Set();
1631
+ for (const match of matches) {
1632
+ const paramName = match[1];
1633
+ if (uniqueParamNames.has(paramName)) {
1634
+ throw new DuplicatedPathParamError(url, paramName);
1635
+ }
1636
+ uniqueParamNames.add(paramName);
1637
+ }
1638
+ }
1639
+ __name(validateURLPathParams, "validateURLPathParams");
1640
+ __name2(validateURLPathParams, "validateURLPathParams");
1641
+ var validateURLPathParams_default = validateURLPathParams;
1642
+ var LocalHttpInterceptorWorker = class extends HttpInterceptorWorker_default {
1643
+ static {
1644
+ __name(this, "LocalHttpInterceptorWorker");
1645
+ }
1646
+ internalWorker;
1647
+ defaultHttpHandler;
1648
+ httpHandlerGroups = [];
1649
+ constructor(_options) {
1650
+ super();
1651
+ this.defaultHttpHandler = http.all("*", async (context) => {
1652
+ const request = context.request;
1653
+ return this.bypassOrRejectUnhandledRequest(request);
1654
+ });
1655
+ }
1656
+ get type() {
1657
+ return "local";
1658
+ }
1659
+ get internalWorkerOrThrow() {
1660
+ if (!this.internalWorker) {
1661
+ throw new NotRunningHttpInterceptorError_default();
1662
+ }
1663
+ return this.internalWorker;
1664
+ }
1665
+ get internalWorkerOrCreate() {
1666
+ this.internalWorker ??= this.createInternalWorker();
1667
+ return this.internalWorker;
1668
+ }
1669
+ createInternalWorker() {
1670
+ if (isServerSide() && "setupServer" in mswNode) {
1671
+ return mswNode.setupServer(this.defaultHttpHandler);
1672
+ }
1673
+ if (isClientSide() && "setupWorker" in mswBrowser) {
1674
+ return mswBrowser.setupWorker(this.defaultHttpHandler);
1675
+ }
1676
+ throw new UnknownHttpInterceptorPlatformError_default();
1677
+ }
1678
+ async start() {
1679
+ await super.sharedStart(async () => {
1680
+ const internalWorker = this.internalWorkerOrCreate;
1681
+ const sharedOptions = {
1682
+ onUnhandledRequest: "bypass"
1683
+ };
1684
+ if (this.isInternalBrowserWorker(internalWorker)) {
1685
+ this.platform = "browser";
1686
+ await this.startInBrowser(internalWorker, sharedOptions);
1687
+ } else {
1688
+ this.platform = "node";
1689
+ this.startInNode(internalWorker, sharedOptions);
1690
+ }
1691
+ this.isRunning = true;
1692
+ });
1693
+ }
1694
+ async startInBrowser(internalWorker, sharedOptions) {
1695
+ try {
1696
+ await internalWorker.start({ ...sharedOptions, quiet: true });
1697
+ } catch (error) {
1698
+ this.handleBrowserWorkerStartError(error);
1699
+ }
1700
+ }
1701
+ handleBrowserWorkerStartError(error) {
1702
+ if (UnregisteredBrowserServiceWorkerError_default.matchesRawError(error)) {
1703
+ throw new UnregisteredBrowserServiceWorkerError_default();
1704
+ }
1705
+ throw error;
1706
+ }
1707
+ startInNode(internalWorker, sharedOptions) {
1708
+ internalWorker.listen(sharedOptions);
1709
+ }
1710
+ async stop() {
1711
+ await super.sharedStop(() => {
1712
+ const internalWorker = this.internalWorkerOrCreate;
1713
+ if (this.isInternalBrowserWorker(internalWorker)) {
1714
+ this.stopInBrowser(internalWorker);
1715
+ } else {
1716
+ this.stopInNode(internalWorker);
1717
+ }
1718
+ this.clearHandlers();
1719
+ this.internalWorker = void 0;
1720
+ this.isRunning = false;
1721
+ });
1722
+ }
1723
+ stopInBrowser(internalWorker) {
1724
+ internalWorker.stop();
1725
+ }
1726
+ stopInNode(internalWorker) {
1727
+ internalWorker.close();
1728
+ }
1729
+ isInternalBrowserWorker(worker) {
1730
+ return "start" in worker && "stop" in worker;
1731
+ }
1732
+ hasInternalBrowserWorker() {
1733
+ return this.isInternalBrowserWorker(this.internalWorkerOrThrow);
1734
+ }
1735
+ hasInternalNodeWorker() {
1736
+ return !this.hasInternalBrowserWorker();
1737
+ }
1738
+ use(interceptor, method, rawURL, createResponse) {
1739
+ const lowercaseMethod = method.toLowerCase();
1740
+ const url = new URL(rawURL);
1741
+ excludeURLParams_default(url);
1742
+ validateURLPathParams_default(url);
1743
+ const httpHandler = http[lowercaseMethod](url.toString(), async (context) => {
1744
+ const request = context.request;
1745
+ const requestClone = request.clone();
1746
+ let response = null;
1747
+ try {
1748
+ response = await createResponse({ ...context, request });
1749
+ } catch (error) {
1750
+ console.error(error);
1751
+ }
1752
+ if (!response) {
1753
+ return this.bypassOrRejectUnhandledRequest(requestClone);
1754
+ }
1755
+ if (context.request.method === "HEAD") {
1756
+ return new Response(null, {
1757
+ status: response.status,
1758
+ statusText: response.statusText,
1759
+ headers: response.headers
1760
+ });
1761
+ }
1762
+ return response;
1763
+ });
1764
+ this.internalWorkerOrThrow.use(httpHandler);
1765
+ this.httpHandlerGroups.push({ interceptor, httpHandler });
1766
+ }
1767
+ async bypassOrRejectUnhandledRequest(request) {
1768
+ const requestClone = request.clone();
1769
+ const strategy = await super.getUnhandledRequestStrategy(request, "local");
1770
+ await super.logUnhandledRequestIfNecessary(requestClone, strategy);
1771
+ if (strategy?.action === "reject") {
1772
+ return Response.error();
1773
+ } else {
1774
+ return passthrough();
1775
+ }
1776
+ }
1777
+ clearHandlers() {
1778
+ this.internalWorkerOrThrow.resetHandlers();
1779
+ this.httpHandlerGroups = [];
1780
+ }
1781
+ clearInterceptorHandlers(interceptor) {
1782
+ const groupToRemoveIndex = this.httpHandlerGroups.findIndex((group) => group.interceptor === interceptor);
1783
+ removeArrayIndex(this.httpHandlerGroups, groupToRemoveIndex);
1784
+ this.internalWorkerOrThrow.resetHandlers();
1785
+ for (const { httpHandler } of this.httpHandlerGroups) {
1786
+ this.internalWorkerOrThrow.use(httpHandler);
1787
+ }
1788
+ }
1789
+ get interceptorsWithHandlers() {
1790
+ return this.httpHandlerGroups.map((group) => group.interceptor);
1791
+ }
1792
+ };
1793
+ var LocalHttpInterceptorWorker_default = LocalHttpInterceptorWorker;
1794
+
1702
1795
  // src/utils/crypto.ts
1703
1796
  var importCrypto = createCachedDynamicImport_default(async () => {
1704
1797
  const globalCrypto = globalThis.crypto;
@@ -1762,6 +1855,19 @@ async function serializeResponse(response) {
1762
1855
  }
1763
1856
  __name(serializeResponse, "serializeResponse");
1764
1857
 
1858
+ // src/webSocket/errors/UnauthorizedWebSocketConnectionError.ts
1859
+ var UnauthorizedWebSocketConnectionError = class extends Error {
1860
+ constructor(event) {
1861
+ super(`${event.reason} (code ${event.code})`);
1862
+ this.event = event;
1863
+ this.name = "UnauthorizedWebSocketConnectionError";
1864
+ }
1865
+ static {
1866
+ __name(this, "UnauthorizedWebSocketConnectionError");
1867
+ }
1868
+ };
1869
+ var UnauthorizedWebSocketConnectionError_default = UnauthorizedWebSocketConnectionError;
1870
+
1765
1871
  // src/utils/webSocket.ts
1766
1872
  var WebSocketTimeoutError = class extends Error {
1767
1873
  static {
@@ -1807,29 +1913,58 @@ var WebSocketCloseTimeoutError = class extends WebSocketTimeoutError {
1807
1913
  var DEFAULT_WEB_SOCKET_LIFECYCLE_TIMEOUT = 60 * 1e3;
1808
1914
  var DEFAULT_WEB_SOCKET_MESSAGE_TIMEOUT = 3 * 60 * 1e3;
1809
1915
  async function waitForOpenClientSocket(socket, options = {}) {
1810
- const { timeout: timeoutDuration = DEFAULT_WEB_SOCKET_LIFECYCLE_TIMEOUT } = options;
1916
+ const { timeout: timeoutDuration = DEFAULT_WEB_SOCKET_LIFECYCLE_TIMEOUT, waitForAuthentication = false } = options;
1811
1917
  const isAlreadyOpen = socket.readyState === socket.OPEN;
1812
1918
  if (isAlreadyOpen) {
1813
1919
  return;
1814
1920
  }
1815
1921
  await new Promise((resolve, reject) => {
1816
- function handleOpenError(error) {
1922
+ function removeAllSocketListeners() {
1923
+ socket.removeEventListener("message", handleSocketMessage);
1817
1924
  socket.removeEventListener("open", handleOpenSuccess);
1925
+ socket.removeEventListener("error", handleOpenError);
1926
+ socket.removeEventListener("close", handleClose);
1927
+ }
1928
+ __name(removeAllSocketListeners, "removeAllSocketListeners");
1929
+ function handleOpenError(error) {
1930
+ removeAllSocketListeners();
1818
1931
  reject(error);
1819
1932
  }
1820
1933
  __name(handleOpenError, "handleOpenError");
1934
+ function handleClose(event) {
1935
+ const isUnauthorized = event.code === 1008;
1936
+ if (isUnauthorized) {
1937
+ const unauthorizedError = new UnauthorizedWebSocketConnectionError_default(event);
1938
+ handleOpenError(unauthorizedError);
1939
+ } else {
1940
+ handleOpenError(event);
1941
+ }
1942
+ }
1943
+ __name(handleClose, "handleClose");
1821
1944
  const openTimeout = setTimeout(() => {
1822
1945
  const timeoutError = new WebSocketOpenTimeoutError(timeoutDuration);
1823
1946
  handleOpenError(timeoutError);
1824
1947
  }, timeoutDuration);
1825
1948
  function handleOpenSuccess() {
1826
- socket.removeEventListener("error", handleOpenError);
1949
+ removeAllSocketListeners();
1827
1950
  clearTimeout(openTimeout);
1828
1951
  resolve();
1829
1952
  }
1830
1953
  __name(handleOpenSuccess, "handleOpenSuccess");
1831
- socket.addEventListener("open", handleOpenSuccess);
1954
+ function handleSocketMessage(message) {
1955
+ const hasValidAuth = message.data === "socket:auth:valid";
1956
+ if (hasValidAuth) {
1957
+ handleOpenSuccess();
1958
+ }
1959
+ }
1960
+ __name(handleSocketMessage, "handleSocketMessage");
1961
+ if (waitForAuthentication) {
1962
+ socket.addEventListener("message", handleSocketMessage);
1963
+ } else {
1964
+ socket.addEventListener("open", handleOpenSuccess);
1965
+ }
1832
1966
  socket.addEventListener("error", handleOpenError);
1967
+ socket.addEventListener("close", handleClose);
1833
1968
  });
1834
1969
  }
1835
1970
  __name(waitForOpenClientSocket, "waitForOpenClientSocket");
@@ -1840,28 +1975,36 @@ async function closeClientSocket(socket, options = {}) {
1840
1975
  return;
1841
1976
  }
1842
1977
  await new Promise((resolve, reject) => {
1843
- function handleCloseError(error) {
1844
- socket.removeEventListener("close", handleCloseSuccess);
1978
+ function removeAllSocketListeners() {
1979
+ socket.removeEventListener("error", handleError);
1980
+ socket.removeEventListener("close", handleClose);
1981
+ }
1982
+ __name(removeAllSocketListeners, "removeAllSocketListeners");
1983
+ function handleError(error) {
1984
+ removeAllSocketListeners();
1845
1985
  reject(error);
1846
1986
  }
1847
- __name(handleCloseError, "handleCloseError");
1987
+ __name(handleError, "handleError");
1848
1988
  const closeTimeout = setTimeout(() => {
1849
1989
  const timeoutError = new WebSocketCloseTimeoutError(timeoutDuration);
1850
- handleCloseError(timeoutError);
1990
+ handleError(timeoutError);
1851
1991
  }, timeoutDuration);
1852
- function handleCloseSuccess() {
1853
- socket.removeEventListener("error", handleCloseError);
1992
+ function handleClose() {
1993
+ removeAllSocketListeners();
1854
1994
  clearTimeout(closeTimeout);
1855
1995
  resolve();
1856
1996
  }
1857
- __name(handleCloseSuccess, "handleCloseSuccess");
1858
- socket.addEventListener("error", handleCloseError);
1859
- socket.addEventListener("close", handleCloseSuccess);
1997
+ __name(handleClose, "handleClose");
1998
+ socket.addEventListener("error", handleError);
1999
+ socket.addEventListener("close", handleClose);
1860
2000
  socket.close();
1861
2001
  });
1862
2002
  }
1863
2003
  __name(closeClientSocket, "closeClientSocket");
1864
2004
 
2005
+ // src/webSocket/constants.ts
2006
+ var WEB_SOCKET_CONTROL_MESSAGES = Object.freeze(["socket:auth:valid"]);
2007
+
1865
2008
  // src/webSocket/errors/InvalidWebSocketMessage.ts
1866
2009
  var InvalidWebSocketMessage = class extends Error {
1867
2010
  static {
@@ -1902,8 +2045,11 @@ var WebSocketHandler = class {
1902
2045
  this.socketTimeout = options.socketTimeout ?? DEFAULT_WEB_SOCKET_LIFECYCLE_TIMEOUT;
1903
2046
  this.messageTimeout = options.messageTimeout ?? DEFAULT_WEB_SOCKET_MESSAGE_TIMEOUT;
1904
2047
  }
1905
- async registerSocket(socket) {
1906
- const openPromise = waitForOpenClientSocket(socket, { timeout: this.socketTimeout });
2048
+ async registerSocket(socket, options = {}) {
2049
+ const openPromise = waitForOpenClientSocket(socket, {
2050
+ timeout: this.socketTimeout,
2051
+ waitForAuthentication: options.waitForAuthentication
2052
+ });
1907
2053
  const handleSocketMessage = /* @__PURE__ */ __name(async (rawMessage) => {
1908
2054
  await this.handleSocketMessage(socket, rawMessage);
1909
2055
  }, "handleSocketMessage");
@@ -1916,8 +2062,8 @@ var WebSocketHandler = class {
1916
2062
  socket.addEventListener("error", handleSocketError);
1917
2063
  const handleSocketClose = /* @__PURE__ */ __name(() => {
1918
2064
  socket.removeEventListener("message", handleSocketMessage);
1919
- socket.removeEventListener("error", handleSocketError);
1920
2065
  socket.removeEventListener("close", handleSocketClose);
2066
+ socket.removeEventListener("error", handleSocketError);
1921
2067
  this.removeSocket(socket);
1922
2068
  }, "handleSocketClose");
1923
2069
  socket.addEventListener("close", handleSocketClose);
@@ -1925,6 +2071,9 @@ var WebSocketHandler = class {
1925
2071
  }
1926
2072
  handleSocketMessage = /* @__PURE__ */ __name(async (socket, rawMessage) => {
1927
2073
  try {
2074
+ if (this.isControlMessageData(rawMessage.data)) {
2075
+ return;
2076
+ }
1928
2077
  const stringifiedMessageData = this.readRawMessageData(rawMessage.data);
1929
2078
  const parsedMessageData = this.parseMessage(stringifiedMessageData);
1930
2079
  await this.notifyListeners(parsedMessageData, socket);
@@ -1932,6 +2081,9 @@ var WebSocketHandler = class {
1932
2081
  console.error(error);
1933
2082
  }
1934
2083
  }, "handleSocketMessage");
2084
+ isControlMessageData(messageData) {
2085
+ return typeof messageData === "string" && WEB_SOCKET_CONTROL_MESSAGES.includes(messageData);
2086
+ }
1935
2087
  readRawMessageData(data) {
1936
2088
  if (typeof data === "string") {
1937
2089
  return data;
@@ -1946,7 +2098,7 @@ var WebSocketHandler = class {
1946
2098
  } catch {
1947
2099
  throw new InvalidWebSocketMessage_default(stringifiedMessage);
1948
2100
  }
1949
- if (!this.isValidMessage(parsedMessage)) {
2101
+ if (!this.isMessage(parsedMessage)) {
1950
2102
  throw new InvalidWebSocketMessage_default(stringifiedMessage);
1951
2103
  }
1952
2104
  if (this.isReplyMessage(parsedMessage)) {
@@ -1963,7 +2115,7 @@ var WebSocketHandler = class {
1963
2115
  data: parsedMessage.data
1964
2116
  };
1965
2117
  }
1966
- isValidMessage(message) {
2118
+ isMessage(message) {
1967
2119
  return typeof message === "object" && message !== null && "id" in message && typeof message.id === "string" && "channel" in message && typeof message.channel === "string" && (!("requestId" in message) || typeof message.requestId === "string");
1968
2120
  }
1969
2121
  async notifyListeners(message, socket) {
@@ -2145,10 +2297,11 @@ var WebSocketClient = class extends WebSocketHandler_default {
2145
2297
  get isRunning() {
2146
2298
  return this.socket !== void 0 && this.socket.readyState === this.socket.OPEN;
2147
2299
  }
2148
- async start() {
2149
- this.socket = new ClientSocket(this.url);
2300
+ async start(options = {}) {
2301
+ const parametersAsString = options.parameters ? Object.entries(options.parameters).map(([key, value]) => `${key}=${value}`).map(encodeURIComponent) : [];
2302
+ this.socket = new ClientSocket(this.url, parametersAsString);
2150
2303
  try {
2151
- await super.registerSocket(this.socket);
2304
+ await super.registerSocket(this.socket, options);
2152
2305
  } catch (error) {
2153
2306
  await this.stop();
2154
2307
  throw error;
@@ -2169,26 +2322,30 @@ var RemoteHttpInterceptorWorker = class extends HttpInterceptorWorker_default {
2169
2322
  static {
2170
2323
  __name(this, "RemoteHttpInterceptorWorker");
2171
2324
  }
2172
- webSocketClient;
2173
2325
  httpHandlers = /* @__PURE__ */ new Map();
2326
+ webSocketClient;
2327
+ auth;
2174
2328
  constructor(options) {
2175
2329
  super();
2176
- const webSocketServerURL = this.deriveWebSocketServerURL(options.serverURL);
2177
2330
  this.webSocketClient = new WebSocketClient_default({
2178
- url: webSocketServerURL.toString()
2331
+ url: this.getWebSocketServerURL(options.serverURL).toString()
2179
2332
  });
2333
+ this.auth = options.auth;
2180
2334
  }
2181
2335
  get type() {
2182
2336
  return "remote";
2183
2337
  }
2184
- deriveWebSocketServerURL(serverURL) {
2338
+ getWebSocketServerURL(serverURL) {
2185
2339
  const webSocketServerURL = new URL(serverURL);
2186
2340
  webSocketServerURL.protocol = serverURL.protocol.replace(/^http(s)?:$/, "ws$1:");
2187
2341
  return webSocketServerURL;
2188
2342
  }
2189
2343
  async start() {
2190
2344
  await super.sharedStart(async () => {
2191
- await this.webSocketClient.start();
2345
+ await this.webSocketClient.start({
2346
+ parameters: this.auth ? { token: this.auth.token } : void 0,
2347
+ waitForAuthentication: true
2348
+ });
2192
2349
  this.webSocketClient.onEvent("interceptors/responses/create", this.createResponse);
2193
2350
  this.webSocketClient.onEvent("interceptors/responses/unhandled", this.handleUnhandledServerRequest);
2194
2351
  this.platform = this.readPlatform();
@@ -2259,7 +2416,7 @@ var RemoteHttpInterceptorWorker = class extends HttpInterceptorWorker_default {
2259
2416
  }
2260
2417
  };
2261
2418
  this.httpHandlers.set(handler.id, handler);
2262
- await this.webSocketClient.request("interceptors/workers/use/commit", {
2419
+ await this.webSocketClient.request("interceptors/workers/commit", {
2263
2420
  id: handler.id,
2264
2421
  url: handler.url,
2265
2422
  method
@@ -2271,7 +2428,7 @@ var RemoteHttpInterceptorWorker = class extends HttpInterceptorWorker_default {
2271
2428
  }
2272
2429
  this.httpHandlers.clear();
2273
2430
  if (this.webSocketClient.isRunning) {
2274
- await this.webSocketClient.request("interceptors/workers/use/reset", void 0);
2431
+ await this.webSocketClient.request("interceptors/workers/reset", void 0);
2275
2432
  }
2276
2433
  }
2277
2434
  async clearInterceptorHandlers(interceptor) {
@@ -2289,7 +2446,7 @@ var RemoteHttpInterceptorWorker = class extends HttpInterceptorWorker_default {
2289
2446
  url: handler.url,
2290
2447
  method: handler.method
2291
2448
  }));
2292
- await this.webSocketClient.request("interceptors/workers/use/reset", groupsToRecommit);
2449
+ await this.webSocketClient.request("interceptors/workers/reset", groupsToRecommit);
2293
2450
  }
2294
2451
  }
2295
2452
  get interceptorsWithHandlers() {
@@ -2322,8 +2479,15 @@ var HttpInterceptorStore = class _HttpInterceptorStore {
2322
2479
  get localWorker() {
2323
2480
  return this.class._localWorker;
2324
2481
  }
2325
- remoteWorker(baseURL) {
2326
- return this.class.remoteWorkers.get(baseURL.origin);
2482
+ getRemoteWorkerKey(baseURL, options) {
2483
+ if (!options.auth) {
2484
+ return baseURL.origin;
2485
+ }
2486
+ return `${baseURL.origin}:${options.auth.token}`;
2487
+ }
2488
+ remoteWorker(baseURL, options) {
2489
+ const remoteWorkerKey = this.getRemoteWorkerKey(baseURL, options);
2490
+ return this.class.remoteWorkers.get(remoteWorkerKey);
2327
2491
  }
2328
2492
  get numberOfRunningLocalInterceptors() {
2329
2493
  return this.class.runningLocalInterceptors.size;
@@ -2361,20 +2525,22 @@ var HttpInterceptorStore = class _HttpInterceptorStore {
2361
2525
  this.class._localWorker = createdWorker;
2362
2526
  return createdWorker;
2363
2527
  }
2528
+ deleteLocalWorker() {
2529
+ this.class._localWorker = void 0;
2530
+ }
2364
2531
  getOrCreateRemoteWorker(workerOptions) {
2365
- const existingWorker = this.class.remoteWorkers.get(workerOptions.serverURL.origin);
2532
+ const remoteWorkerKey = this.getRemoteWorkerKey(workerOptions.serverURL, { auth: workerOptions.auth });
2533
+ const existingWorker = this.class.remoteWorkers.get(remoteWorkerKey);
2366
2534
  if (existingWorker) {
2367
2535
  return existingWorker;
2368
2536
  }
2369
2537
  const createdWorker = createHttpInterceptorWorker({ ...workerOptions, type: "remote" });
2370
- this.class.remoteWorkers.set(workerOptions.serverURL.origin, createdWorker);
2538
+ this.class.remoteWorkers.set(remoteWorkerKey, createdWorker);
2371
2539
  return createdWorker;
2372
2540
  }
2373
- clear() {
2374
- this.class._localWorker = void 0;
2375
- this.class.runningLocalInterceptors.clear();
2376
- this.class.remoteWorkers.clear();
2377
- this.class.runningRemoteInterceptors.clear();
2541
+ deleteRemoteWorker(baseURL, options) {
2542
+ const remoteWorkerKey = this.getRemoteWorkerKey(baseURL, options);
2543
+ this.class.remoteWorkers.delete(remoteWorkerKey);
2378
2544
  }
2379
2545
  };
2380
2546
  var HttpInterceptorStore_default = HttpInterceptorStore;
@@ -2388,11 +2554,15 @@ var LocalHttpInterceptor = class {
2388
2554
  client;
2389
2555
  constructor(options) {
2390
2556
  const baseURL = new URL(options.baseURL);
2391
- const worker = this.store.getOrCreateLocalWorker({});
2392
2557
  this.client = new HttpInterceptorClient_default({
2393
- worker,
2394
2558
  store: this.store,
2395
2559
  baseURL,
2560
+ createWorker: /* @__PURE__ */ __name(() => {
2561
+ return this.store.getOrCreateLocalWorker({});
2562
+ }, "createWorker"),
2563
+ deleteWorker: /* @__PURE__ */ __name(() => {
2564
+ this.store.deleteLocalWorker();
2565
+ }, "deleteWorker"),
2396
2566
  Handler: LocalHttpRequestHandler_default,
2397
2567
  onUnhandledRequest: options.onUnhandledRequest,
2398
2568
  requestSaving: options.requestSaving
@@ -2475,14 +2645,22 @@ var RemoteHttpInterceptor = class {
2475
2645
  }
2476
2646
  store = new HttpInterceptorStore_default();
2477
2647
  client;
2648
+ _auth;
2478
2649
  constructor(options) {
2650
+ this._auth = options.auth;
2479
2651
  const baseURL = new URL(options.baseURL);
2480
- const serverURL = new URL(baseURL.origin);
2481
- const worker = this.store.getOrCreateRemoteWorker({ serverURL });
2482
2652
  this.client = new HttpInterceptorClient_default({
2483
- worker,
2484
2653
  store: this.store,
2485
2654
  baseURL,
2655
+ createWorker: /* @__PURE__ */ __name(() => {
2656
+ return this.store.getOrCreateRemoteWorker({
2657
+ serverURL: new URL(baseURL.origin),
2658
+ auth: this._auth
2659
+ });
2660
+ }, "createWorker"),
2661
+ deleteWorker: /* @__PURE__ */ __name(() => {
2662
+ this.store.deleteRemoteWorker(baseURL, { auth: options.auth });
2663
+ }, "deleteWorker"),
2486
2664
  Handler: RemoteHttpRequestHandler_default,
2487
2665
  onUnhandledRequest: options.onUnhandledRequest,
2488
2666
  requestSaving: options.requestSaving
@@ -2503,6 +2681,27 @@ var RemoteHttpInterceptor = class {
2503
2681
  set requestSaving(requestSaving) {
2504
2682
  this.client.requestSaving = requestSaving;
2505
2683
  }
2684
+ get auth() {
2685
+ return this._auth;
2686
+ }
2687
+ set auth(auth) {
2688
+ const cannotChangeAuthWhileRunningMessage = "Did you forget to call `await interceptor.stop()` before changing the authentication parameters?";
2689
+ if (this.isRunning) {
2690
+ throw new RunningHttpInterceptorError_default(cannotChangeAuthWhileRunningMessage);
2691
+ }
2692
+ if (!auth) {
2693
+ this._auth = void 0;
2694
+ return;
2695
+ }
2696
+ this._auth = new Proxy(auth, {
2697
+ set: /* @__PURE__ */ __name((target, property, value) => {
2698
+ if (this.isRunning) {
2699
+ throw new RunningHttpInterceptorError_default(cannotChangeAuthWhileRunningMessage);
2700
+ }
2701
+ return Reflect.set(target, property, value);
2702
+ }, "set")
2703
+ });
2704
+ }
2506
2705
  get onUnhandledRequest() {
2507
2706
  return this.client.onUnhandledRequest;
2508
2707
  }
@@ -2589,13 +2788,17 @@ function createHttpInterceptor(options) {
2589
2788
  throw new UnknownHttpInterceptorTypeError_default(type);
2590
2789
  }
2591
2790
  __name(createHttpInterceptor, "createHttpInterceptor");
2791
+ /* istanbul ignore next -- @preserve
2792
+ * Ignoring because there will always be a handler for the given method and path at this point. */
2592
2793
  /* istanbul ignore else -- @preserve */
2593
2794
  /* istanbul ignore next -- @preserve
2594
2795
  * Ignoring because checking unknown platforms is not configured in our test setup. */
2595
- /* istanbul ignore next -- @preserve
2596
- * Ignoring because there will always be a handler for the given method and path at this point. */
2597
2796
  /* istanbul ignore next -- @preserve
2598
2797
  * Ignoring as Node.js >=20 provides a global crypto and the import fallback won't run. */
2798
+ /* istanbul ignore else -- @preserve
2799
+ * An unauthorized close event is the only one we expect to happen here. */
2800
+ /* istanbul ignore else -- @preserve
2801
+ * We currently only support the 'socket:auth:valid' message and it is the only possible control message here. */
2599
2802
  /* istanbul ignore next -- @preserve
2600
2803
  * It is difficult to reliably simulate socket errors in tests. */
2601
2804
  /* istanbul ignore else -- @preserve