@zimic/interceptor 1.1.2 → 1.1.3-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.
package/dist/server.js CHANGED
@@ -1,29 +1,29 @@
1
1
  'use strict';
2
2
 
3
- var chunkRQ2YYT5B_js = require('./chunk-RQ2YYT5B.js');
3
+ var chunkNWA64QXK_js = require('./chunk-NWA64QXK.js');
4
4
  require('./chunk-DGUM43GV.js');
5
5
 
6
6
 
7
7
 
8
8
  Object.defineProperty(exports, "DEFAULT_ACCESS_CONTROL_HEADERS", {
9
9
  enumerable: true,
10
- get: function () { return chunkRQ2YYT5B_js.DEFAULT_ACCESS_CONTROL_HEADERS; }
10
+ get: function () { return chunkNWA64QXK_js.DEFAULT_ACCESS_CONTROL_HEADERS; }
11
11
  });
12
12
  Object.defineProperty(exports, "DEFAULT_PREFLIGHT_STATUS_CODE", {
13
13
  enumerable: true,
14
- get: function () { return chunkRQ2YYT5B_js.DEFAULT_PREFLIGHT_STATUS_CODE; }
14
+ get: function () { return chunkNWA64QXK_js.DEFAULT_PREFLIGHT_STATUS_CODE; }
15
15
  });
16
16
  Object.defineProperty(exports, "NotRunningInterceptorServerError", {
17
17
  enumerable: true,
18
- get: function () { return chunkRQ2YYT5B_js.NotRunningInterceptorServerError_default; }
18
+ get: function () { return chunkNWA64QXK_js.NotRunningInterceptorServerError_default; }
19
19
  });
20
20
  Object.defineProperty(exports, "RunningInterceptorServerError", {
21
21
  enumerable: true,
22
- get: function () { return chunkRQ2YYT5B_js.RunningInterceptorServerError_default; }
22
+ get: function () { return chunkNWA64QXK_js.RunningInterceptorServerError_default; }
23
23
  });
24
24
  Object.defineProperty(exports, "createInterceptorServer", {
25
25
  enumerable: true,
26
- get: function () { return chunkRQ2YYT5B_js.createInterceptorServer; }
26
+ get: function () { return chunkNWA64QXK_js.createInterceptorServer; }
27
27
  });
28
28
  //# sourceMappingURL=server.js.map
29
29
  //# sourceMappingURL=server.js.map
package/dist/server.mjs CHANGED
@@ -1,4 +1,4 @@
1
- export { DEFAULT_ACCESS_CONTROL_HEADERS, DEFAULT_PREFLIGHT_STATUS_CODE, NotRunningInterceptorServerError_default as NotRunningInterceptorServerError, RunningInterceptorServerError_default as RunningInterceptorServerError, createInterceptorServer } from './chunk-AMKVGJZN.mjs';
1
+ export { DEFAULT_ACCESS_CONTROL_HEADERS, DEFAULT_PREFLIGHT_STATUS_CODE, NotRunningInterceptorServerError_default as NotRunningInterceptorServerError, RunningInterceptorServerError_default as RunningInterceptorServerError, createInterceptorServer } from './chunk-5JHZWURB.mjs';
2
2
  import './chunk-BJTO5JO5.mjs';
3
3
  //# sourceMappingURL=server.mjs.map
4
4
  //# sourceMappingURL=server.mjs.map
package/package.json CHANGED
@@ -14,7 +14,7 @@
14
14
  "api",
15
15
  "static"
16
16
  ],
17
- "version": "1.1.2",
17
+ "version": "1.1.3-canary.1",
18
18
  "homepage": "https://zimic.dev/docs/interceptor",
19
19
  "repository": {
20
20
  "type": "git",
@@ -105,13 +105,13 @@
105
105
  "typescript": "^5.9.2",
106
106
  "vitest": "^3.2.4",
107
107
  "@zimic/eslint-config-node": "0.0.0",
108
- "@zimic/lint-staged-config": "0.0.0",
109
108
  "@zimic/tsconfig": "0.0.0",
110
- "@zimic/utils": "0.0.0"
109
+ "@zimic/utils": "0.0.0",
110
+ "@zimic/lint-staged-config": "0.0.0"
111
111
  },
112
112
  "peerDependencies": {
113
113
  "typescript": ">=5.0.0",
114
- "@zimic/http": "^1.1.0 || 1.1.2"
114
+ "@zimic/http": "^1.1.0 || 1.2.0-canary.0"
115
115
  },
116
116
  "peerDependenciesMeta": {
117
117
  "typescript": {
package/src/http/index.ts CHANGED
@@ -1,11 +1,14 @@
1
+ import {
2
+ InvalidFormDataError as HttpInvalidFormDataError,
3
+ InvalidJSONError as HttpInvalidJSONError,
4
+ } from '@zimic/http';
5
+
1
6
  export { default as RunningHttpInterceptorError } from './interceptor/errors/RunningHttpInterceptorError';
2
7
  export { default as NotRunningHttpInterceptorError } from './interceptor/errors/NotRunningHttpInterceptorError';
3
8
  export { default as UnknownHttpInterceptorPlatformError } from './interceptor/errors/UnknownHttpInterceptorPlatformError';
4
9
  export { default as UnknownHttpInterceptorTypeError } from './interceptor/errors/UnknownHttpInterceptorTypeError';
5
10
  export { default as RequestSavingSafeLimitExceededError } from './interceptor/errors/RequestSavingSafeLimitExceededError';
6
11
 
7
- export { default as InvalidFormDataError } from './interceptorWorker/errors/InvalidFormDataError';
8
- export { default as InvalidJSONError } from './interceptorWorker/errors/InvalidJSONError';
9
12
  export { default as UnregisteredBrowserServiceWorkerError } from './interceptorWorker/errors/UnregisteredBrowserServiceWorkerError';
10
13
 
11
14
  export { default as DisabledRequestSavingError } from './requestHandler/errors/DisabledRequestSavingError';
@@ -51,3 +54,31 @@ export type { InferHttpInterceptorSchema } from './interceptor/types/schema';
51
54
  export type { LocalHttpInterceptor, RemoteHttpInterceptor, HttpInterceptor } from './interceptor/types/public';
52
55
 
53
56
  export { createHttpInterceptor } from './interceptor/factory';
57
+
58
+ /**
59
+ * Error thrown when a value is not valid {@link https://developer.mozilla.org/docs/Web/API/FormData FormData}. HTTP
60
+ * interceptors might throw this error when trying to parse the body of a request or response with the header
61
+ * `'content-type': 'multipart/form-data'`, if the content cannot be parsed to form data.
62
+ *
63
+ * @deprecated This type has been moved to {@link https://zimic.dev/docs/http `@zimic/http`}. Please import
64
+ * `InvalidFormDataError` from `@zimic/http` instead.
65
+ *
66
+ * ```ts
67
+ * import { InvalidFormDataError } from '@zimic/http';
68
+ * ```
69
+ */
70
+ export class InvalidFormDataError extends HttpInvalidFormDataError {}
71
+
72
+ /**
73
+ * Error thrown when a value is not valid JSON. HTTP interceptors might throw this error when trying to parse the body
74
+ * of a request or response with the header `'content-type': 'application/json'`, if the content cannot be parsed to
75
+ * JSON.
76
+ *
77
+ * @deprecated This type has been moved to {@link https://zimic.dev/docs/http `@zimic/http`}. Please import
78
+ * `InvalidJSONError` from `@zimic/http` instead.
79
+ *
80
+ * ```ts
81
+ * import { InvalidJSONError } from '@zimic/http';
82
+ * ```
83
+ */
84
+ export class InvalidJSONError extends HttpInvalidJSONError {}
@@ -9,7 +9,7 @@ import {
9
9
  } from '@zimic/http';
10
10
  import { Default, PossiblePromise } from '@zimic/utils/types';
11
11
  import createRegexFromPath from '@zimic/utils/url/createRegexFromPath';
12
- import excludeURLParams from '@zimic/utils/url/excludeURLParams';
12
+ import excludeNonPathParams from '@zimic/utils/url/excludeNonPathParams';
13
13
  import validateURLProtocol from '@zimic/utils/url/validateURLProtocol';
14
14
 
15
15
  import { isServerSide } from '@/utils/environment';
@@ -109,7 +109,7 @@ class HttpInterceptorClient<
109
109
  }
110
110
 
111
111
  validateURLProtocol(newBaseURL, SUPPORTED_BASE_URL_PROTOCOLS);
112
- excludeURLParams(newBaseURL);
112
+ excludeNonPathParams(newBaseURL);
113
113
 
114
114
  this._baseURL = newBaseURL;
115
115
  }
@@ -8,7 +8,7 @@ import {
8
8
  HttpSchema,
9
9
  HttpStatusCode,
10
10
  InferPathParams,
11
- HttpFormData,
11
+ parseHttpBody,
12
12
  HttpSearchParams,
13
13
  } from '@zimic/http';
14
14
  import isDefined from '@zimic/utils/data/isDefined';
@@ -33,8 +33,6 @@ import {
33
33
  HttpInterceptorResponse,
34
34
  } from '../requestHandler/types/requests';
35
35
  import { DEFAULT_UNHANDLED_REQUEST_STRATEGY } from './constants';
36
- import InvalidFormDataError from './errors/InvalidFormDataError';
37
- import InvalidJSONError from './errors/InvalidJSONError';
38
36
  import { MSWHttpResponseFactory } from './types/msw';
39
37
  import { HttpInterceptorWorkerType } from './types/options';
40
38
 
@@ -208,6 +206,7 @@ abstract class HttpInterceptorWorker {
208
206
 
209
207
  if (
210
208
  typeof declaration.body === 'string' ||
209
+ declaration.body === null ||
211
210
  declaration.body === undefined ||
212
211
  declaration.body instanceof FormData ||
213
212
  declaration.body instanceof URLSearchParams ||
@@ -235,7 +234,11 @@ abstract class HttpInterceptorWorker {
235
234
  const rawRequestClone = rawRequest.clone();
236
235
 
237
236
  type BodySchema = Default<Default<MethodSchema['request']>['body']>;
238
- const parsedBody = await this.parseRawBody<BodySchema>(rawRequest);
237
+
238
+ const parsedBody = await parseHttpBody<BodySchema>(rawRequest).catch((error: unknown) => {
239
+ logger.error('Failed to parse request body:', error);
240
+ return null;
241
+ });
239
242
 
240
243
  type HeadersSchema = Default<Default<MethodSchema['request']>['headers']>;
241
244
  const headers = new HttpHeaders<HeadersSchema>(rawRequest.headers);
@@ -311,7 +314,10 @@ abstract class HttpInterceptorWorker {
311
314
  const rawResponseClone = rawResponse.clone();
312
315
 
313
316
  type BodySchema = Default<Default<Default<MethodSchema['response']>[StatusCode]>['body']>;
314
- const parsedBody = await this.parseRawBody<BodySchema>(rawResponse);
317
+ const parsedBody = await parseHttpBody<BodySchema>(rawResponse).catch((error: unknown) => {
318
+ logger.error('Failed to parse response body:', error);
319
+ return null;
320
+ });
315
321
 
316
322
  type HeadersSchema = Default<Default<Default<MethodSchema['response']>[StatusCode]>['headers']>;
317
323
  const headers = new HttpHeaders<HeadersSchema>(rawResponse.headers);
@@ -376,107 +382,6 @@ abstract class HttpInterceptorWorker {
376
382
  return params as InferPathParams<Path>;
377
383
  }
378
384
 
379
- static async parseRawBody<Body extends HttpBody>(resource: Request | Response) {
380
- const contentType = resource.headers.get('content-type');
381
-
382
- try {
383
- if (contentType) {
384
- if (contentType.startsWith('application/json')) {
385
- return await this.parseRawBodyAsJSON<Body>(resource);
386
- }
387
- if (contentType.startsWith('multipart/form-data')) {
388
- return await this.parseRawBodyAsFormData<Body>(resource);
389
- }
390
- if (contentType.startsWith('application/x-www-form-urlencoded')) {
391
- return await this.parseRawBodyAsSearchParams<Body>(resource);
392
- }
393
- if (contentType.startsWith('text/') || contentType.startsWith('application/xml')) {
394
- return await this.parseRawBodyAsText<Body>(resource);
395
- }
396
- if (
397
- contentType.startsWith('application/') ||
398
- contentType.startsWith('image/') ||
399
- contentType.startsWith('audio/') ||
400
- contentType.startsWith('font/') ||
401
- contentType.startsWith('video/') ||
402
- contentType.startsWith('multipart/')
403
- ) {
404
- return await this.parseRawBodyAsBlob<Body>(resource);
405
- }
406
- }
407
-
408
- const resourceClone = resource.clone();
409
-
410
- try {
411
- return await this.parseRawBodyAsJSON<Body>(resource);
412
- } catch {
413
- return await this.parseRawBodyAsBlob<Body>(resourceClone);
414
- }
415
- } catch (error) {
416
- console.error(error);
417
- return null;
418
- }
419
- }
420
-
421
- private static async parseRawBodyAsJSON<Body extends HttpBody>(resource: Request | Response) {
422
- const bodyAsText = await resource.text();
423
-
424
- if (!bodyAsText.trim()) {
425
- return null;
426
- }
427
-
428
- try {
429
- const bodyAsJSON = JSON.parse(bodyAsText) as Body;
430
- return bodyAsJSON;
431
- } catch {
432
- throw new InvalidJSONError(bodyAsText);
433
- }
434
- }
435
-
436
- private static async parseRawBodyAsSearchParams<Body extends HttpBody>(resource: Request | Response) {
437
- const bodyAsText = await resource.text();
438
-
439
- if (!bodyAsText.trim()) {
440
- return null;
441
- }
442
-
443
- const bodyAsSearchParams = new HttpSearchParams(bodyAsText);
444
- return bodyAsSearchParams as Body;
445
- }
446
-
447
- private static async parseRawBodyAsFormData<Body extends HttpBody>(resource: Request | Response) {
448
- const resourceClone = resource.clone();
449
-
450
- try {
451
- const bodyAsRawFormData = await resource.formData();
452
-
453
- const bodyAsFormData = new HttpFormData();
454
- for (const [key, value] of bodyAsRawFormData) {
455
- bodyAsFormData.append(key, value as string);
456
- }
457
-
458
- return bodyAsFormData as Body;
459
- } catch {
460
- const bodyAsText = await resourceClone.text();
461
-
462
- if (!bodyAsText.trim()) {
463
- return null;
464
- }
465
-
466
- throw new InvalidFormDataError(bodyAsText);
467
- }
468
- }
469
-
470
- private static async parseRawBodyAsBlob<Body extends HttpBody>(resource: Request | Response) {
471
- const bodyAsBlob = await resource.blob();
472
- return bodyAsBlob as Body;
473
- }
474
-
475
- private static async parseRawBodyAsText<Body extends HttpBody>(resource: Request | Response) {
476
- const bodyAsText = await resource.text();
477
- return (bodyAsText || null) as Body;
478
- }
479
-
480
385
  static async logUnhandledRequestWarning(rawRequest: Request, action: UnhandledRequestStrategy.Action) {
481
386
  const request = await this.parseRawRequest(rawRequest);
482
387
 
@@ -1,6 +1,6 @@
1
1
  import { HttpRequest, HttpResponse, HttpMethod, HttpSchema } from '@zimic/http';
2
2
  import createRegexFromPath from '@zimic/utils/url/createRegexFromPath';
3
- import excludeURLParams from '@zimic/utils/url/excludeURLParams';
3
+ import excludeNonPathParams from '@zimic/utils/url/excludeNonPathParams';
4
4
  import validatePathParams from '@zimic/utils/url/validatePathParams';
5
5
  import { SharedOptions as MSWWorkerSharedOptions, http, passthrough } from 'msw';
6
6
  import * as mswBrowser from 'msw/browser';
@@ -210,7 +210,7 @@ class LocalHttpInterceptorWorker extends HttpInterceptorWorker {
210
210
  private async createResponseForRequest(request: HttpRequest) {
211
211
  const methodHandlers = this.httpHandlersByMethod[request.method as HttpMethod];
212
212
 
213
- const requestURL = excludeURLParams(new URL(request.url));
213
+ const requestURL = excludeNonPathParams(new URL(request.url));
214
214
  const requestURLAsString = requestURL.href === `${requestURL.origin}/` ? requestURL.origin : requestURL.href;
215
215
 
216
216
  for (let handlerIndex = methodHandlers.length - 1; handlerIndex >= 0; handlerIndex--) {
@@ -1,7 +1,7 @@
1
1
  import { normalizeNodeRequest, sendNodeResponse } from '@whatwg-node/server';
2
2
  import { HttpRequest, HttpMethod } from '@zimic/http';
3
3
  import createRegexFromPath from '@zimic/utils/url/createRegexFromPath';
4
- import excludeURLParams from '@zimic/utils/url/excludeURLParams';
4
+ import excludeNonPathParams from '@zimic/utils/url/excludeNonPathParams';
5
5
  import { createServer, Server as HttpServer, IncomingMessage, ServerResponse } from 'http';
6
6
  import type { WebSocket as Socket } from 'isomorphic-ws';
7
7
 
@@ -314,7 +314,7 @@ class InterceptorServer implements PublicInterceptorServer {
314
314
  private async createResponseForRequest(request: SerializedHttpRequest) {
315
315
  const methodHandlers = this.httpHandlersByMethod[request.method as HttpMethod];
316
316
 
317
- const requestURL = excludeURLParams(new URL(request.url));
317
+ const requestURL = excludeNonPathParams(new URL(request.url));
318
318
  const requestURLAsString = requestURL.href === `${requestURL.origin}/` ? requestURL.origin : requestURL.href;
319
319
 
320
320
  let matchedSomeInterceptor = false;