@zimic/interceptor 1.2.3 → 1.2.4-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 (34) hide show
  1. package/dist/{chunk-XCYZ5L2M.mjs → chunk-EIYQEPK2.mjs} +111 -85
  2. package/dist/chunk-EIYQEPK2.mjs.map +1 -0
  3. package/dist/{chunk-ZU6IGW27.js → chunk-OKZEX5DQ.js} +111 -85
  4. package/dist/chunk-OKZEX5DQ.js.map +1 -0
  5. package/dist/cli.js +18 -18
  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.js +112 -110
  10. package/dist/http.js.map +1 -1
  11. package/dist/http.mjs +112 -110
  12. package/dist/http.mjs.map +1 -1
  13. package/dist/server.js +6 -6
  14. package/dist/server.mjs +1 -1
  15. package/package.json +1 -1
  16. package/src/http/interceptor/HttpInterceptorClient.ts +1 -1
  17. package/src/http/interceptor/HttpInterceptorStore.ts +6 -3
  18. package/src/http/interceptor/RemoteHttpInterceptor.ts +1 -1
  19. package/src/http/interceptor/errors/UnknownHttpInterceptorPlatformError.ts +1 -1
  20. package/src/http/interceptorWorker/HttpInterceptorWorker.ts +3 -5
  21. package/src/http/interceptorWorker/LocalHttpInterceptorWorker.ts +16 -12
  22. package/src/http/interceptorWorker/RemoteHttpInterceptorWorker.ts +20 -43
  23. package/src/server/InterceptorServer.ts +39 -21
  24. package/src/server/types/schema.ts +1 -1
  25. package/src/utils/http.ts +2 -2
  26. package/src/utils/webSocket.ts +3 -3
  27. package/src/webSocket/WebSocketClient.ts +4 -4
  28. package/src/webSocket/WebSocketHandler.ts +119 -69
  29. package/src/webSocket/WebSocketServer.ts +2 -3
  30. package/src/webSocket/errors/InvalidWebSocketMessageError.ts +8 -0
  31. package/src/webSocket/types.ts +9 -14
  32. package/dist/chunk-XCYZ5L2M.mjs.map +0 -1
  33. package/dist/chunk-ZU6IGW27.js.map +0 -1
  34. package/src/webSocket/errors/InvalidWebSocketMessage.ts +0 -8
package/dist/http.mjs CHANGED
@@ -31,7 +31,7 @@ var UnknownHttpInterceptorPlatformError = class extends Error {
31
31
  * Ignoring because checking unknown platforms is currently not possible in our Vitest setup. */
32
32
  constructor() {
33
33
  super("Unknown interceptor platform.");
34
- this.name = "UnknownHttpInterceptorPlatform";
34
+ this.name = "UnknownHttpInterceptorPlatformError";
35
35
  }
36
36
  };
37
37
  var UnknownHttpInterceptorPlatformError_default = UnknownHttpInterceptorPlatformError;
@@ -1637,7 +1637,7 @@ var HttpInterceptorClient = class {
1637
1637
  }
1638
1638
  clear() {
1639
1639
  const clearPromises = [
1640
- Promise.resolve(this.workerOrThrow.clearInterceptorHandlers(this))
1640
+ Promise.resolve(this.workerOrThrow.clearHandlers({ interceptor: this }))
1641
1641
  ];
1642
1642
  for (const method of HTTP_METHODS) {
1643
1643
  for (const result of this.clearMethodHandlers(method)) {
@@ -1851,19 +1851,19 @@ var LocalHttpInterceptorWorker = class extends HttpInterceptorWorker_default {
1851
1851
  return passthrough();
1852
1852
  }
1853
1853
  }
1854
- clearHandlers() {
1855
- this.internalWorkerOrThrow.resetHandlers();
1856
- for (const handlers of Object.values(this.httpHandlersByMethod)) {
1857
- handlers.length = 0;
1858
- }
1859
- }
1860
- clearInterceptorHandlers(interceptor) {
1854
+ clearHandlers(options = {}) {
1861
1855
  if (!this.isRunning) {
1862
1856
  throw new NotRunningHttpInterceptorError_default();
1863
1857
  }
1864
- for (const methodHandlers of Object.values(this.httpHandlersByMethod)) {
1865
- const groupToRemoveIndex = methodHandlers.findIndex((group) => group.interceptor === interceptor);
1866
- removeArrayIndex(methodHandlers, groupToRemoveIndex);
1858
+ if (options.interceptor === void 0) {
1859
+ for (const handlers of Object.values(this.httpHandlersByMethod)) {
1860
+ handlers.length = 0;
1861
+ }
1862
+ } else {
1863
+ for (const methodHandlers of Object.values(this.httpHandlersByMethod)) {
1864
+ const groupToRemoveIndex = methodHandlers.findIndex((group) => group.interceptor === options.interceptor);
1865
+ removeArrayIndex(methodHandlers, groupToRemoveIndex);
1866
+ }
1867
1867
  }
1868
1868
  }
1869
1869
  get interceptorsWithHandlers() {
@@ -1928,13 +1928,13 @@ var WebSocketTimeoutError = class extends Error {
1928
1928
  var WebSocketOpenTimeoutError = class extends WebSocketTimeoutError {
1929
1929
  constructor(reachedTimeout) {
1930
1930
  super(`Web socket open timed out after ${reachedTimeout}ms.`);
1931
- this.name = "WebSocketOpenTimeout";
1931
+ this.name = "WebSocketOpenTimeoutError";
1932
1932
  }
1933
1933
  };
1934
1934
  var WebSocketMessageTimeoutError = class extends WebSocketTimeoutError {
1935
1935
  constructor(reachedTimeout) {
1936
1936
  super(`Web socket message timed out after ${reachedTimeout}ms.`);
1937
- this.name = "WebSocketMessageTimeout";
1937
+ this.name = "WebSocketMessageTimeoutError";
1938
1938
  }
1939
1939
  };
1940
1940
  var WebSocketMessageAbortError = class extends WebSocketTimeoutError {
@@ -1946,7 +1946,7 @@ var WebSocketMessageAbortError = class extends WebSocketTimeoutError {
1946
1946
  var WebSocketCloseTimeoutError = class extends WebSocketTimeoutError {
1947
1947
  constructor(reachedTimeout) {
1948
1948
  super(`Web socket close timed out after ${reachedTimeout}ms.`);
1949
- this.name = "WebSocketCloseTimeout";
1949
+ this.name = "WebSocketCloseTimeoutError";
1950
1950
  }
1951
1951
  };
1952
1952
  var DEFAULT_WEB_SOCKET_LIFECYCLE_TIMEOUT = 60 * 1e3;
@@ -2034,14 +2034,14 @@ async function closeClientSocket(socket, options = {}) {
2034
2034
  // src/webSocket/constants.ts
2035
2035
  var WEB_SOCKET_CONTROL_MESSAGES = Object.freeze(["socket:auth:valid"]);
2036
2036
 
2037
- // src/webSocket/errors/InvalidWebSocketMessage.ts
2038
- var InvalidWebSocketMessage = class extends Error {
2037
+ // src/webSocket/errors/InvalidWebSocketMessageError.ts
2038
+ var InvalidWebSocketMessageError = class extends Error {
2039
2039
  constructor(message) {
2040
2040
  super(`Web socket message is invalid and could not be parsed: ${message}`);
2041
- this.name = "InvalidWebSocketMessage";
2041
+ this.name = "InvalidWebSocketMessageError";
2042
2042
  }
2043
2043
  };
2044
- var InvalidWebSocketMessage_default = InvalidWebSocketMessage;
2044
+ var InvalidWebSocketMessageError_default = InvalidWebSocketMessageError;
2045
2045
 
2046
2046
  // src/webSocket/errors/NotRunningWebSocketHandlerError.ts
2047
2047
  var NotRunningWebSocketHandlerError = class extends Error {
@@ -2059,7 +2059,7 @@ var WebSocketHandler = class {
2059
2059
  messageTimeout;
2060
2060
  channelListeners = {};
2061
2061
  socketListeners = {
2062
- messageAbort: /* @__PURE__ */ new Map()
2062
+ abortRequests: /* @__PURE__ */ new Map()
2063
2063
  };
2064
2064
  constructor(options) {
2065
2065
  this.socketTimeout = options.socketTimeout ?? DEFAULT_WEB_SOCKET_LIFECYCLE_TIMEOUT;
@@ -2080,10 +2080,12 @@ var WebSocketHandler = class {
2080
2080
  }
2081
2081
  socket.addEventListener("error", handleSocketError);
2082
2082
  const handleSocketClose = () => {
2083
+ this.sockets.delete(socket);
2084
+ this.emitSocket("abortRequests", socket);
2085
+ this.socketListeners.abortRequests.delete(socket);
2083
2086
  socket.removeEventListener("message", handleSocketMessage);
2084
2087
  socket.removeEventListener("close", handleSocketClose);
2085
2088
  socket.removeEventListener("error", handleSocketError);
2086
- this.removeSocket(socket);
2087
2089
  };
2088
2090
  socket.addEventListener("close", handleSocketClose);
2089
2091
  this.sockets.add(socket);
@@ -2107,7 +2109,7 @@ var WebSocketHandler = class {
2107
2109
  if (typeof data === "string") {
2108
2110
  return data;
2109
2111
  } else {
2110
- throw new InvalidWebSocketMessage_default(data);
2112
+ throw new InvalidWebSocketMessageError_default(data);
2111
2113
  }
2112
2114
  }
2113
2115
  parseMessage(stringifiedMessage) {
@@ -2115,10 +2117,10 @@ var WebSocketHandler = class {
2115
2117
  try {
2116
2118
  parsedMessage = JSON.parse(stringifiedMessage);
2117
2119
  } catch {
2118
- throw new InvalidWebSocketMessage_default(stringifiedMessage);
2120
+ throw new InvalidWebSocketMessageError_default(stringifiedMessage);
2119
2121
  }
2120
2122
  if (!this.isMessage(parsedMessage)) {
2121
- throw new InvalidWebSocketMessage_default(stringifiedMessage);
2123
+ throw new InvalidWebSocketMessageError_default(stringifiedMessage);
2122
2124
  }
2123
2125
  if (this.isReplyMessage(parsedMessage)) {
2124
2126
  return {
@@ -2137,6 +2139,9 @@ var WebSocketHandler = class {
2137
2139
  isMessage(message) {
2138
2140
  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");
2139
2141
  }
2142
+ isChannelEvent(event, channel) {
2143
+ return event.channel === channel;
2144
+ }
2140
2145
  async notifyListeners(message, socket) {
2141
2146
  if (this.isReplyMessage(message)) {
2142
2147
  await this.notifyReplyListeners(message, socket);
@@ -2165,10 +2170,6 @@ var WebSocketHandler = class {
2165
2170
  });
2166
2171
  await Promise.all(closingPromises);
2167
2172
  }
2168
- removeSocket(socket) {
2169
- this.abortSocketMessages([socket]);
2170
- this.sockets.delete(socket);
2171
- }
2172
2173
  async createEventMessage(channel, eventData) {
2173
2174
  const crypto = await importCrypto();
2174
2175
  const eventMessage = {
@@ -2185,31 +2186,46 @@ var WebSocketHandler = class {
2185
2186
  async request(channel, requestData, options = {}) {
2186
2187
  const request = await this.createEventMessage(channel, requestData);
2187
2188
  this.sendMessage(request, options.sockets);
2188
- const response = await this.waitForReply(channel, request.id, options.sockets);
2189
+ const response = await this.waitForReply(channel, request, options.sockets);
2189
2190
  return response.data;
2190
2191
  }
2191
- async waitForReply(channel, requestId, sockets = this.sockets) {
2192
+ async waitForReply(channel, request, sockets = this.sockets) {
2192
2193
  return new Promise((resolve, reject) => {
2193
2194
  const replyTimeout = setTimeout(() => {
2194
- this.offReply(channel, replyListener);
2195
- this.offAbortSocketMessages(sockets, abortListener);
2195
+ this.offChannel("reply", channel, replyListener);
2196
+ for (const socket of sockets) {
2197
+ this.offSocket("abortRequests", socket, abortRequestsHandler);
2198
+ }
2196
2199
  const timeoutError = new WebSocketMessageTimeoutError(this.messageTimeout);
2197
2200
  reject(timeoutError);
2198
2201
  }, this.messageTimeout);
2199
- const abortListener = this.onAbortSocketMessages(sockets, (error) => {
2202
+ const replyListener = this.onChannel("reply", channel, (message) => {
2203
+ if (message.requestId !== request.id) {
2204
+ return;
2205
+ }
2200
2206
  clearTimeout(replyTimeout);
2201
- this.offReply(channel, replyListener);
2202
- this.offAbortSocketMessages(sockets, abortListener);
2203
- reject(error);
2204
- });
2205
- const replyListener = this.onReply(channel, (message) => {
2206
- if (message.requestId === requestId) {
2207
- clearTimeout(replyTimeout);
2208
- this.offReply(channel, replyListener);
2209
- this.offAbortSocketMessages(sockets, abortListener);
2210
- resolve(message);
2207
+ this.offChannel("reply", channel, replyListener);
2208
+ for (const socket of sockets) {
2209
+ this.offSocket("abortRequests", socket, abortRequestsHandler);
2211
2210
  }
2211
+ resolve(message);
2212
2212
  });
2213
+ const abortRequestsHandler = (options) => {
2214
+ const shouldAbortRequest = options.shouldAbortRequest === void 0 || options.shouldAbortRequest(request);
2215
+ if (!shouldAbortRequest) {
2216
+ return;
2217
+ }
2218
+ clearTimeout(replyTimeout);
2219
+ this.offChannel("reply", channel, replyListener);
2220
+ for (const socket of sockets) {
2221
+ this.offSocket("abortRequests", socket, abortRequestsHandler);
2222
+ }
2223
+ const abortError = new WebSocketMessageAbortError();
2224
+ reject(abortError);
2225
+ };
2226
+ for (const socket of sockets) {
2227
+ this.onSocket("abortRequests", socket, abortRequestsHandler);
2228
+ }
2213
2229
  });
2214
2230
  }
2215
2231
  isReplyMessage(message) {
@@ -2240,9 +2256,9 @@ var WebSocketHandler = class {
2240
2256
  socket.send(stringifiedMessage);
2241
2257
  }
2242
2258
  }
2243
- onEvent(channel, listener) {
2259
+ onChannel(type, channel, listener) {
2244
2260
  const listeners = this.getOrCreateChannelListeners(channel);
2245
- listeners.event.add(listener);
2261
+ listeners[type].add(listener);
2246
2262
  return listener;
2247
2263
  }
2248
2264
  getOrCreateChannelListeners(channel) {
@@ -2255,42 +2271,36 @@ var WebSocketHandler = class {
2255
2271
  }
2256
2272
  return listeners;
2257
2273
  }
2258
- onReply(channel, listener) {
2259
- const listeners = this.getOrCreateChannelListeners(channel);
2260
- listeners.reply.add(listener);
2261
- return listener;
2262
- }
2263
- offEvent(channel, listener) {
2264
- this.channelListeners[channel]?.event.delete(listener);
2265
- }
2266
- offReply(channel, listener) {
2267
- this.channelListeners[channel]?.reply.delete(listener);
2274
+ offChannel(type, channel, listener) {
2275
+ const listeners = this.channelListeners[channel];
2276
+ listeners?.[type].delete(listener);
2268
2277
  }
2269
- removeAllChannelListeners() {
2270
- this.channelListeners = {};
2278
+ onSocket(type, socket, listener) {
2279
+ const listeners = this.getOrCreateSocketListeners(type, socket);
2280
+ listeners.add(listener);
2281
+ return listener;
2271
2282
  }
2272
- onAbortSocketMessages(sockets, listener) {
2273
- for (const socket of sockets) {
2274
- let listeners = this.socketListeners.messageAbort.get(socket);
2275
- if (!listeners) {
2276
- listeners = /* @__PURE__ */ new Set();
2277
- this.socketListeners.messageAbort.set(socket, listeners);
2278
- }
2279
- listeners.add(listener);
2283
+ getOrCreateSocketListeners(type, socket) {
2284
+ const listeners = this.socketListeners[type].get(socket) ?? /* @__PURE__ */ new Set();
2285
+ if (!this.socketListeners[type].has(socket)) {
2286
+ this.socketListeners[type].set(socket, listeners);
2280
2287
  }
2281
- return listener;
2288
+ return listeners;
2282
2289
  }
2283
- offAbortSocketMessages(sockets, listener) {
2284
- for (const socket of sockets) {
2285
- this.socketListeners.messageAbort.get(socket)?.delete(listener);
2290
+ offSocket(type, socket, listener) {
2291
+ const listeners = this.socketListeners[type].get(socket);
2292
+ listeners?.delete(listener);
2293
+ }
2294
+ emitSocket(type, socket, options = {}) {
2295
+ for (const listener of this.socketListeners[type].get(socket) ?? []) {
2296
+ listener(options);
2286
2297
  }
2287
2298
  }
2288
- abortSocketMessages(sockets = this.sockets) {
2289
- const abortError = new WebSocketMessageAbortError();
2290
- for (const socket of sockets) {
2291
- const listeners = this.socketListeners.messageAbort.get(socket) ?? [];
2292
- for (const listener of listeners) {
2293
- listener(abortError);
2299
+ offAny() {
2300
+ this.channelListeners = {};
2301
+ for (const listenersBySocket of Object.values(this.socketListeners)) {
2302
+ for (const listeners of listenersBySocket.values()) {
2303
+ listeners.clear();
2294
2304
  }
2295
2305
  }
2296
2306
  }
@@ -2324,10 +2334,10 @@ var WebSocketClient = class extends WebSocketHandler_default {
2324
2334
  }
2325
2335
  }
2326
2336
  async stop() {
2327
- super.removeAllChannelListeners();
2328
- const sockets = this.socket ? [this.socket] : [];
2329
- super.abortSocketMessages(sockets);
2330
- await super.closeClientSockets(sockets);
2337
+ super.offAny();
2338
+ if (this.socket) {
2339
+ await super.closeClientSockets([this.socket]);
2340
+ }
2331
2341
  this.socket = void 0;
2332
2342
  }
2333
2343
  };
@@ -2355,12 +2365,12 @@ var RemoteHttpInterceptorWorker = class extends HttpInterceptorWorker_default {
2355
2365
  }
2356
2366
  async start() {
2357
2367
  await super.sharedStart(async () => {
2368
+ this.webSocketClient.onChannel("event", "interceptors/responses/create", this.createResponse);
2369
+ this.webSocketClient.onChannel("event", "interceptors/responses/unhandled", this.handleUnhandledServerRequest);
2358
2370
  await this.webSocketClient.start({
2359
2371
  parameters: this.auth ? { token: this.auth.token } : void 0,
2360
2372
  waitForAuthentication: true
2361
2373
  });
2362
- this.webSocketClient.onEvent("interceptors/responses/create", this.createResponse);
2363
- this.webSocketClient.onEvent("interceptors/responses/unhandled", this.handleUnhandledServerRequest);
2364
2374
  this.platform = this.readPlatform();
2365
2375
  this.isRunning = true;
2366
2376
  });
@@ -2400,9 +2410,9 @@ var RemoteHttpInterceptorWorker = class extends HttpInterceptorWorker_default {
2400
2410
  }
2401
2411
  async stop() {
2402
2412
  await super.sharedStop(async () => {
2413
+ this.webSocketClient.offChannel("event", "interceptors/responses/create", this.createResponse);
2414
+ this.webSocketClient.offChannel("event", "interceptors/responses/unhandled", this.handleUnhandledServerRequest);
2403
2415
  await this.clearHandlers();
2404
- this.webSocketClient.offEvent("interceptors/responses/create", this.createResponse);
2405
- this.webSocketClient.offEvent("interceptors/responses/unhandled", this.handleUnhandledServerRequest);
2406
2416
  await this.webSocketClient.stop();
2407
2417
  this.isRunning = false;
2408
2418
  });
@@ -2432,43 +2442,30 @@ var RemoteHttpInterceptorWorker = class extends HttpInterceptorWorker_default {
2432
2442
  path: handler.path
2433
2443
  });
2434
2444
  }
2435
- async clearHandlers() {
2436
- if (!this.isRunning) {
2437
- throw new NotRunningHttpInterceptorError_default();
2438
- }
2439
- this.httpHandlers.clear();
2440
- if (!this.webSocketClient.isRunning) {
2441
- return;
2442
- }
2443
- try {
2444
- await this.webSocketClient.request("interceptors/workers/reset", void 0);
2445
- } catch (error) {
2446
- const isMessageAbortError = error instanceof WebSocketMessageAbortError;
2447
- if (!isMessageAbortError) {
2448
- throw error;
2449
- }
2450
- }
2451
- }
2452
- async clearInterceptorHandlers(interceptor) {
2445
+ async clearHandlers(options = {}) {
2453
2446
  if (!this.isRunning) {
2454
2447
  throw new NotRunningHttpInterceptorError_default();
2455
2448
  }
2456
- for (const handler of this.httpHandlers.values()) {
2457
- if (handler.interceptor === interceptor) {
2458
- this.httpHandlers.delete(handler.id);
2449
+ if (options.interceptor === void 0) {
2450
+ this.httpHandlers.clear();
2451
+ } else {
2452
+ for (const handler of this.httpHandlers.values()) {
2453
+ if (handler.interceptor === options.interceptor) {
2454
+ this.httpHandlers.delete(handler.id);
2455
+ }
2459
2456
  }
2460
2457
  }
2461
2458
  if (!this.webSocketClient.isRunning) {
2462
2459
  return;
2463
2460
  }
2464
- const groupsToRecommit = Array.from(this.httpHandlers.values(), (handler) => ({
2461
+ const handlersToRecommit = Array.from(this.httpHandlers.values(), (handler) => ({
2465
2462
  id: handler.id,
2466
2463
  baseURL: handler.baseURL,
2467
2464
  method: handler.method,
2468
2465
  path: handler.path
2469
2466
  }));
2470
2467
  try {
2471
- await this.webSocketClient.request("interceptors/workers/reset", groupsToRecommit);
2468
+ await this.webSocketClient.request("interceptors/workers/reset", handlersToRecommit);
2472
2469
  } catch (error) {
2473
2470
  const isMessageAbortError = error instanceof WebSocketMessageAbortError;
2474
2471
  if (!isMessageAbortError) {
@@ -2503,10 +2500,11 @@ var HttpInterceptorStore = class _HttpInterceptorStore {
2503
2500
  return this.class._localWorker;
2504
2501
  }
2505
2502
  getRemoteWorkerKey(baseURL, options) {
2506
- if (!options.auth) {
2507
- return baseURL.origin;
2503
+ const key = [`${baseURL.origin}${baseURL.pathname}`];
2504
+ if (options.auth) {
2505
+ key.push(options.auth.token);
2508
2506
  }
2509
- return `${baseURL.origin}:${options.auth.token}`;
2507
+ return key.join(":");
2510
2508
  }
2511
2509
  remoteWorker(baseURL, options) {
2512
2510
  const remoteWorkerKey = this.getRemoteWorkerKey(baseURL, options);
@@ -2671,7 +2669,7 @@ var RemoteHttpInterceptor = class {
2671
2669
  baseURL,
2672
2670
  createWorker: () => {
2673
2671
  return this.store.getOrCreateRemoteWorker({
2674
- serverURL: new URL(baseURL.origin),
2672
+ serverURL: baseURL,
2675
2673
  auth: this._auth
2676
2674
  });
2677
2675
  },
@@ -2805,6 +2803,8 @@ var InvalidJSONError = class extends InvalidJSONError$1 {
2805
2803
  };
2806
2804
  /* istanbul ignore next -- @preserve
2807
2805
  * Ignoring because there will always be a handler for the given method and path at this point. */
2806
+ /* istanbul ignore if -- @preserve
2807
+ * Trying to access the internal worker when it does not exist should not happen. */
2808
2808
  /* istanbul ignore else -- @preserve */
2809
2809
  /* istanbul ignore next -- @preserve
2810
2810
  * Ignoring because checking unknown platforms is not configured in our test setup. */
@@ -2821,6 +2821,8 @@ var InvalidJSONError = class extends InvalidJSONError$1 {
2821
2821
  /* istanbul ignore next -- @preserve
2822
2822
  * Reply listeners are always present when notified in normal conditions. If they were not present, the request
2823
2823
  * would reach a timeout and not be responded. The empty set serves as a fallback. */
2824
+ /* istanbul ignore if -- @preserve
2825
+ * Aborting requests is highly non-deterministic because it depends on specific timing of socket events. */
2824
2826
  /* istanbul ignore next -- @preserve
2825
2827
  *
2826
2828
  * If the socket is closed before receiving a response, the message is aborted with an error. This can happen if