@zimic/fetch 1.0.7-canary.2 → 1.1.0-canary.0

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/README.md CHANGED
@@ -36,7 +36,7 @@
36
36
 
37
37
  ---
38
38
 
39
- `@zimic/fetch` is a minimal (~2 kB minified and gzipped) and type-safe `fetch`-like API client.
39
+ `@zimic/fetch` is a minimal (~2 kB minified gzipped) and type-safe `fetch`-like API client.
40
40
 
41
41
  ## Highlights
42
42
 
package/dist/index.d.ts CHANGED
@@ -98,17 +98,19 @@ declare namespace FetchRequest {
98
98
  /**
99
99
  * A plain object representation of a {@link FetchRequest `FetchRequest`}, compatible with JSON.
100
100
  *
101
- * If the body is included in the object, it is represented as a string or null if empty.
101
+ * If the body is included in the object, it is automatically parsed based on the `content-type` header of the request.
102
+ *
103
+ * @see {@link https://zimic.dev/docs/fetch/api/fetch-response-error#errortoobject `error.toObject()`}
102
104
  */
103
105
  type FetchRequestObject = Pick<FetchRequest.Loose, 'url' | 'path' | 'method' | 'cache' | 'destination' | 'credentials' | 'integrity' | 'keepalive' | 'mode' | 'redirect' | 'referrer' | 'referrerPolicy'> & {
104
106
  /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Response/headers) */
105
107
  headers: HttpHeadersSerialized<HttpHeadersSchema>;
106
108
  /**
107
- * The body of the response, represented as a string or null if empty.
109
+ * The body of the request. It is automatically parsed based on the `content-type` header of the request.
108
110
  *
109
- * [MDN Reference](https://developer.mozilla.org/docs/Web/API/Request/body)
111
+ * @see {@link https://zimic.dev/docs/fetch/api/fetch-response-error#errortoobject `error.toObject()`}
110
112
  */
111
- body?: string | null;
113
+ body?: HttpBody | null;
112
114
  };
113
115
  /** @see {@link https://zimic.dev/docs/fetch/api/fetch-response `FetchResponse` API reference} */
114
116
  interface FetchResponsePerStatusCode<Schema extends HttpSchema, Method extends HttpSchemaMethod<Schema>, Path extends HttpSchemaPath.Literal<Schema, Method>, StatusCode extends HttpStatusCode = HttpStatusCode> extends HttpResponse<HttpResponseBodySchema<Default<Schema[Path][Method]>, StatusCode>, Default<HttpResponseHeadersSchema<Default<Schema[Path][Method]>, StatusCode>>, StatusCode> {
@@ -143,17 +145,19 @@ declare namespace FetchResponse {
143
145
  /**
144
146
  * A plain object representation of a {@link FetchResponse `FetchResponse`}, compatible with JSON.
145
147
  *
146
- * If the body is included in the object, it is represented as a string or null if empty.
148
+ * If the body is included in the object, it is automatically parsed based on the `content-type` header of the response.
149
+ *
150
+ * @see {@link https://zimic.dev/docs/fetch/api/fetch-response-error#errortoobject `error.toObject()`}
147
151
  */
148
152
  type FetchResponseObject = Pick<FetchResponse.Loose, 'url' | 'type' | 'status' | 'statusText' | 'ok' | 'redirected'> & {
149
153
  /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Response/headers) */
150
154
  headers: HttpHeadersSerialized<HttpHeadersSchema>;
151
155
  /**
152
- * The body of the response, represented as a string or null if empty.
156
+ * The body of the response. It is automatically parsed based on the `content-type` header of the response.
153
157
  *
154
- * [MDN Reference](https://developer.mozilla.org/docs/Web/API/Request/body)
158
+ * @see {@link https://zimic.dev/docs/fetch/api/fetch-response-error#errortoobject `error.toObject()`}
155
159
  */
156
- body?: string | null;
160
+ body?: HttpBody | null;
157
161
  };
158
162
  /** @see {@link https://zimic.dev/docs/fetch/api/fetch#fetchrequest `fetch.Request` API reference} */
159
163
  type FetchRequestConstructor<Schema extends HttpSchema> = new <Method extends HttpSchemaMethod<Schema>, Path extends HttpSchemaPath.NonLiteral<Schema, Method>>(input: FetchInput<Schema, Method, Path>, init: FetchRequestInit<Schema, Method, LiteralHttpSchemaPathFromNonLiteral<Schema, Method, Path>>) => FetchRequest<Schema, Method, LiteralHttpSchemaPathFromNonLiteral<Schema, Method, Path>>;
package/dist/index.js CHANGED
@@ -75,14 +75,18 @@ var FetchResponseError = class extends Error {
75
75
  const resource = this[resourceType];
76
76
  if (resource.bodyUsed) {
77
77
  console.warn(
78
- `[@zimic/fetch] Could not include the ${resourceType} body because it is already used. If you access the body before calling \`error.toObject()\`, consider reading it from a cloned ${resourceType}.
78
+ "[@zimic/fetch]",
79
+ `Could not include the ${resourceType} body because it is already used. If you access the body before calling \`error.toObject()\`, consider reading it from a cloned ${resourceType}.
79
80
 
80
81
  Learn more: https://zimic.dev/docs/fetch/api/fetch-response-error#errortoobject`
81
82
  );
82
83
  return resourceObject;
83
84
  }
84
- return resource.text().then((body) => {
85
- resourceObject.body = body.length > 0 ? body : null;
85
+ return http.parseHttpBody(resource).then((body) => {
86
+ resourceObject.body = body;
87
+ return resourceObject;
88
+ }).catch((error) => {
89
+ console.error("[@zimic/fetch]", `Failed to parse ${resourceType} body:`, error);
86
90
  return resourceObject;
87
91
  });
88
92
  }
@@ -161,15 +165,15 @@ function createRegexFromPath(path) {
161
165
  }
162
166
  var createRegexFromPath_default = createRegexFromPath;
163
167
 
164
- // ../zimic-utils/dist/url/excludeURLParams.mjs
165
- function excludeURLParams(url) {
168
+ // ../zimic-utils/dist/url/excludeNonPathParams.mjs
169
+ function excludeNonPathParams(url) {
166
170
  url.hash = "";
167
171
  url.search = "";
168
172
  url.username = "";
169
173
  url.password = "";
170
174
  return url;
171
175
  }
172
- var excludeURLParams_default = excludeURLParams;
176
+ var excludeNonPathParams_default = excludeNonPathParams;
173
177
 
174
178
  // ../zimic-utils/dist/url/joinURL.mjs
175
179
  function joinURL(...parts) {
@@ -302,7 +306,7 @@ var FetchClient = class {
302
306
  super(url, initWithDefaults);
303
307
  }
304
308
  const baseURLWithoutTrailingSlash = baseURL.toString().replace(/\/$/, "");
305
- this.path = excludeURLParams_default(url).toString().replace(baseURLWithoutTrailingSlash, "");
309
+ this.path = excludeNonPathParams_default(url).toString().replace(baseURLWithoutTrailingSlash, "");
306
310
  }
307
311
  clone() {
308
312
  const rawClone = super.clone();
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/client/errors/FetchResponseError.ts","../../zimic-utils/src/url/createRegexFromPath.ts","../../zimic-utils/src/url/excludeURLParams.ts","../../zimic-utils/src/url/joinURL.ts","../src/client/FetchClient.ts","../src/client/factory.ts"],"names":["HttpHeaders","Request","HttpSearchParams"],"mappings":"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","file":"index.js","sourcesContent":["import { HttpHeaders, HttpHeadersSchema, HttpSchema, HttpSchemaMethod, HttpSchemaPath } from '@zimic/http';\nimport { PossiblePromise } from '@zimic/utils/types';\n\nimport { FetchRequest, FetchRequestObject, FetchResponse, FetchResponseObject } from '../types/requests';\n\n/** @see {@link https://zimic.dev/docs/fetch/api/fetch-response-error#errortoobject `fetchResponseError.toObject()` API reference} */\nexport interface FetchResponseErrorObjectOptions {\n /** @see {@link https://zimic.dev/docs/fetch/api/fetch-response-error#errortoobject `fetchResponseError.toObject()` API reference} */\n includeRequestBody?: boolean;\n /** @see {@link https://zimic.dev/docs/fetch/api/fetch-response-error#errortoobject `fetchResponseError.toObject()` API reference} */\n includeResponseBody?: boolean;\n}\n\nexport namespace FetchResponseErrorObjectOptions {\n /**\n * Options for converting a {@link FetchResponseError `FetchResponseError`} into a plain object, including the body of\n * the request and/or response.\n */\n export type WithBody = FetchResponseErrorObjectOptions &\n ({ includeRequestBody: true } | { includeResponseBody: true });\n\n /**\n * Options for converting a {@link FetchResponseError `FetchResponseError`} into a plain object, excluding the body of\n * the request and/or response.\n */\n export type WithoutBody = FetchResponseErrorObjectOptions &\n ({ includeRequestBody?: false } | { includeResponseBody?: false });\n}\n\n/**\n * A plain object representation of a {@link FetchResponseError `FetchResponseError`}, compatible with JSON. It is useful\n * for serialization, debugging, and logging purposes.\n *\n * @see {@link https://zimic.dev/docs/fetch/api/fetch-response-error#errortoobject `fetchResponseError.toObject()` API reference}\n */\nexport interface FetchResponseErrorObject {\n name: string;\n message: string;\n request: FetchRequestObject;\n response: FetchResponseObject;\n}\n\n/** @see {@link https://zimic.dev/docs/fetch/api/fetch-response-error `FetchResponseError` API reference} */\nclass FetchResponseError<\n Schema extends HttpSchema,\n Method extends HttpSchemaMethod<Schema>,\n Path extends HttpSchemaPath.Literal<Schema, Method>,\n> extends Error {\n constructor(\n public request: FetchRequest<Schema, Method, Path>,\n public response: FetchResponse<Schema, Method, Path, true, 'manual'>,\n ) {\n super(`${request.method} ${request.url} failed with status ${response.status}: ${response.statusText}`);\n this.name = 'FetchResponseError';\n }\n\n /** @see {@link https://zimic.dev/docs/fetch/api/fetch-response-error#errortoobject `fetchResponseError.toObject()` API reference} */\n toObject(options: FetchResponseErrorObjectOptions.WithBody): Promise<FetchResponseErrorObject>;\n toObject(options?: FetchResponseErrorObjectOptions.WithoutBody): FetchResponseErrorObject;\n toObject(options?: FetchResponseErrorObjectOptions): PossiblePromise<FetchResponseErrorObject>;\n toObject({\n includeRequestBody = false,\n includeResponseBody = false,\n }: FetchResponseErrorObjectOptions = {}): PossiblePromise<FetchResponseErrorObject> {\n const partialObject = {\n name: this.name,\n message: this.message,\n } satisfies Partial<FetchResponseErrorObject>;\n\n if (!includeRequestBody && !includeResponseBody) {\n return {\n ...partialObject,\n request: this.requestToObject({ includeBody: false }),\n response: this.responseToObject({ includeBody: false }),\n };\n }\n\n return Promise.all([\n Promise.resolve(this.requestToObject({ includeBody: includeRequestBody })),\n Promise.resolve(this.responseToObject({ includeBody: includeResponseBody })),\n ]).then(([request, response]) => ({ ...partialObject, request, response }));\n }\n\n private requestToObject(options: { includeBody: true }): Promise<FetchRequestObject>;\n private requestToObject(options: { includeBody: false }): FetchRequestObject;\n private requestToObject(options: { includeBody: boolean }): PossiblePromise<FetchRequestObject>;\n private requestToObject(options: { includeBody: boolean }): PossiblePromise<FetchRequestObject> {\n const request = this.request;\n\n const requestObject: FetchRequestObject = {\n url: request.url,\n path: request.path,\n method: request.method,\n headers: this.convertHeadersToObject(request),\n cache: request.cache,\n destination: request.destination,\n credentials: request.credentials,\n integrity: request.integrity,\n keepalive: request.keepalive,\n mode: request.mode,\n redirect: request.redirect,\n referrer: request.referrer,\n referrerPolicy: request.referrerPolicy,\n };\n\n if (!options.includeBody) {\n return requestObject;\n }\n\n return this.withIncludedBodyIfAvailable('request', requestObject);\n }\n\n private responseToObject(options: { includeBody: true }): Promise<FetchResponseObject>;\n private responseToObject(options: { includeBody: false }): FetchResponseObject;\n private responseToObject(options: { includeBody: boolean }): PossiblePromise<FetchResponseObject>;\n private responseToObject(options: { includeBody: boolean }): PossiblePromise<FetchResponseObject> {\n const response = this.response;\n\n const responseObject: FetchResponseObject = {\n url: response.url,\n type: response.type,\n status: response.status,\n statusText: response.statusText,\n ok: response.ok,\n headers: this.convertHeadersToObject(response),\n redirected: response.redirected,\n };\n\n if (!options.includeBody) {\n return responseObject;\n }\n\n return this.withIncludedBodyIfAvailable('response', responseObject);\n }\n\n private convertHeadersToObject(\n resource: FetchRequest<Schema, Method, Path> | FetchResponse<Schema, Method, Path, true, 'manual'>,\n ): HttpHeadersSchema {\n return HttpHeaders.prototype.toObject.call(resource.headers) as HttpHeadersSchema;\n }\n\n private withIncludedBodyIfAvailable(\n resourceType: 'request',\n resourceObject: FetchRequestObject,\n ): PossiblePromise<FetchRequestObject>;\n private withIncludedBodyIfAvailable(\n resourceType: 'response',\n resourceObject: FetchResponseObject,\n ): PossiblePromise<FetchResponseObject>;\n private withIncludedBodyIfAvailable(\n resourceType: 'request' | 'response',\n resourceObject: FetchRequestObject | FetchResponseObject,\n ): PossiblePromise<FetchRequestObject | FetchResponseObject> {\n const resource = this[resourceType];\n\n if (resource.bodyUsed) {\n console.warn(\n `[@zimic/fetch] Could not include the ${resourceType} body because it is already used. ` +\n 'If you access the body before calling `error.toObject()`, consider reading it from a cloned ' +\n `${resourceType}.\\n\\nLearn more: https://zimic.dev/docs/fetch/api/fetch-response-error#errortoobject`,\n );\n return resourceObject;\n }\n\n return resource.text().then((body: string) => {\n resourceObject.body = body.length > 0 ? body : null;\n return resourceObject;\n });\n }\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type AnyFetchRequestError = FetchResponseError<any, any, any>;\n\nexport default FetchResponseError;\n","export function createPathCharactersToEscapeRegex() {\n return /([.(){}+$])/g;\n}\n\nexport function preparePathForRegex(path: string) {\n // We encode the path using the URL API because, differently from encodeURI and encodeURIComponent, URL does not\n // re-encode already encoded characters. Since URL requires a full URL, we use a data scheme and strip it later.\n const pathURLPrefix = `data:${path.startsWith('/') ? '' : '/'}`;\n const pathAsURL = new URL(`${pathURLPrefix}${path}`);\n const encodedPath = pathAsURL.href.replace(pathURLPrefix, '');\n\n return encodedPath.replace(/^\\/+/g, '').replace(/\\/+$/g, '').replace(createPathCharactersToEscapeRegex(), '\\\\$1');\n}\n\n// Path params names must match the JavaScript identifier pattern.\n// See // https://developer.mozilla.org/docs/Web/JavaScript/Reference/Lexical_grammar#identifiers.\nexport function createPathParamRegex() {\n return /(?<escape>\\\\)?:(?<identifier>[$_\\p{ID_Start}][$\\p{ID_Continue}]+)/gu;\n}\n\nexport function createRepeatingPathParamRegex() {\n return /(?<escape>\\\\)?:(?<identifier>[$_\\p{ID_Start}][$\\p{ID_Continue}]+)\\\\+/gu;\n}\n\nexport function createOptionalPathParamRegex() {\n return /(?<leadingSlash>\\/)?(?<escape>\\\\)?:(?<identifier>[$_\\p{ID_Start}][$\\p{ID_Continue}]+)\\?(?<trailingSlash>\\/)?/gu;\n}\n\nexport function createOptionalRepeatingPathParamRegex() {\n return /(?<leadingSlash>\\/)?(?<escape>\\\\)?:(?<identifier>[$_\\p{ID_Start}][$\\p{ID_Continue}]+)\\*(?<trailingSlash>\\/)?/gu;\n}\n\nfunction createRegexFromPath(path: string) {\n const pathRegexContent = preparePathForRegex(path)\n .replace(\n createOptionalRepeatingPathParamRegex(),\n (\n _match,\n leadingSlash: string | undefined,\n escape: string | undefined,\n identifier: string,\n trailingSlash: string | undefined,\n ) => {\n if (escape) {\n return `:${identifier}`;\n }\n\n const hasSegmentBeforePrefix = leadingSlash === '/';\n const prefixExpression = hasSegmentBeforePrefix ? '/?' : leadingSlash;\n\n const hasSegmentAfterSuffix = trailingSlash === '/';\n const suffixExpression = hasSegmentAfterSuffix ? '/?' : trailingSlash;\n\n if (prefixExpression && suffixExpression) {\n return `(?:${prefixExpression}(?<${identifier}>.+?)?${suffixExpression})?`;\n } else if (prefixExpression) {\n return `(?:${prefixExpression}(?<${identifier}>.+?))?`;\n } else if (suffixExpression) {\n return `(?:(?<${identifier}>.+?)${suffixExpression})?`;\n } else {\n return `(?<${identifier}>.+?)?`;\n }\n },\n )\n .replace(createRepeatingPathParamRegex(), (_match, escape: string | undefined, identifier: string) => {\n return escape ? `:${identifier}` : `(?<${identifier}>.+)`;\n })\n .replace(\n createOptionalPathParamRegex(),\n (\n _match,\n leadingSlash: string | undefined,\n escape: string | undefined,\n identifier: string,\n trailingSlash: string | undefined,\n ) => {\n if (escape) {\n return `:${identifier}`;\n }\n\n const hasSegmentBeforePrefix = leadingSlash === '/';\n const prefixExpression = hasSegmentBeforePrefix ? '/?' : leadingSlash;\n\n const hasSegmentAfterSuffix = trailingSlash === '/';\n const suffixExpression = hasSegmentAfterSuffix ? '/?' : trailingSlash;\n\n if (prefixExpression && suffixExpression) {\n return `(?:${prefixExpression}(?<${identifier}>[^\\\\/]+?)?${suffixExpression})`;\n } else if (prefixExpression) {\n return `(?:${prefixExpression}(?<${identifier}>[^\\\\/]+?))?`;\n } else if (suffixExpression) {\n return `(?:(?<${identifier}>[^\\\\/]+?)${suffixExpression})?`;\n } else {\n return `(?<${identifier}>[^\\\\/]+?)?`;\n }\n },\n )\n .replace(createPathParamRegex(), (_match, escape: string | undefined, identifier: string) => {\n return escape ? `:${identifier}` : `(?<${identifier}>[^\\\\/]+?)`;\n });\n\n return new RegExp(`^/?${pathRegexContent}/?$`);\n}\n\nexport default createRegexFromPath;\n","function excludeURLParams(url: URL) {\n url.hash = '';\n url.search = '';\n url.username = '';\n url.password = '';\n return url;\n}\n\nexport default excludeURLParams;\n","function joinURL(...parts: (URL | string)[]) {\n return parts\n .map((part, index) => {\n const isFirstPart = index === 0;\n const isLastPart = index === parts.length - 1;\n\n let partAsString = part.toString();\n\n if (!isFirstPart) {\n partAsString = partAsString.replace(/^\\//, '');\n }\n if (!isLastPart) {\n partAsString = partAsString.replace(/\\/$/, '');\n }\n\n return partAsString;\n })\n .filter((part) => part.length > 0)\n .join('/');\n}\n\nexport default joinURL;\n","import {\n HttpSchemaPath,\n HttpSchemaMethod,\n HttpSearchParams,\n LiteralHttpSchemaPathFromNonLiteral,\n HttpSchema,\n HttpHeaders,\n} from '@zimic/http';\nimport createRegexFromPath from '@zimic/utils/url/createRegexFromPath';\nimport excludeURLParams from '@zimic/utils/url/excludeURLParams';\nimport joinURL from '@zimic/utils/url/joinURL';\n\nimport FetchResponseError from './errors/FetchResponseError';\nimport { FetchInput, FetchOptions, Fetch, FetchDefaults } from './types/public';\nimport { FetchRequestConstructor, FetchRequestInit, FetchRequest, FetchResponse } from './types/requests';\n\nclass FetchClient<Schema extends HttpSchema> implements Omit<Fetch<Schema>, 'defaults' | 'loose' | 'Request'> {\n fetch: Fetch<Schema>;\n\n constructor({ onRequest, onResponse, ...defaults }: FetchOptions<Schema>) {\n this.fetch = this.createFetchFunction();\n\n this.fetch.defaults = {\n ...defaults,\n headers: defaults.headers ?? {},\n searchParams: defaults.searchParams ?? {},\n };\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n this.fetch.loose = this.fetch as Fetch<any> as Fetch.Loose;\n\n this.fetch.Request = this.createRequestClass(this.fetch.defaults);\n this.fetch.onRequest = onRequest;\n this.fetch.onResponse = onResponse;\n }\n\n private createFetchFunction() {\n const fetch = async <\n Method extends HttpSchemaMethod<Schema>,\n Path extends HttpSchemaPath.NonLiteral<Schema, Method>,\n >(\n input: FetchInput<Schema, Method, Path>,\n init: FetchRequestInit<Schema, Method, LiteralHttpSchemaPathFromNonLiteral<Schema, Method, Path>>,\n ) => {\n const request = await this.createFetchRequest<Method, Path>(input, init);\n const requestClone = request.clone();\n\n const rawResponse = await globalThis.fetch(\n // Optimize type checking by narrowing the type of request\n requestClone as Request,\n );\n const response = await this.createFetchResponse<\n Method,\n LiteralHttpSchemaPathFromNonLiteral<Schema, Method, Path>\n >(request, rawResponse);\n\n return response;\n };\n\n Object.setPrototypeOf(fetch, this);\n\n return fetch as Fetch<Schema>;\n }\n\n private async createFetchRequest<\n Method extends HttpSchemaMethod<Schema>,\n Path extends HttpSchemaPath.NonLiteral<Schema, Method>,\n >(\n input: FetchInput<Schema, Method, Path>,\n init: FetchRequestInit<Schema, Method, LiteralHttpSchemaPathFromNonLiteral<Schema, Method, Path>>,\n ) {\n let request = input instanceof Request ? input : new this.fetch.Request(input, init);\n\n if (this.fetch.onRequest) {\n const requestAfterInterceptor = await this.fetch.onRequest(\n // Optimize type checking by narrowing the type of request\n request as FetchRequest.Loose,\n );\n\n if (requestAfterInterceptor !== request) {\n const isFetchRequest = requestAfterInterceptor instanceof this.fetch.Request;\n\n request = isFetchRequest\n ? (requestAfterInterceptor as Request as typeof request)\n : new this.fetch.Request(requestAfterInterceptor as FetchInput<Schema, Method, Path>, init);\n }\n }\n\n return request;\n }\n\n private async createFetchResponse<\n Method extends HttpSchemaMethod<Schema>,\n Path extends HttpSchemaPath.Literal<Schema, Method>,\n >(fetchRequest: FetchRequest<Schema, Method, Path>, rawResponse: Response) {\n let response = this.defineFetchResponseProperties<Method, Path>(fetchRequest, rawResponse);\n\n if (this.fetch.onResponse) {\n const responseAfterInterceptor = await this.fetch.onResponse(\n // Optimize type checking by narrowing the type of response\n response as FetchResponse.Loose,\n );\n\n const isFetchResponse =\n responseAfterInterceptor instanceof Response &&\n 'request' in responseAfterInterceptor &&\n responseAfterInterceptor.request instanceof this.fetch.Request;\n\n response = isFetchResponse\n ? (responseAfterInterceptor as typeof response)\n : this.defineFetchResponseProperties<Method, Path>(fetchRequest, responseAfterInterceptor);\n }\n\n return response;\n }\n\n private defineFetchResponseProperties<\n Method extends HttpSchemaMethod<Schema>,\n Path extends HttpSchemaPath.Literal<Schema, Method>,\n >(fetchRequest: FetchRequest<Schema, Method, Path>, response: Response) {\n const fetchResponse = response as FetchResponse<Schema, Method, Path>;\n\n Object.defineProperty(fetchResponse, 'request', {\n value: fetchRequest,\n writable: false,\n enumerable: true,\n configurable: false,\n });\n\n let responseError: FetchResponse.Loose['error'] | undefined;\n\n Object.defineProperty(fetchResponse, 'error', {\n get() {\n if (responseError === undefined) {\n responseError = fetchResponse.ok\n ? null\n : new FetchResponseError(\n fetchRequest,\n fetchResponse as FetchResponse<Schema, Method, Path, true, 'manual'>,\n );\n }\n return responseError;\n },\n enumerable: true,\n configurable: false,\n });\n\n return fetchResponse;\n }\n\n private createRequestClass(defaults: FetchDefaults) {\n class Request<\n Method extends HttpSchemaMethod<Schema>,\n Path extends HttpSchemaPath.NonLiteral<Schema, Method>,\n > extends globalThis.Request {\n path: LiteralHttpSchemaPathFromNonLiteral<Schema, Method, Path>;\n\n constructor(\n input: FetchInput<Schema, Method, Path>,\n init: FetchRequestInit<Schema, Method, LiteralHttpSchemaPathFromNonLiteral<Schema, Method, Path>>,\n ) {\n const initWithDefaults = { ...defaults, ...init };\n\n const headersFromDefaults = new HttpHeaders(defaults.headers);\n const headersFromInit = new HttpHeaders((init satisfies RequestInit as RequestInit).headers);\n\n let url: URL;\n const baseURL = new URL(initWithDefaults.baseURL);\n\n if (input instanceof globalThis.Request) {\n // Optimize type checking by narrowing the type of input\n const request = input as globalThis.Request;\n\n // Optimize type checking by narrowing the type of headers\n const headersFromRequest = new HttpHeaders(input.headers as Headers);\n\n initWithDefaults.headers = {\n ...headersFromDefaults.toObject(),\n ...headersFromRequest.toObject(),\n ...headersFromInit.toObject(),\n };\n\n super(request, initWithDefaults);\n\n url = new URL(input.url);\n } else {\n initWithDefaults.headers = {\n ...headersFromDefaults.toObject(),\n ...headersFromInit.toObject(),\n };\n\n url = input instanceof URL ? new URL(input) : new URL(joinURL(baseURL, input));\n\n const searchParamsFromDefaults = new HttpSearchParams(defaults.searchParams);\n const searchParamsFromInit = new HttpSearchParams(initWithDefaults.searchParams);\n\n initWithDefaults.searchParams = {\n ...searchParamsFromDefaults.toObject(),\n ...searchParamsFromInit.toObject(),\n };\n\n url.search = new HttpSearchParams(initWithDefaults.searchParams).toString();\n\n super(url, initWithDefaults);\n }\n\n const baseURLWithoutTrailingSlash = baseURL.toString().replace(/\\/$/, '');\n\n this.path = excludeURLParams(url)\n .toString()\n .replace(baseURLWithoutTrailingSlash, '') as LiteralHttpSchemaPathFromNonLiteral<Schema, Method, Path>;\n }\n\n clone(): Request<Method, Path> {\n const rawClone = super.clone();\n\n return new Request<Method, Path>(\n rawClone as unknown as FetchInput<Schema, Method, Path>,\n rawClone as unknown as FetchRequestInit<\n Schema,\n Method,\n LiteralHttpSchemaPathFromNonLiteral<Schema, Method, Path>\n >,\n );\n }\n }\n\n return Request as FetchRequestConstructor<Schema>;\n }\n\n isRequest<Path extends HttpSchemaPath.Literal<Schema, Method>, Method extends HttpSchemaMethod<Schema>>(\n request: unknown,\n method: Method,\n path: Path,\n ): request is FetchRequest<Schema, Method, Path> {\n return (\n request instanceof Request &&\n request.method === method &&\n 'path' in request &&\n typeof request.path === 'string' &&\n createRegexFromPath(path).test(request.path)\n );\n }\n\n isResponse<Path extends HttpSchemaPath.Literal<Schema, Method>, Method extends HttpSchemaMethod<Schema>>(\n response: unknown,\n method: Method,\n path: Path,\n ): response is FetchResponse<Schema, Method, Path> {\n return (\n response instanceof Response &&\n 'request' in response &&\n this.isRequest(response.request, method, path) &&\n 'error' in response &&\n (response.error === null || response.error instanceof FetchResponseError)\n );\n }\n\n isResponseError<Path extends HttpSchemaPath.Literal<Schema, Method>, Method extends HttpSchemaMethod<Schema>>(\n error: unknown,\n method: Method,\n path: Path,\n ): error is FetchResponseError<Schema, Method, Path> {\n return (\n error instanceof FetchResponseError &&\n this.isRequest(error.request, method, path) &&\n this.isResponse(error.response, method, path)\n );\n }\n}\n\nexport default FetchClient;\n","import { HttpSchema } from '@zimic/http';\n\nimport FetchClient from './FetchClient';\nimport { FetchOptions, Fetch } from './types/public';\n\n/** @see {@link https://zimic.dev/docs/fetch/api/create-fetch `createFetch` API reference} */\nfunction createFetch<Schema extends HttpSchema>(options: FetchOptions<Schema>): Fetch<Schema> {\n const { fetch } = new FetchClient<Schema>(options);\n return fetch;\n}\n\nexport default createFetch;\n"]}
1
+ {"version":3,"sources":["../src/client/errors/FetchResponseError.ts","../../zimic-utils/src/url/createRegexFromPath.ts","../../zimic-utils/src/url/excludeNonPathParams.ts","../../zimic-utils/src/url/joinURL.ts","../src/client/FetchClient.ts","../src/client/factory.ts"],"names":["HttpHeaders","parseHttpBody","Request","HttpSearchParams"],"mappings":"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","file":"index.js","sourcesContent":["import {\n HttpHeaders,\n HttpHeadersSchema,\n HttpSchema,\n HttpSchemaMethod,\n HttpSchemaPath,\n parseHttpBody,\n} from '@zimic/http';\nimport { PossiblePromise } from '@zimic/utils/types';\n\nimport { FetchRequest, FetchRequestObject, FetchResponse, FetchResponseObject } from '../types/requests';\n\n/** @see {@link https://zimic.dev/docs/fetch/api/fetch-response-error#errortoobject `fetchResponseError.toObject()` API reference} */\nexport interface FetchResponseErrorObjectOptions {\n /** @see {@link https://zimic.dev/docs/fetch/api/fetch-response-error#errortoobject `fetchResponseError.toObject()` API reference} */\n includeRequestBody?: boolean;\n /** @see {@link https://zimic.dev/docs/fetch/api/fetch-response-error#errortoobject `fetchResponseError.toObject()` API reference} */\n includeResponseBody?: boolean;\n}\n\nexport namespace FetchResponseErrorObjectOptions {\n /**\n * Options for converting a {@link FetchResponseError `FetchResponseError`} into a plain object, including the body of\n * the request and/or response.\n */\n export type WithBody = FetchResponseErrorObjectOptions &\n ({ includeRequestBody: true } | { includeResponseBody: true });\n\n /**\n * Options for converting a {@link FetchResponseError `FetchResponseError`} into a plain object, excluding the body of\n * the request and/or response.\n */\n export type WithoutBody = FetchResponseErrorObjectOptions &\n ({ includeRequestBody?: false } | { includeResponseBody?: false });\n}\n\n/**\n * A plain object representation of a {@link FetchResponseError `FetchResponseError`}, compatible with JSON. It is useful\n * for serialization, debugging, and logging purposes.\n *\n * @see {@link https://zimic.dev/docs/fetch/api/fetch-response-error#errortoobject `fetchResponseError.toObject()` API reference}\n */\nexport interface FetchResponseErrorObject {\n name: string;\n message: string;\n request: FetchRequestObject;\n response: FetchResponseObject;\n}\n\n/** @see {@link https://zimic.dev/docs/fetch/api/fetch-response-error `FetchResponseError` API reference} */\nclass FetchResponseError<\n Schema extends HttpSchema,\n Method extends HttpSchemaMethod<Schema>,\n Path extends HttpSchemaPath.Literal<Schema, Method>,\n> extends Error {\n constructor(\n public request: FetchRequest<Schema, Method, Path>,\n public response: FetchResponse<Schema, Method, Path, true, 'manual'>,\n ) {\n super(`${request.method} ${request.url} failed with status ${response.status}: ${response.statusText}`);\n this.name = 'FetchResponseError';\n }\n\n /** @see {@link https://zimic.dev/docs/fetch/api/fetch-response-error#errortoobject `fetchResponseError.toObject()` API reference} */\n toObject(options: FetchResponseErrorObjectOptions.WithBody): Promise<FetchResponseErrorObject>;\n toObject(options?: FetchResponseErrorObjectOptions.WithoutBody): FetchResponseErrorObject;\n toObject(options?: FetchResponseErrorObjectOptions): PossiblePromise<FetchResponseErrorObject>;\n toObject({\n includeRequestBody = false,\n includeResponseBody = false,\n }: FetchResponseErrorObjectOptions = {}): PossiblePromise<FetchResponseErrorObject> {\n const partialObject = {\n name: this.name,\n message: this.message,\n } satisfies Partial<FetchResponseErrorObject>;\n\n if (!includeRequestBody && !includeResponseBody) {\n return {\n ...partialObject,\n request: this.requestToObject({ includeBody: false }),\n response: this.responseToObject({ includeBody: false }),\n };\n }\n\n return Promise.all([\n Promise.resolve(this.requestToObject({ includeBody: includeRequestBody })),\n Promise.resolve(this.responseToObject({ includeBody: includeResponseBody })),\n ]).then(([request, response]) => ({ ...partialObject, request, response }));\n }\n\n private requestToObject(options: { includeBody: true }): Promise<FetchRequestObject>;\n private requestToObject(options: { includeBody: false }): FetchRequestObject;\n private requestToObject(options: { includeBody: boolean }): PossiblePromise<FetchRequestObject>;\n private requestToObject(options: { includeBody: boolean }): PossiblePromise<FetchRequestObject> {\n const request = this.request;\n\n const requestObject: FetchRequestObject = {\n url: request.url,\n path: request.path,\n method: request.method,\n headers: this.convertHeadersToObject(request),\n cache: request.cache,\n destination: request.destination,\n credentials: request.credentials,\n integrity: request.integrity,\n keepalive: request.keepalive,\n mode: request.mode,\n redirect: request.redirect,\n referrer: request.referrer,\n referrerPolicy: request.referrerPolicy,\n };\n\n if (!options.includeBody) {\n return requestObject;\n }\n\n return this.withIncludedBodyIfAvailable('request', requestObject);\n }\n\n private responseToObject(options: { includeBody: true }): Promise<FetchResponseObject>;\n private responseToObject(options: { includeBody: false }): FetchResponseObject;\n private responseToObject(options: { includeBody: boolean }): PossiblePromise<FetchResponseObject>;\n private responseToObject(options: { includeBody: boolean }): PossiblePromise<FetchResponseObject> {\n const response = this.response;\n\n const responseObject: FetchResponseObject = {\n url: response.url,\n type: response.type,\n status: response.status,\n statusText: response.statusText,\n ok: response.ok,\n headers: this.convertHeadersToObject(response),\n redirected: response.redirected,\n };\n\n if (!options.includeBody) {\n return responseObject;\n }\n\n return this.withIncludedBodyIfAvailable('response', responseObject);\n }\n\n private convertHeadersToObject(\n resource: FetchRequest<Schema, Method, Path> | FetchResponse<Schema, Method, Path, true, 'manual'>,\n ): HttpHeadersSchema {\n return HttpHeaders.prototype.toObject.call(resource.headers) as HttpHeadersSchema;\n }\n\n private withIncludedBodyIfAvailable(\n resourceType: 'request',\n resourceObject: FetchRequestObject,\n ): PossiblePromise<FetchRequestObject>;\n private withIncludedBodyIfAvailable(\n resourceType: 'response',\n resourceObject: FetchResponseObject,\n ): PossiblePromise<FetchResponseObject>;\n private withIncludedBodyIfAvailable(\n resourceType: 'request' | 'response',\n resourceObject: FetchRequestObject | FetchResponseObject,\n ): PossiblePromise<FetchRequestObject | FetchResponseObject> {\n const resource = this[resourceType] as Request | Response;\n\n if (resource.bodyUsed) {\n console.warn(\n '[@zimic/fetch]',\n `Could not include the ${resourceType} body because it is already used. ` +\n 'If you access the body before calling `error.toObject()`, consider reading it from a cloned ' +\n `${resourceType}.\\n\\nLearn more: https://zimic.dev/docs/fetch/api/fetch-response-error#errortoobject`,\n );\n return resourceObject;\n }\n\n return parseHttpBody(resource)\n .then((body) => {\n resourceObject.body = body;\n return resourceObject;\n })\n .catch((error: unknown) => {\n console.error('[@zimic/fetch]', `Failed to parse ${resourceType} body:`, error);\n return resourceObject;\n });\n }\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type AnyFetchRequestError = FetchResponseError<any, any, any>;\n\nexport default FetchResponseError;\n","export function createPathCharactersToEscapeRegex() {\n return /([.(){}+$])/g;\n}\n\nexport function preparePathForRegex(path: string) {\n // We encode the path using the URL API because, differently from encodeURI and encodeURIComponent, URL does not\n // re-encode already encoded characters. Since URL requires a full URL, we use a data scheme and strip it later.\n const pathURLPrefix = `data:${path.startsWith('/') ? '' : '/'}`;\n const pathAsURL = new URL(`${pathURLPrefix}${path}`);\n const encodedPath = pathAsURL.href.replace(pathURLPrefix, '');\n\n return encodedPath.replace(/^\\/+/g, '').replace(/\\/+$/g, '').replace(createPathCharactersToEscapeRegex(), '\\\\$1');\n}\n\n// Path params names must match the JavaScript identifier pattern.\n// See // https://developer.mozilla.org/docs/Web/JavaScript/Reference/Lexical_grammar#identifiers.\nexport function createPathParamRegex() {\n return /(?<escape>\\\\)?:(?<identifier>[$_\\p{ID_Start}][$\\p{ID_Continue}]+)/gu;\n}\n\nexport function createRepeatingPathParamRegex() {\n return /(?<escape>\\\\)?:(?<identifier>[$_\\p{ID_Start}][$\\p{ID_Continue}]+)\\\\+/gu;\n}\n\nexport function createOptionalPathParamRegex() {\n return /(?<leadingSlash>\\/)?(?<escape>\\\\)?:(?<identifier>[$_\\p{ID_Start}][$\\p{ID_Continue}]+)\\?(?<trailingSlash>\\/)?/gu;\n}\n\nexport function createOptionalRepeatingPathParamRegex() {\n return /(?<leadingSlash>\\/)?(?<escape>\\\\)?:(?<identifier>[$_\\p{ID_Start}][$\\p{ID_Continue}]+)\\*(?<trailingSlash>\\/)?/gu;\n}\n\nfunction createRegexFromPath(path: string) {\n const pathRegexContent = preparePathForRegex(path)\n .replace(\n createOptionalRepeatingPathParamRegex(),\n (\n _match,\n leadingSlash: string | undefined,\n escape: string | undefined,\n identifier: string,\n trailingSlash: string | undefined,\n ) => {\n if (escape) {\n return `:${identifier}`;\n }\n\n const hasSegmentBeforePrefix = leadingSlash === '/';\n const prefixExpression = hasSegmentBeforePrefix ? '/?' : leadingSlash;\n\n const hasSegmentAfterSuffix = trailingSlash === '/';\n const suffixExpression = hasSegmentAfterSuffix ? '/?' : trailingSlash;\n\n if (prefixExpression && suffixExpression) {\n return `(?:${prefixExpression}(?<${identifier}>.+?)?${suffixExpression})?`;\n } else if (prefixExpression) {\n return `(?:${prefixExpression}(?<${identifier}>.+?))?`;\n } else if (suffixExpression) {\n return `(?:(?<${identifier}>.+?)${suffixExpression})?`;\n } else {\n return `(?<${identifier}>.+?)?`;\n }\n },\n )\n .replace(createRepeatingPathParamRegex(), (_match, escape: string | undefined, identifier: string) => {\n return escape ? `:${identifier}` : `(?<${identifier}>.+)`;\n })\n .replace(\n createOptionalPathParamRegex(),\n (\n _match,\n leadingSlash: string | undefined,\n escape: string | undefined,\n identifier: string,\n trailingSlash: string | undefined,\n ) => {\n if (escape) {\n return `:${identifier}`;\n }\n\n const hasSegmentBeforePrefix = leadingSlash === '/';\n const prefixExpression = hasSegmentBeforePrefix ? '/?' : leadingSlash;\n\n const hasSegmentAfterSuffix = trailingSlash === '/';\n const suffixExpression = hasSegmentAfterSuffix ? '/?' : trailingSlash;\n\n if (prefixExpression && suffixExpression) {\n return `(?:${prefixExpression}(?<${identifier}>[^\\\\/]+?)?${suffixExpression})`;\n } else if (prefixExpression) {\n return `(?:${prefixExpression}(?<${identifier}>[^\\\\/]+?))?`;\n } else if (suffixExpression) {\n return `(?:(?<${identifier}>[^\\\\/]+?)${suffixExpression})?`;\n } else {\n return `(?<${identifier}>[^\\\\/]+?)?`;\n }\n },\n )\n .replace(createPathParamRegex(), (_match, escape: string | undefined, identifier: string) => {\n return escape ? `:${identifier}` : `(?<${identifier}>[^\\\\/]+?)`;\n });\n\n return new RegExp(`^/?${pathRegexContent}/?$`);\n}\n\nexport default createRegexFromPath;\n","function excludeNonPathParams(url: URL) {\n url.hash = '';\n url.search = '';\n url.username = '';\n url.password = '';\n return url;\n}\n\nexport default excludeNonPathParams;\n","function joinURL(...parts: (URL | string)[]) {\n return parts\n .map((part, index) => {\n const isFirstPart = index === 0;\n const isLastPart = index === parts.length - 1;\n\n let partAsString = part.toString();\n\n if (!isFirstPart) {\n partAsString = partAsString.replace(/^\\//, '');\n }\n if (!isLastPart) {\n partAsString = partAsString.replace(/\\/$/, '');\n }\n\n return partAsString;\n })\n .filter((part) => part.length > 0)\n .join('/');\n}\n\nexport default joinURL;\n","import {\n HttpSchemaPath,\n HttpSchemaMethod,\n HttpSearchParams,\n LiteralHttpSchemaPathFromNonLiteral,\n HttpSchema,\n HttpHeaders,\n} from '@zimic/http';\nimport createRegexFromPath from '@zimic/utils/url/createRegexFromPath';\nimport excludeNonPathParams from '@zimic/utils/url/excludeNonPathParams';\nimport joinURL from '@zimic/utils/url/joinURL';\n\nimport FetchResponseError from './errors/FetchResponseError';\nimport { FetchInput, FetchOptions, Fetch, FetchDefaults } from './types/public';\nimport { FetchRequestConstructor, FetchRequestInit, FetchRequest, FetchResponse } from './types/requests';\n\nclass FetchClient<Schema extends HttpSchema> implements Omit<Fetch<Schema>, 'defaults' | 'loose' | 'Request'> {\n fetch: Fetch<Schema>;\n\n constructor({ onRequest, onResponse, ...defaults }: FetchOptions<Schema>) {\n this.fetch = this.createFetchFunction();\n\n this.fetch.defaults = {\n ...defaults,\n headers: defaults.headers ?? {},\n searchParams: defaults.searchParams ?? {},\n };\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n this.fetch.loose = this.fetch as Fetch<any> as Fetch.Loose;\n\n this.fetch.Request = this.createRequestClass(this.fetch.defaults);\n this.fetch.onRequest = onRequest;\n this.fetch.onResponse = onResponse;\n }\n\n private createFetchFunction() {\n const fetch = async <\n Method extends HttpSchemaMethod<Schema>,\n Path extends HttpSchemaPath.NonLiteral<Schema, Method>,\n >(\n input: FetchInput<Schema, Method, Path>,\n init: FetchRequestInit<Schema, Method, LiteralHttpSchemaPathFromNonLiteral<Schema, Method, Path>>,\n ) => {\n const request = await this.createFetchRequest<Method, Path>(input, init);\n const requestClone = request.clone();\n\n const rawResponse = await globalThis.fetch(\n // Optimize type checking by narrowing the type of request\n requestClone as Request,\n );\n const response = await this.createFetchResponse<\n Method,\n LiteralHttpSchemaPathFromNonLiteral<Schema, Method, Path>\n >(request, rawResponse);\n\n return response;\n };\n\n Object.setPrototypeOf(fetch, this);\n\n return fetch as Fetch<Schema>;\n }\n\n private async createFetchRequest<\n Method extends HttpSchemaMethod<Schema>,\n Path extends HttpSchemaPath.NonLiteral<Schema, Method>,\n >(\n input: FetchInput<Schema, Method, Path>,\n init: FetchRequestInit<Schema, Method, LiteralHttpSchemaPathFromNonLiteral<Schema, Method, Path>>,\n ) {\n let request = input instanceof Request ? input : new this.fetch.Request(input, init);\n\n if (this.fetch.onRequest) {\n const requestAfterInterceptor = await this.fetch.onRequest(\n // Optimize type checking by narrowing the type of request\n request as FetchRequest.Loose,\n );\n\n if (requestAfterInterceptor !== request) {\n const isFetchRequest = requestAfterInterceptor instanceof this.fetch.Request;\n\n request = isFetchRequest\n ? (requestAfterInterceptor as Request as typeof request)\n : new this.fetch.Request(requestAfterInterceptor as FetchInput<Schema, Method, Path>, init);\n }\n }\n\n return request;\n }\n\n private async createFetchResponse<\n Method extends HttpSchemaMethod<Schema>,\n Path extends HttpSchemaPath.Literal<Schema, Method>,\n >(fetchRequest: FetchRequest<Schema, Method, Path>, rawResponse: Response) {\n let response = this.defineFetchResponseProperties<Method, Path>(fetchRequest, rawResponse);\n\n if (this.fetch.onResponse) {\n const responseAfterInterceptor = await this.fetch.onResponse(\n // Optimize type checking by narrowing the type of response\n response as FetchResponse.Loose,\n );\n\n const isFetchResponse =\n responseAfterInterceptor instanceof Response &&\n 'request' in responseAfterInterceptor &&\n responseAfterInterceptor.request instanceof this.fetch.Request;\n\n response = isFetchResponse\n ? (responseAfterInterceptor as typeof response)\n : this.defineFetchResponseProperties<Method, Path>(fetchRequest, responseAfterInterceptor);\n }\n\n return response;\n }\n\n private defineFetchResponseProperties<\n Method extends HttpSchemaMethod<Schema>,\n Path extends HttpSchemaPath.Literal<Schema, Method>,\n >(fetchRequest: FetchRequest<Schema, Method, Path>, response: Response) {\n const fetchResponse = response as FetchResponse<Schema, Method, Path>;\n\n Object.defineProperty(fetchResponse, 'request', {\n value: fetchRequest,\n writable: false,\n enumerable: true,\n configurable: false,\n });\n\n let responseError: FetchResponse.Loose['error'] | undefined;\n\n Object.defineProperty(fetchResponse, 'error', {\n get() {\n if (responseError === undefined) {\n responseError = fetchResponse.ok\n ? null\n : new FetchResponseError(\n fetchRequest,\n fetchResponse as FetchResponse<Schema, Method, Path, true, 'manual'>,\n );\n }\n return responseError;\n },\n enumerable: true,\n configurable: false,\n });\n\n return fetchResponse;\n }\n\n private createRequestClass(defaults: FetchDefaults) {\n class Request<\n Method extends HttpSchemaMethod<Schema>,\n Path extends HttpSchemaPath.NonLiteral<Schema, Method>,\n > extends globalThis.Request {\n path: LiteralHttpSchemaPathFromNonLiteral<Schema, Method, Path>;\n\n constructor(\n input: FetchInput<Schema, Method, Path>,\n init: FetchRequestInit<Schema, Method, LiteralHttpSchemaPathFromNonLiteral<Schema, Method, Path>>,\n ) {\n const initWithDefaults = { ...defaults, ...init };\n\n const headersFromDefaults = new HttpHeaders(defaults.headers);\n const headersFromInit = new HttpHeaders((init satisfies RequestInit as RequestInit).headers);\n\n let url: URL;\n const baseURL = new URL(initWithDefaults.baseURL);\n\n if (input instanceof globalThis.Request) {\n // Optimize type checking by narrowing the type of input\n const request = input as globalThis.Request;\n\n // Optimize type checking by narrowing the type of headers\n const headersFromRequest = new HttpHeaders(input.headers as Headers);\n\n initWithDefaults.headers = {\n ...headersFromDefaults.toObject(),\n ...headersFromRequest.toObject(),\n ...headersFromInit.toObject(),\n };\n\n super(request, initWithDefaults);\n\n url = new URL(input.url);\n } else {\n initWithDefaults.headers = {\n ...headersFromDefaults.toObject(),\n ...headersFromInit.toObject(),\n };\n\n url = input instanceof URL ? new URL(input) : new URL(joinURL(baseURL, input));\n\n const searchParamsFromDefaults = new HttpSearchParams(defaults.searchParams);\n const searchParamsFromInit = new HttpSearchParams(initWithDefaults.searchParams);\n\n initWithDefaults.searchParams = {\n ...searchParamsFromDefaults.toObject(),\n ...searchParamsFromInit.toObject(),\n };\n\n url.search = new HttpSearchParams(initWithDefaults.searchParams).toString();\n\n super(url, initWithDefaults);\n }\n\n const baseURLWithoutTrailingSlash = baseURL.toString().replace(/\\/$/, '');\n\n this.path = excludeNonPathParams(url)\n .toString()\n .replace(baseURLWithoutTrailingSlash, '') as LiteralHttpSchemaPathFromNonLiteral<Schema, Method, Path>;\n }\n\n clone(): Request<Method, Path> {\n const rawClone = super.clone();\n\n return new Request<Method, Path>(\n rawClone as unknown as FetchInput<Schema, Method, Path>,\n rawClone as unknown as FetchRequestInit<\n Schema,\n Method,\n LiteralHttpSchemaPathFromNonLiteral<Schema, Method, Path>\n >,\n );\n }\n }\n\n return Request as FetchRequestConstructor<Schema>;\n }\n\n isRequest<Path extends HttpSchemaPath.Literal<Schema, Method>, Method extends HttpSchemaMethod<Schema>>(\n request: unknown,\n method: Method,\n path: Path,\n ): request is FetchRequest<Schema, Method, Path> {\n return (\n request instanceof Request &&\n request.method === method &&\n 'path' in request &&\n typeof request.path === 'string' &&\n createRegexFromPath(path).test(request.path)\n );\n }\n\n isResponse<Path extends HttpSchemaPath.Literal<Schema, Method>, Method extends HttpSchemaMethod<Schema>>(\n response: unknown,\n method: Method,\n path: Path,\n ): response is FetchResponse<Schema, Method, Path> {\n return (\n response instanceof Response &&\n 'request' in response &&\n this.isRequest(response.request, method, path) &&\n 'error' in response &&\n (response.error === null || response.error instanceof FetchResponseError)\n );\n }\n\n isResponseError<Path extends HttpSchemaPath.Literal<Schema, Method>, Method extends HttpSchemaMethod<Schema>>(\n error: unknown,\n method: Method,\n path: Path,\n ): error is FetchResponseError<Schema, Method, Path> {\n return (\n error instanceof FetchResponseError &&\n this.isRequest(error.request, method, path) &&\n this.isResponse(error.response, method, path)\n );\n }\n}\n\nexport default FetchClient;\n","import { HttpSchema } from '@zimic/http';\n\nimport FetchClient from './FetchClient';\nimport { FetchOptions, Fetch } from './types/public';\n\n/** @see {@link https://zimic.dev/docs/fetch/api/create-fetch `createFetch` API reference} */\nfunction createFetch<Schema extends HttpSchema>(options: FetchOptions<Schema>): Fetch<Schema> {\n const { fetch } = new FetchClient<Schema>(options);\n return fetch;\n}\n\nexport default createFetch;\n"]}
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { HttpHeaders, HttpSearchParams } from '@zimic/http';
1
+ import { HttpHeaders, parseHttpBody, HttpSearchParams } from '@zimic/http';
2
2
 
3
3
  // src/client/errors/FetchResponseError.ts
4
4
  var FetchResponseError = class extends Error {
@@ -73,14 +73,18 @@ var FetchResponseError = class extends Error {
73
73
  const resource = this[resourceType];
74
74
  if (resource.bodyUsed) {
75
75
  console.warn(
76
- `[@zimic/fetch] Could not include the ${resourceType} body because it is already used. If you access the body before calling \`error.toObject()\`, consider reading it from a cloned ${resourceType}.
76
+ "[@zimic/fetch]",
77
+ `Could not include the ${resourceType} body because it is already used. If you access the body before calling \`error.toObject()\`, consider reading it from a cloned ${resourceType}.
77
78
 
78
79
  Learn more: https://zimic.dev/docs/fetch/api/fetch-response-error#errortoobject`
79
80
  );
80
81
  return resourceObject;
81
82
  }
82
- return resource.text().then((body) => {
83
- resourceObject.body = body.length > 0 ? body : null;
83
+ return parseHttpBody(resource).then((body) => {
84
+ resourceObject.body = body;
85
+ return resourceObject;
86
+ }).catch((error) => {
87
+ console.error("[@zimic/fetch]", `Failed to parse ${resourceType} body:`, error);
84
88
  return resourceObject;
85
89
  });
86
90
  }
@@ -159,15 +163,15 @@ function createRegexFromPath(path) {
159
163
  }
160
164
  var createRegexFromPath_default = createRegexFromPath;
161
165
 
162
- // ../zimic-utils/dist/url/excludeURLParams.mjs
163
- function excludeURLParams(url) {
166
+ // ../zimic-utils/dist/url/excludeNonPathParams.mjs
167
+ function excludeNonPathParams(url) {
164
168
  url.hash = "";
165
169
  url.search = "";
166
170
  url.username = "";
167
171
  url.password = "";
168
172
  return url;
169
173
  }
170
- var excludeURLParams_default = excludeURLParams;
174
+ var excludeNonPathParams_default = excludeNonPathParams;
171
175
 
172
176
  // ../zimic-utils/dist/url/joinURL.mjs
173
177
  function joinURL(...parts) {
@@ -300,7 +304,7 @@ var FetchClient = class {
300
304
  super(url, initWithDefaults);
301
305
  }
302
306
  const baseURLWithoutTrailingSlash = baseURL.toString().replace(/\/$/, "");
303
- this.path = excludeURLParams_default(url).toString().replace(baseURLWithoutTrailingSlash, "");
307
+ this.path = excludeNonPathParams_default(url).toString().replace(baseURLWithoutTrailingSlash, "");
304
308
  }
305
309
  clone() {
306
310
  const rawClone = super.clone();
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/client/errors/FetchResponseError.ts","../../zimic-utils/src/url/createRegexFromPath.ts","../../zimic-utils/src/url/excludeURLParams.ts","../../zimic-utils/src/url/joinURL.ts","../src/client/FetchClient.ts","../src/client/factory.ts"],"names":["Request","HttpHeaders"],"mappings":"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","file":"index.mjs","sourcesContent":["import { HttpHeaders, HttpHeadersSchema, HttpSchema, HttpSchemaMethod, HttpSchemaPath } from '@zimic/http';\nimport { PossiblePromise } from '@zimic/utils/types';\n\nimport { FetchRequest, FetchRequestObject, FetchResponse, FetchResponseObject } from '../types/requests';\n\n/** @see {@link https://zimic.dev/docs/fetch/api/fetch-response-error#errortoobject `fetchResponseError.toObject()` API reference} */\nexport interface FetchResponseErrorObjectOptions {\n /** @see {@link https://zimic.dev/docs/fetch/api/fetch-response-error#errortoobject `fetchResponseError.toObject()` API reference} */\n includeRequestBody?: boolean;\n /** @see {@link https://zimic.dev/docs/fetch/api/fetch-response-error#errortoobject `fetchResponseError.toObject()` API reference} */\n includeResponseBody?: boolean;\n}\n\nexport namespace FetchResponseErrorObjectOptions {\n /**\n * Options for converting a {@link FetchResponseError `FetchResponseError`} into a plain object, including the body of\n * the request and/or response.\n */\n export type WithBody = FetchResponseErrorObjectOptions &\n ({ includeRequestBody: true } | { includeResponseBody: true });\n\n /**\n * Options for converting a {@link FetchResponseError `FetchResponseError`} into a plain object, excluding the body of\n * the request and/or response.\n */\n export type WithoutBody = FetchResponseErrorObjectOptions &\n ({ includeRequestBody?: false } | { includeResponseBody?: false });\n}\n\n/**\n * A plain object representation of a {@link FetchResponseError `FetchResponseError`}, compatible with JSON. It is useful\n * for serialization, debugging, and logging purposes.\n *\n * @see {@link https://zimic.dev/docs/fetch/api/fetch-response-error#errortoobject `fetchResponseError.toObject()` API reference}\n */\nexport interface FetchResponseErrorObject {\n name: string;\n message: string;\n request: FetchRequestObject;\n response: FetchResponseObject;\n}\n\n/** @see {@link https://zimic.dev/docs/fetch/api/fetch-response-error `FetchResponseError` API reference} */\nclass FetchResponseError<\n Schema extends HttpSchema,\n Method extends HttpSchemaMethod<Schema>,\n Path extends HttpSchemaPath.Literal<Schema, Method>,\n> extends Error {\n constructor(\n public request: FetchRequest<Schema, Method, Path>,\n public response: FetchResponse<Schema, Method, Path, true, 'manual'>,\n ) {\n super(`${request.method} ${request.url} failed with status ${response.status}: ${response.statusText}`);\n this.name = 'FetchResponseError';\n }\n\n /** @see {@link https://zimic.dev/docs/fetch/api/fetch-response-error#errortoobject `fetchResponseError.toObject()` API reference} */\n toObject(options: FetchResponseErrorObjectOptions.WithBody): Promise<FetchResponseErrorObject>;\n toObject(options?: FetchResponseErrorObjectOptions.WithoutBody): FetchResponseErrorObject;\n toObject(options?: FetchResponseErrorObjectOptions): PossiblePromise<FetchResponseErrorObject>;\n toObject({\n includeRequestBody = false,\n includeResponseBody = false,\n }: FetchResponseErrorObjectOptions = {}): PossiblePromise<FetchResponseErrorObject> {\n const partialObject = {\n name: this.name,\n message: this.message,\n } satisfies Partial<FetchResponseErrorObject>;\n\n if (!includeRequestBody && !includeResponseBody) {\n return {\n ...partialObject,\n request: this.requestToObject({ includeBody: false }),\n response: this.responseToObject({ includeBody: false }),\n };\n }\n\n return Promise.all([\n Promise.resolve(this.requestToObject({ includeBody: includeRequestBody })),\n Promise.resolve(this.responseToObject({ includeBody: includeResponseBody })),\n ]).then(([request, response]) => ({ ...partialObject, request, response }));\n }\n\n private requestToObject(options: { includeBody: true }): Promise<FetchRequestObject>;\n private requestToObject(options: { includeBody: false }): FetchRequestObject;\n private requestToObject(options: { includeBody: boolean }): PossiblePromise<FetchRequestObject>;\n private requestToObject(options: { includeBody: boolean }): PossiblePromise<FetchRequestObject> {\n const request = this.request;\n\n const requestObject: FetchRequestObject = {\n url: request.url,\n path: request.path,\n method: request.method,\n headers: this.convertHeadersToObject(request),\n cache: request.cache,\n destination: request.destination,\n credentials: request.credentials,\n integrity: request.integrity,\n keepalive: request.keepalive,\n mode: request.mode,\n redirect: request.redirect,\n referrer: request.referrer,\n referrerPolicy: request.referrerPolicy,\n };\n\n if (!options.includeBody) {\n return requestObject;\n }\n\n return this.withIncludedBodyIfAvailable('request', requestObject);\n }\n\n private responseToObject(options: { includeBody: true }): Promise<FetchResponseObject>;\n private responseToObject(options: { includeBody: false }): FetchResponseObject;\n private responseToObject(options: { includeBody: boolean }): PossiblePromise<FetchResponseObject>;\n private responseToObject(options: { includeBody: boolean }): PossiblePromise<FetchResponseObject> {\n const response = this.response;\n\n const responseObject: FetchResponseObject = {\n url: response.url,\n type: response.type,\n status: response.status,\n statusText: response.statusText,\n ok: response.ok,\n headers: this.convertHeadersToObject(response),\n redirected: response.redirected,\n };\n\n if (!options.includeBody) {\n return responseObject;\n }\n\n return this.withIncludedBodyIfAvailable('response', responseObject);\n }\n\n private convertHeadersToObject(\n resource: FetchRequest<Schema, Method, Path> | FetchResponse<Schema, Method, Path, true, 'manual'>,\n ): HttpHeadersSchema {\n return HttpHeaders.prototype.toObject.call(resource.headers) as HttpHeadersSchema;\n }\n\n private withIncludedBodyIfAvailable(\n resourceType: 'request',\n resourceObject: FetchRequestObject,\n ): PossiblePromise<FetchRequestObject>;\n private withIncludedBodyIfAvailable(\n resourceType: 'response',\n resourceObject: FetchResponseObject,\n ): PossiblePromise<FetchResponseObject>;\n private withIncludedBodyIfAvailable(\n resourceType: 'request' | 'response',\n resourceObject: FetchRequestObject | FetchResponseObject,\n ): PossiblePromise<FetchRequestObject | FetchResponseObject> {\n const resource = this[resourceType];\n\n if (resource.bodyUsed) {\n console.warn(\n `[@zimic/fetch] Could not include the ${resourceType} body because it is already used. ` +\n 'If you access the body before calling `error.toObject()`, consider reading it from a cloned ' +\n `${resourceType}.\\n\\nLearn more: https://zimic.dev/docs/fetch/api/fetch-response-error#errortoobject`,\n );\n return resourceObject;\n }\n\n return resource.text().then((body: string) => {\n resourceObject.body = body.length > 0 ? body : null;\n return resourceObject;\n });\n }\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type AnyFetchRequestError = FetchResponseError<any, any, any>;\n\nexport default FetchResponseError;\n","export function createPathCharactersToEscapeRegex() {\n return /([.(){}+$])/g;\n}\n\nexport function preparePathForRegex(path: string) {\n // We encode the path using the URL API because, differently from encodeURI and encodeURIComponent, URL does not\n // re-encode already encoded characters. Since URL requires a full URL, we use a data scheme and strip it later.\n const pathURLPrefix = `data:${path.startsWith('/') ? '' : '/'}`;\n const pathAsURL = new URL(`${pathURLPrefix}${path}`);\n const encodedPath = pathAsURL.href.replace(pathURLPrefix, '');\n\n return encodedPath.replace(/^\\/+/g, '').replace(/\\/+$/g, '').replace(createPathCharactersToEscapeRegex(), '\\\\$1');\n}\n\n// Path params names must match the JavaScript identifier pattern.\n// See // https://developer.mozilla.org/docs/Web/JavaScript/Reference/Lexical_grammar#identifiers.\nexport function createPathParamRegex() {\n return /(?<escape>\\\\)?:(?<identifier>[$_\\p{ID_Start}][$\\p{ID_Continue}]+)/gu;\n}\n\nexport function createRepeatingPathParamRegex() {\n return /(?<escape>\\\\)?:(?<identifier>[$_\\p{ID_Start}][$\\p{ID_Continue}]+)\\\\+/gu;\n}\n\nexport function createOptionalPathParamRegex() {\n return /(?<leadingSlash>\\/)?(?<escape>\\\\)?:(?<identifier>[$_\\p{ID_Start}][$\\p{ID_Continue}]+)\\?(?<trailingSlash>\\/)?/gu;\n}\n\nexport function createOptionalRepeatingPathParamRegex() {\n return /(?<leadingSlash>\\/)?(?<escape>\\\\)?:(?<identifier>[$_\\p{ID_Start}][$\\p{ID_Continue}]+)\\*(?<trailingSlash>\\/)?/gu;\n}\n\nfunction createRegexFromPath(path: string) {\n const pathRegexContent = preparePathForRegex(path)\n .replace(\n createOptionalRepeatingPathParamRegex(),\n (\n _match,\n leadingSlash: string | undefined,\n escape: string | undefined,\n identifier: string,\n trailingSlash: string | undefined,\n ) => {\n if (escape) {\n return `:${identifier}`;\n }\n\n const hasSegmentBeforePrefix = leadingSlash === '/';\n const prefixExpression = hasSegmentBeforePrefix ? '/?' : leadingSlash;\n\n const hasSegmentAfterSuffix = trailingSlash === '/';\n const suffixExpression = hasSegmentAfterSuffix ? '/?' : trailingSlash;\n\n if (prefixExpression && suffixExpression) {\n return `(?:${prefixExpression}(?<${identifier}>.+?)?${suffixExpression})?`;\n } else if (prefixExpression) {\n return `(?:${prefixExpression}(?<${identifier}>.+?))?`;\n } else if (suffixExpression) {\n return `(?:(?<${identifier}>.+?)${suffixExpression})?`;\n } else {\n return `(?<${identifier}>.+?)?`;\n }\n },\n )\n .replace(createRepeatingPathParamRegex(), (_match, escape: string | undefined, identifier: string) => {\n return escape ? `:${identifier}` : `(?<${identifier}>.+)`;\n })\n .replace(\n createOptionalPathParamRegex(),\n (\n _match,\n leadingSlash: string | undefined,\n escape: string | undefined,\n identifier: string,\n trailingSlash: string | undefined,\n ) => {\n if (escape) {\n return `:${identifier}`;\n }\n\n const hasSegmentBeforePrefix = leadingSlash === '/';\n const prefixExpression = hasSegmentBeforePrefix ? '/?' : leadingSlash;\n\n const hasSegmentAfterSuffix = trailingSlash === '/';\n const suffixExpression = hasSegmentAfterSuffix ? '/?' : trailingSlash;\n\n if (prefixExpression && suffixExpression) {\n return `(?:${prefixExpression}(?<${identifier}>[^\\\\/]+?)?${suffixExpression})`;\n } else if (prefixExpression) {\n return `(?:${prefixExpression}(?<${identifier}>[^\\\\/]+?))?`;\n } else if (suffixExpression) {\n return `(?:(?<${identifier}>[^\\\\/]+?)${suffixExpression})?`;\n } else {\n return `(?<${identifier}>[^\\\\/]+?)?`;\n }\n },\n )\n .replace(createPathParamRegex(), (_match, escape: string | undefined, identifier: string) => {\n return escape ? `:${identifier}` : `(?<${identifier}>[^\\\\/]+?)`;\n });\n\n return new RegExp(`^/?${pathRegexContent}/?$`);\n}\n\nexport default createRegexFromPath;\n","function excludeURLParams(url: URL) {\n url.hash = '';\n url.search = '';\n url.username = '';\n url.password = '';\n return url;\n}\n\nexport default excludeURLParams;\n","function joinURL(...parts: (URL | string)[]) {\n return parts\n .map((part, index) => {\n const isFirstPart = index === 0;\n const isLastPart = index === parts.length - 1;\n\n let partAsString = part.toString();\n\n if (!isFirstPart) {\n partAsString = partAsString.replace(/^\\//, '');\n }\n if (!isLastPart) {\n partAsString = partAsString.replace(/\\/$/, '');\n }\n\n return partAsString;\n })\n .filter((part) => part.length > 0)\n .join('/');\n}\n\nexport default joinURL;\n","import {\n HttpSchemaPath,\n HttpSchemaMethod,\n HttpSearchParams,\n LiteralHttpSchemaPathFromNonLiteral,\n HttpSchema,\n HttpHeaders,\n} from '@zimic/http';\nimport createRegexFromPath from '@zimic/utils/url/createRegexFromPath';\nimport excludeURLParams from '@zimic/utils/url/excludeURLParams';\nimport joinURL from '@zimic/utils/url/joinURL';\n\nimport FetchResponseError from './errors/FetchResponseError';\nimport { FetchInput, FetchOptions, Fetch, FetchDefaults } from './types/public';\nimport { FetchRequestConstructor, FetchRequestInit, FetchRequest, FetchResponse } from './types/requests';\n\nclass FetchClient<Schema extends HttpSchema> implements Omit<Fetch<Schema>, 'defaults' | 'loose' | 'Request'> {\n fetch: Fetch<Schema>;\n\n constructor({ onRequest, onResponse, ...defaults }: FetchOptions<Schema>) {\n this.fetch = this.createFetchFunction();\n\n this.fetch.defaults = {\n ...defaults,\n headers: defaults.headers ?? {},\n searchParams: defaults.searchParams ?? {},\n };\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n this.fetch.loose = this.fetch as Fetch<any> as Fetch.Loose;\n\n this.fetch.Request = this.createRequestClass(this.fetch.defaults);\n this.fetch.onRequest = onRequest;\n this.fetch.onResponse = onResponse;\n }\n\n private createFetchFunction() {\n const fetch = async <\n Method extends HttpSchemaMethod<Schema>,\n Path extends HttpSchemaPath.NonLiteral<Schema, Method>,\n >(\n input: FetchInput<Schema, Method, Path>,\n init: FetchRequestInit<Schema, Method, LiteralHttpSchemaPathFromNonLiteral<Schema, Method, Path>>,\n ) => {\n const request = await this.createFetchRequest<Method, Path>(input, init);\n const requestClone = request.clone();\n\n const rawResponse = await globalThis.fetch(\n // Optimize type checking by narrowing the type of request\n requestClone as Request,\n );\n const response = await this.createFetchResponse<\n Method,\n LiteralHttpSchemaPathFromNonLiteral<Schema, Method, Path>\n >(request, rawResponse);\n\n return response;\n };\n\n Object.setPrototypeOf(fetch, this);\n\n return fetch as Fetch<Schema>;\n }\n\n private async createFetchRequest<\n Method extends HttpSchemaMethod<Schema>,\n Path extends HttpSchemaPath.NonLiteral<Schema, Method>,\n >(\n input: FetchInput<Schema, Method, Path>,\n init: FetchRequestInit<Schema, Method, LiteralHttpSchemaPathFromNonLiteral<Schema, Method, Path>>,\n ) {\n let request = input instanceof Request ? input : new this.fetch.Request(input, init);\n\n if (this.fetch.onRequest) {\n const requestAfterInterceptor = await this.fetch.onRequest(\n // Optimize type checking by narrowing the type of request\n request as FetchRequest.Loose,\n );\n\n if (requestAfterInterceptor !== request) {\n const isFetchRequest = requestAfterInterceptor instanceof this.fetch.Request;\n\n request = isFetchRequest\n ? (requestAfterInterceptor as Request as typeof request)\n : new this.fetch.Request(requestAfterInterceptor as FetchInput<Schema, Method, Path>, init);\n }\n }\n\n return request;\n }\n\n private async createFetchResponse<\n Method extends HttpSchemaMethod<Schema>,\n Path extends HttpSchemaPath.Literal<Schema, Method>,\n >(fetchRequest: FetchRequest<Schema, Method, Path>, rawResponse: Response) {\n let response = this.defineFetchResponseProperties<Method, Path>(fetchRequest, rawResponse);\n\n if (this.fetch.onResponse) {\n const responseAfterInterceptor = await this.fetch.onResponse(\n // Optimize type checking by narrowing the type of response\n response as FetchResponse.Loose,\n );\n\n const isFetchResponse =\n responseAfterInterceptor instanceof Response &&\n 'request' in responseAfterInterceptor &&\n responseAfterInterceptor.request instanceof this.fetch.Request;\n\n response = isFetchResponse\n ? (responseAfterInterceptor as typeof response)\n : this.defineFetchResponseProperties<Method, Path>(fetchRequest, responseAfterInterceptor);\n }\n\n return response;\n }\n\n private defineFetchResponseProperties<\n Method extends HttpSchemaMethod<Schema>,\n Path extends HttpSchemaPath.Literal<Schema, Method>,\n >(fetchRequest: FetchRequest<Schema, Method, Path>, response: Response) {\n const fetchResponse = response as FetchResponse<Schema, Method, Path>;\n\n Object.defineProperty(fetchResponse, 'request', {\n value: fetchRequest,\n writable: false,\n enumerable: true,\n configurable: false,\n });\n\n let responseError: FetchResponse.Loose['error'] | undefined;\n\n Object.defineProperty(fetchResponse, 'error', {\n get() {\n if (responseError === undefined) {\n responseError = fetchResponse.ok\n ? null\n : new FetchResponseError(\n fetchRequest,\n fetchResponse as FetchResponse<Schema, Method, Path, true, 'manual'>,\n );\n }\n return responseError;\n },\n enumerable: true,\n configurable: false,\n });\n\n return fetchResponse;\n }\n\n private createRequestClass(defaults: FetchDefaults) {\n class Request<\n Method extends HttpSchemaMethod<Schema>,\n Path extends HttpSchemaPath.NonLiteral<Schema, Method>,\n > extends globalThis.Request {\n path: LiteralHttpSchemaPathFromNonLiteral<Schema, Method, Path>;\n\n constructor(\n input: FetchInput<Schema, Method, Path>,\n init: FetchRequestInit<Schema, Method, LiteralHttpSchemaPathFromNonLiteral<Schema, Method, Path>>,\n ) {\n const initWithDefaults = { ...defaults, ...init };\n\n const headersFromDefaults = new HttpHeaders(defaults.headers);\n const headersFromInit = new HttpHeaders((init satisfies RequestInit as RequestInit).headers);\n\n let url: URL;\n const baseURL = new URL(initWithDefaults.baseURL);\n\n if (input instanceof globalThis.Request) {\n // Optimize type checking by narrowing the type of input\n const request = input as globalThis.Request;\n\n // Optimize type checking by narrowing the type of headers\n const headersFromRequest = new HttpHeaders(input.headers as Headers);\n\n initWithDefaults.headers = {\n ...headersFromDefaults.toObject(),\n ...headersFromRequest.toObject(),\n ...headersFromInit.toObject(),\n };\n\n super(request, initWithDefaults);\n\n url = new URL(input.url);\n } else {\n initWithDefaults.headers = {\n ...headersFromDefaults.toObject(),\n ...headersFromInit.toObject(),\n };\n\n url = input instanceof URL ? new URL(input) : new URL(joinURL(baseURL, input));\n\n const searchParamsFromDefaults = new HttpSearchParams(defaults.searchParams);\n const searchParamsFromInit = new HttpSearchParams(initWithDefaults.searchParams);\n\n initWithDefaults.searchParams = {\n ...searchParamsFromDefaults.toObject(),\n ...searchParamsFromInit.toObject(),\n };\n\n url.search = new HttpSearchParams(initWithDefaults.searchParams).toString();\n\n super(url, initWithDefaults);\n }\n\n const baseURLWithoutTrailingSlash = baseURL.toString().replace(/\\/$/, '');\n\n this.path = excludeURLParams(url)\n .toString()\n .replace(baseURLWithoutTrailingSlash, '') as LiteralHttpSchemaPathFromNonLiteral<Schema, Method, Path>;\n }\n\n clone(): Request<Method, Path> {\n const rawClone = super.clone();\n\n return new Request<Method, Path>(\n rawClone as unknown as FetchInput<Schema, Method, Path>,\n rawClone as unknown as FetchRequestInit<\n Schema,\n Method,\n LiteralHttpSchemaPathFromNonLiteral<Schema, Method, Path>\n >,\n );\n }\n }\n\n return Request as FetchRequestConstructor<Schema>;\n }\n\n isRequest<Path extends HttpSchemaPath.Literal<Schema, Method>, Method extends HttpSchemaMethod<Schema>>(\n request: unknown,\n method: Method,\n path: Path,\n ): request is FetchRequest<Schema, Method, Path> {\n return (\n request instanceof Request &&\n request.method === method &&\n 'path' in request &&\n typeof request.path === 'string' &&\n createRegexFromPath(path).test(request.path)\n );\n }\n\n isResponse<Path extends HttpSchemaPath.Literal<Schema, Method>, Method extends HttpSchemaMethod<Schema>>(\n response: unknown,\n method: Method,\n path: Path,\n ): response is FetchResponse<Schema, Method, Path> {\n return (\n response instanceof Response &&\n 'request' in response &&\n this.isRequest(response.request, method, path) &&\n 'error' in response &&\n (response.error === null || response.error instanceof FetchResponseError)\n );\n }\n\n isResponseError<Path extends HttpSchemaPath.Literal<Schema, Method>, Method extends HttpSchemaMethod<Schema>>(\n error: unknown,\n method: Method,\n path: Path,\n ): error is FetchResponseError<Schema, Method, Path> {\n return (\n error instanceof FetchResponseError &&\n this.isRequest(error.request, method, path) &&\n this.isResponse(error.response, method, path)\n );\n }\n}\n\nexport default FetchClient;\n","import { HttpSchema } from '@zimic/http';\n\nimport FetchClient from './FetchClient';\nimport { FetchOptions, Fetch } from './types/public';\n\n/** @see {@link https://zimic.dev/docs/fetch/api/create-fetch `createFetch` API reference} */\nfunction createFetch<Schema extends HttpSchema>(options: FetchOptions<Schema>): Fetch<Schema> {\n const { fetch } = new FetchClient<Schema>(options);\n return fetch;\n}\n\nexport default createFetch;\n"]}
1
+ {"version":3,"sources":["../src/client/errors/FetchResponseError.ts","../../zimic-utils/src/url/createRegexFromPath.ts","../../zimic-utils/src/url/excludeNonPathParams.ts","../../zimic-utils/src/url/joinURL.ts","../src/client/FetchClient.ts","../src/client/factory.ts"],"names":["Request","HttpHeaders"],"mappings":"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","file":"index.mjs","sourcesContent":["import {\n HttpHeaders,\n HttpHeadersSchema,\n HttpSchema,\n HttpSchemaMethod,\n HttpSchemaPath,\n parseHttpBody,\n} from '@zimic/http';\nimport { PossiblePromise } from '@zimic/utils/types';\n\nimport { FetchRequest, FetchRequestObject, FetchResponse, FetchResponseObject } from '../types/requests';\n\n/** @see {@link https://zimic.dev/docs/fetch/api/fetch-response-error#errortoobject `fetchResponseError.toObject()` API reference} */\nexport interface FetchResponseErrorObjectOptions {\n /** @see {@link https://zimic.dev/docs/fetch/api/fetch-response-error#errortoobject `fetchResponseError.toObject()` API reference} */\n includeRequestBody?: boolean;\n /** @see {@link https://zimic.dev/docs/fetch/api/fetch-response-error#errortoobject `fetchResponseError.toObject()` API reference} */\n includeResponseBody?: boolean;\n}\n\nexport namespace FetchResponseErrorObjectOptions {\n /**\n * Options for converting a {@link FetchResponseError `FetchResponseError`} into a plain object, including the body of\n * the request and/or response.\n */\n export type WithBody = FetchResponseErrorObjectOptions &\n ({ includeRequestBody: true } | { includeResponseBody: true });\n\n /**\n * Options for converting a {@link FetchResponseError `FetchResponseError`} into a plain object, excluding the body of\n * the request and/or response.\n */\n export type WithoutBody = FetchResponseErrorObjectOptions &\n ({ includeRequestBody?: false } | { includeResponseBody?: false });\n}\n\n/**\n * A plain object representation of a {@link FetchResponseError `FetchResponseError`}, compatible with JSON. It is useful\n * for serialization, debugging, and logging purposes.\n *\n * @see {@link https://zimic.dev/docs/fetch/api/fetch-response-error#errortoobject `fetchResponseError.toObject()` API reference}\n */\nexport interface FetchResponseErrorObject {\n name: string;\n message: string;\n request: FetchRequestObject;\n response: FetchResponseObject;\n}\n\n/** @see {@link https://zimic.dev/docs/fetch/api/fetch-response-error `FetchResponseError` API reference} */\nclass FetchResponseError<\n Schema extends HttpSchema,\n Method extends HttpSchemaMethod<Schema>,\n Path extends HttpSchemaPath.Literal<Schema, Method>,\n> extends Error {\n constructor(\n public request: FetchRequest<Schema, Method, Path>,\n public response: FetchResponse<Schema, Method, Path, true, 'manual'>,\n ) {\n super(`${request.method} ${request.url} failed with status ${response.status}: ${response.statusText}`);\n this.name = 'FetchResponseError';\n }\n\n /** @see {@link https://zimic.dev/docs/fetch/api/fetch-response-error#errortoobject `fetchResponseError.toObject()` API reference} */\n toObject(options: FetchResponseErrorObjectOptions.WithBody): Promise<FetchResponseErrorObject>;\n toObject(options?: FetchResponseErrorObjectOptions.WithoutBody): FetchResponseErrorObject;\n toObject(options?: FetchResponseErrorObjectOptions): PossiblePromise<FetchResponseErrorObject>;\n toObject({\n includeRequestBody = false,\n includeResponseBody = false,\n }: FetchResponseErrorObjectOptions = {}): PossiblePromise<FetchResponseErrorObject> {\n const partialObject = {\n name: this.name,\n message: this.message,\n } satisfies Partial<FetchResponseErrorObject>;\n\n if (!includeRequestBody && !includeResponseBody) {\n return {\n ...partialObject,\n request: this.requestToObject({ includeBody: false }),\n response: this.responseToObject({ includeBody: false }),\n };\n }\n\n return Promise.all([\n Promise.resolve(this.requestToObject({ includeBody: includeRequestBody })),\n Promise.resolve(this.responseToObject({ includeBody: includeResponseBody })),\n ]).then(([request, response]) => ({ ...partialObject, request, response }));\n }\n\n private requestToObject(options: { includeBody: true }): Promise<FetchRequestObject>;\n private requestToObject(options: { includeBody: false }): FetchRequestObject;\n private requestToObject(options: { includeBody: boolean }): PossiblePromise<FetchRequestObject>;\n private requestToObject(options: { includeBody: boolean }): PossiblePromise<FetchRequestObject> {\n const request = this.request;\n\n const requestObject: FetchRequestObject = {\n url: request.url,\n path: request.path,\n method: request.method,\n headers: this.convertHeadersToObject(request),\n cache: request.cache,\n destination: request.destination,\n credentials: request.credentials,\n integrity: request.integrity,\n keepalive: request.keepalive,\n mode: request.mode,\n redirect: request.redirect,\n referrer: request.referrer,\n referrerPolicy: request.referrerPolicy,\n };\n\n if (!options.includeBody) {\n return requestObject;\n }\n\n return this.withIncludedBodyIfAvailable('request', requestObject);\n }\n\n private responseToObject(options: { includeBody: true }): Promise<FetchResponseObject>;\n private responseToObject(options: { includeBody: false }): FetchResponseObject;\n private responseToObject(options: { includeBody: boolean }): PossiblePromise<FetchResponseObject>;\n private responseToObject(options: { includeBody: boolean }): PossiblePromise<FetchResponseObject> {\n const response = this.response;\n\n const responseObject: FetchResponseObject = {\n url: response.url,\n type: response.type,\n status: response.status,\n statusText: response.statusText,\n ok: response.ok,\n headers: this.convertHeadersToObject(response),\n redirected: response.redirected,\n };\n\n if (!options.includeBody) {\n return responseObject;\n }\n\n return this.withIncludedBodyIfAvailable('response', responseObject);\n }\n\n private convertHeadersToObject(\n resource: FetchRequest<Schema, Method, Path> | FetchResponse<Schema, Method, Path, true, 'manual'>,\n ): HttpHeadersSchema {\n return HttpHeaders.prototype.toObject.call(resource.headers) as HttpHeadersSchema;\n }\n\n private withIncludedBodyIfAvailable(\n resourceType: 'request',\n resourceObject: FetchRequestObject,\n ): PossiblePromise<FetchRequestObject>;\n private withIncludedBodyIfAvailable(\n resourceType: 'response',\n resourceObject: FetchResponseObject,\n ): PossiblePromise<FetchResponseObject>;\n private withIncludedBodyIfAvailable(\n resourceType: 'request' | 'response',\n resourceObject: FetchRequestObject | FetchResponseObject,\n ): PossiblePromise<FetchRequestObject | FetchResponseObject> {\n const resource = this[resourceType] as Request | Response;\n\n if (resource.bodyUsed) {\n console.warn(\n '[@zimic/fetch]',\n `Could not include the ${resourceType} body because it is already used. ` +\n 'If you access the body before calling `error.toObject()`, consider reading it from a cloned ' +\n `${resourceType}.\\n\\nLearn more: https://zimic.dev/docs/fetch/api/fetch-response-error#errortoobject`,\n );\n return resourceObject;\n }\n\n return parseHttpBody(resource)\n .then((body) => {\n resourceObject.body = body;\n return resourceObject;\n })\n .catch((error: unknown) => {\n console.error('[@zimic/fetch]', `Failed to parse ${resourceType} body:`, error);\n return resourceObject;\n });\n }\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type AnyFetchRequestError = FetchResponseError<any, any, any>;\n\nexport default FetchResponseError;\n","export function createPathCharactersToEscapeRegex() {\n return /([.(){}+$])/g;\n}\n\nexport function preparePathForRegex(path: string) {\n // We encode the path using the URL API because, differently from encodeURI and encodeURIComponent, URL does not\n // re-encode already encoded characters. Since URL requires a full URL, we use a data scheme and strip it later.\n const pathURLPrefix = `data:${path.startsWith('/') ? '' : '/'}`;\n const pathAsURL = new URL(`${pathURLPrefix}${path}`);\n const encodedPath = pathAsURL.href.replace(pathURLPrefix, '');\n\n return encodedPath.replace(/^\\/+/g, '').replace(/\\/+$/g, '').replace(createPathCharactersToEscapeRegex(), '\\\\$1');\n}\n\n// Path params names must match the JavaScript identifier pattern.\n// See // https://developer.mozilla.org/docs/Web/JavaScript/Reference/Lexical_grammar#identifiers.\nexport function createPathParamRegex() {\n return /(?<escape>\\\\)?:(?<identifier>[$_\\p{ID_Start}][$\\p{ID_Continue}]+)/gu;\n}\n\nexport function createRepeatingPathParamRegex() {\n return /(?<escape>\\\\)?:(?<identifier>[$_\\p{ID_Start}][$\\p{ID_Continue}]+)\\\\+/gu;\n}\n\nexport function createOptionalPathParamRegex() {\n return /(?<leadingSlash>\\/)?(?<escape>\\\\)?:(?<identifier>[$_\\p{ID_Start}][$\\p{ID_Continue}]+)\\?(?<trailingSlash>\\/)?/gu;\n}\n\nexport function createOptionalRepeatingPathParamRegex() {\n return /(?<leadingSlash>\\/)?(?<escape>\\\\)?:(?<identifier>[$_\\p{ID_Start}][$\\p{ID_Continue}]+)\\*(?<trailingSlash>\\/)?/gu;\n}\n\nfunction createRegexFromPath(path: string) {\n const pathRegexContent = preparePathForRegex(path)\n .replace(\n createOptionalRepeatingPathParamRegex(),\n (\n _match,\n leadingSlash: string | undefined,\n escape: string | undefined,\n identifier: string,\n trailingSlash: string | undefined,\n ) => {\n if (escape) {\n return `:${identifier}`;\n }\n\n const hasSegmentBeforePrefix = leadingSlash === '/';\n const prefixExpression = hasSegmentBeforePrefix ? '/?' : leadingSlash;\n\n const hasSegmentAfterSuffix = trailingSlash === '/';\n const suffixExpression = hasSegmentAfterSuffix ? '/?' : trailingSlash;\n\n if (prefixExpression && suffixExpression) {\n return `(?:${prefixExpression}(?<${identifier}>.+?)?${suffixExpression})?`;\n } else if (prefixExpression) {\n return `(?:${prefixExpression}(?<${identifier}>.+?))?`;\n } else if (suffixExpression) {\n return `(?:(?<${identifier}>.+?)${suffixExpression})?`;\n } else {\n return `(?<${identifier}>.+?)?`;\n }\n },\n )\n .replace(createRepeatingPathParamRegex(), (_match, escape: string | undefined, identifier: string) => {\n return escape ? `:${identifier}` : `(?<${identifier}>.+)`;\n })\n .replace(\n createOptionalPathParamRegex(),\n (\n _match,\n leadingSlash: string | undefined,\n escape: string | undefined,\n identifier: string,\n trailingSlash: string | undefined,\n ) => {\n if (escape) {\n return `:${identifier}`;\n }\n\n const hasSegmentBeforePrefix = leadingSlash === '/';\n const prefixExpression = hasSegmentBeforePrefix ? '/?' : leadingSlash;\n\n const hasSegmentAfterSuffix = trailingSlash === '/';\n const suffixExpression = hasSegmentAfterSuffix ? '/?' : trailingSlash;\n\n if (prefixExpression && suffixExpression) {\n return `(?:${prefixExpression}(?<${identifier}>[^\\\\/]+?)?${suffixExpression})`;\n } else if (prefixExpression) {\n return `(?:${prefixExpression}(?<${identifier}>[^\\\\/]+?))?`;\n } else if (suffixExpression) {\n return `(?:(?<${identifier}>[^\\\\/]+?)${suffixExpression})?`;\n } else {\n return `(?<${identifier}>[^\\\\/]+?)?`;\n }\n },\n )\n .replace(createPathParamRegex(), (_match, escape: string | undefined, identifier: string) => {\n return escape ? `:${identifier}` : `(?<${identifier}>[^\\\\/]+?)`;\n });\n\n return new RegExp(`^/?${pathRegexContent}/?$`);\n}\n\nexport default createRegexFromPath;\n","function excludeNonPathParams(url: URL) {\n url.hash = '';\n url.search = '';\n url.username = '';\n url.password = '';\n return url;\n}\n\nexport default excludeNonPathParams;\n","function joinURL(...parts: (URL | string)[]) {\n return parts\n .map((part, index) => {\n const isFirstPart = index === 0;\n const isLastPart = index === parts.length - 1;\n\n let partAsString = part.toString();\n\n if (!isFirstPart) {\n partAsString = partAsString.replace(/^\\//, '');\n }\n if (!isLastPart) {\n partAsString = partAsString.replace(/\\/$/, '');\n }\n\n return partAsString;\n })\n .filter((part) => part.length > 0)\n .join('/');\n}\n\nexport default joinURL;\n","import {\n HttpSchemaPath,\n HttpSchemaMethod,\n HttpSearchParams,\n LiteralHttpSchemaPathFromNonLiteral,\n HttpSchema,\n HttpHeaders,\n} from '@zimic/http';\nimport createRegexFromPath from '@zimic/utils/url/createRegexFromPath';\nimport excludeNonPathParams from '@zimic/utils/url/excludeNonPathParams';\nimport joinURL from '@zimic/utils/url/joinURL';\n\nimport FetchResponseError from './errors/FetchResponseError';\nimport { FetchInput, FetchOptions, Fetch, FetchDefaults } from './types/public';\nimport { FetchRequestConstructor, FetchRequestInit, FetchRequest, FetchResponse } from './types/requests';\n\nclass FetchClient<Schema extends HttpSchema> implements Omit<Fetch<Schema>, 'defaults' | 'loose' | 'Request'> {\n fetch: Fetch<Schema>;\n\n constructor({ onRequest, onResponse, ...defaults }: FetchOptions<Schema>) {\n this.fetch = this.createFetchFunction();\n\n this.fetch.defaults = {\n ...defaults,\n headers: defaults.headers ?? {},\n searchParams: defaults.searchParams ?? {},\n };\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n this.fetch.loose = this.fetch as Fetch<any> as Fetch.Loose;\n\n this.fetch.Request = this.createRequestClass(this.fetch.defaults);\n this.fetch.onRequest = onRequest;\n this.fetch.onResponse = onResponse;\n }\n\n private createFetchFunction() {\n const fetch = async <\n Method extends HttpSchemaMethod<Schema>,\n Path extends HttpSchemaPath.NonLiteral<Schema, Method>,\n >(\n input: FetchInput<Schema, Method, Path>,\n init: FetchRequestInit<Schema, Method, LiteralHttpSchemaPathFromNonLiteral<Schema, Method, Path>>,\n ) => {\n const request = await this.createFetchRequest<Method, Path>(input, init);\n const requestClone = request.clone();\n\n const rawResponse = await globalThis.fetch(\n // Optimize type checking by narrowing the type of request\n requestClone as Request,\n );\n const response = await this.createFetchResponse<\n Method,\n LiteralHttpSchemaPathFromNonLiteral<Schema, Method, Path>\n >(request, rawResponse);\n\n return response;\n };\n\n Object.setPrototypeOf(fetch, this);\n\n return fetch as Fetch<Schema>;\n }\n\n private async createFetchRequest<\n Method extends HttpSchemaMethod<Schema>,\n Path extends HttpSchemaPath.NonLiteral<Schema, Method>,\n >(\n input: FetchInput<Schema, Method, Path>,\n init: FetchRequestInit<Schema, Method, LiteralHttpSchemaPathFromNonLiteral<Schema, Method, Path>>,\n ) {\n let request = input instanceof Request ? input : new this.fetch.Request(input, init);\n\n if (this.fetch.onRequest) {\n const requestAfterInterceptor = await this.fetch.onRequest(\n // Optimize type checking by narrowing the type of request\n request as FetchRequest.Loose,\n );\n\n if (requestAfterInterceptor !== request) {\n const isFetchRequest = requestAfterInterceptor instanceof this.fetch.Request;\n\n request = isFetchRequest\n ? (requestAfterInterceptor as Request as typeof request)\n : new this.fetch.Request(requestAfterInterceptor as FetchInput<Schema, Method, Path>, init);\n }\n }\n\n return request;\n }\n\n private async createFetchResponse<\n Method extends HttpSchemaMethod<Schema>,\n Path extends HttpSchemaPath.Literal<Schema, Method>,\n >(fetchRequest: FetchRequest<Schema, Method, Path>, rawResponse: Response) {\n let response = this.defineFetchResponseProperties<Method, Path>(fetchRequest, rawResponse);\n\n if (this.fetch.onResponse) {\n const responseAfterInterceptor = await this.fetch.onResponse(\n // Optimize type checking by narrowing the type of response\n response as FetchResponse.Loose,\n );\n\n const isFetchResponse =\n responseAfterInterceptor instanceof Response &&\n 'request' in responseAfterInterceptor &&\n responseAfterInterceptor.request instanceof this.fetch.Request;\n\n response = isFetchResponse\n ? (responseAfterInterceptor as typeof response)\n : this.defineFetchResponseProperties<Method, Path>(fetchRequest, responseAfterInterceptor);\n }\n\n return response;\n }\n\n private defineFetchResponseProperties<\n Method extends HttpSchemaMethod<Schema>,\n Path extends HttpSchemaPath.Literal<Schema, Method>,\n >(fetchRequest: FetchRequest<Schema, Method, Path>, response: Response) {\n const fetchResponse = response as FetchResponse<Schema, Method, Path>;\n\n Object.defineProperty(fetchResponse, 'request', {\n value: fetchRequest,\n writable: false,\n enumerable: true,\n configurable: false,\n });\n\n let responseError: FetchResponse.Loose['error'] | undefined;\n\n Object.defineProperty(fetchResponse, 'error', {\n get() {\n if (responseError === undefined) {\n responseError = fetchResponse.ok\n ? null\n : new FetchResponseError(\n fetchRequest,\n fetchResponse as FetchResponse<Schema, Method, Path, true, 'manual'>,\n );\n }\n return responseError;\n },\n enumerable: true,\n configurable: false,\n });\n\n return fetchResponse;\n }\n\n private createRequestClass(defaults: FetchDefaults) {\n class Request<\n Method extends HttpSchemaMethod<Schema>,\n Path extends HttpSchemaPath.NonLiteral<Schema, Method>,\n > extends globalThis.Request {\n path: LiteralHttpSchemaPathFromNonLiteral<Schema, Method, Path>;\n\n constructor(\n input: FetchInput<Schema, Method, Path>,\n init: FetchRequestInit<Schema, Method, LiteralHttpSchemaPathFromNonLiteral<Schema, Method, Path>>,\n ) {\n const initWithDefaults = { ...defaults, ...init };\n\n const headersFromDefaults = new HttpHeaders(defaults.headers);\n const headersFromInit = new HttpHeaders((init satisfies RequestInit as RequestInit).headers);\n\n let url: URL;\n const baseURL = new URL(initWithDefaults.baseURL);\n\n if (input instanceof globalThis.Request) {\n // Optimize type checking by narrowing the type of input\n const request = input as globalThis.Request;\n\n // Optimize type checking by narrowing the type of headers\n const headersFromRequest = new HttpHeaders(input.headers as Headers);\n\n initWithDefaults.headers = {\n ...headersFromDefaults.toObject(),\n ...headersFromRequest.toObject(),\n ...headersFromInit.toObject(),\n };\n\n super(request, initWithDefaults);\n\n url = new URL(input.url);\n } else {\n initWithDefaults.headers = {\n ...headersFromDefaults.toObject(),\n ...headersFromInit.toObject(),\n };\n\n url = input instanceof URL ? new URL(input) : new URL(joinURL(baseURL, input));\n\n const searchParamsFromDefaults = new HttpSearchParams(defaults.searchParams);\n const searchParamsFromInit = new HttpSearchParams(initWithDefaults.searchParams);\n\n initWithDefaults.searchParams = {\n ...searchParamsFromDefaults.toObject(),\n ...searchParamsFromInit.toObject(),\n };\n\n url.search = new HttpSearchParams(initWithDefaults.searchParams).toString();\n\n super(url, initWithDefaults);\n }\n\n const baseURLWithoutTrailingSlash = baseURL.toString().replace(/\\/$/, '');\n\n this.path = excludeNonPathParams(url)\n .toString()\n .replace(baseURLWithoutTrailingSlash, '') as LiteralHttpSchemaPathFromNonLiteral<Schema, Method, Path>;\n }\n\n clone(): Request<Method, Path> {\n const rawClone = super.clone();\n\n return new Request<Method, Path>(\n rawClone as unknown as FetchInput<Schema, Method, Path>,\n rawClone as unknown as FetchRequestInit<\n Schema,\n Method,\n LiteralHttpSchemaPathFromNonLiteral<Schema, Method, Path>\n >,\n );\n }\n }\n\n return Request as FetchRequestConstructor<Schema>;\n }\n\n isRequest<Path extends HttpSchemaPath.Literal<Schema, Method>, Method extends HttpSchemaMethod<Schema>>(\n request: unknown,\n method: Method,\n path: Path,\n ): request is FetchRequest<Schema, Method, Path> {\n return (\n request instanceof Request &&\n request.method === method &&\n 'path' in request &&\n typeof request.path === 'string' &&\n createRegexFromPath(path).test(request.path)\n );\n }\n\n isResponse<Path extends HttpSchemaPath.Literal<Schema, Method>, Method extends HttpSchemaMethod<Schema>>(\n response: unknown,\n method: Method,\n path: Path,\n ): response is FetchResponse<Schema, Method, Path> {\n return (\n response instanceof Response &&\n 'request' in response &&\n this.isRequest(response.request, method, path) &&\n 'error' in response &&\n (response.error === null || response.error instanceof FetchResponseError)\n );\n }\n\n isResponseError<Path extends HttpSchemaPath.Literal<Schema, Method>, Method extends HttpSchemaMethod<Schema>>(\n error: unknown,\n method: Method,\n path: Path,\n ): error is FetchResponseError<Schema, Method, Path> {\n return (\n error instanceof FetchResponseError &&\n this.isRequest(error.request, method, path) &&\n this.isResponse(error.response, method, path)\n );\n }\n}\n\nexport default FetchClient;\n","import { HttpSchema } from '@zimic/http';\n\nimport FetchClient from './FetchClient';\nimport { FetchOptions, Fetch } from './types/public';\n\n/** @see {@link https://zimic.dev/docs/fetch/api/create-fetch `createFetch` API reference} */\nfunction createFetch<Schema extends HttpSchema>(options: FetchOptions<Schema>): Fetch<Schema> {\n const { fetch } = new FetchClient<Schema>(options);\n return fetch;\n}\n\nexport default createFetch;\n"]}
package/package.json CHANGED
@@ -13,7 +13,7 @@
13
13
  "api",
14
14
  "static"
15
15
  ],
16
- "version": "1.0.7-canary.2",
16
+ "version": "1.1.0-canary.0",
17
17
  "homepage": "https://zimic.dev/docs/fetch",
18
18
  "repository": {
19
19
  "type": "git",
@@ -67,19 +67,20 @@
67
67
  "@vitest/coverage-istanbul": "^3.2.4",
68
68
  "dotenv-cli": "^10.0.0",
69
69
  "eslint": "^9.36.0",
70
+ "picocolors": "^1.1.1",
70
71
  "playwright": "^1.55.1",
71
72
  "tsup": "^8.4.0",
72
73
  "typescript": "^5.9.2",
73
74
  "vitest": "^3.2.4",
74
75
  "@zimic/eslint-config-node": "0.0.0",
75
- "@zimic/interceptor": "1.1.2-canary.6",
76
- "@zimic/lint-staged-config": "0.0.0",
76
+ "@zimic/interceptor": "1.1.3-canary.0",
77
77
  "@zimic/tsconfig": "0.0.0",
78
+ "@zimic/lint-staged-config": "0.0.0",
78
79
  "@zimic/utils": "0.0.0"
79
80
  },
80
81
  "peerDependencies": {
81
82
  "typescript": ">=5.0.0",
82
- "@zimic/http": "^1.1.0 || 1.1.2-canary.6"
83
+ "@zimic/http": "^1.1.0 || 1.2.0-canary.0"
83
84
  },
84
85
  "peerDependenciesMeta": {
85
86
  "typescript": {
@@ -94,7 +95,7 @@
94
95
  "style": "prettier --log-level warn --ignore-unknown --no-error-on-unmatched-pattern --cache",
95
96
  "style:check": "pnpm style --check",
96
97
  "style:format": "pnpm style --write",
97
- "test": "dotenv -v NODE_ENV=test -- vitest",
98
+ "test": "dotenv -v NODE_ENV=test -v FORCE_COLOR=1 -- vitest",
98
99
  "test:turbo": "dotenv -v CI=true -- pnpm run test run --coverage",
99
100
  "types:check": "tsc --noEmit",
100
101
  "deps:prepare": "playwright install chromium"
@@ -7,7 +7,7 @@ import {
7
7
  HttpHeaders,
8
8
  } from '@zimic/http';
9
9
  import createRegexFromPath from '@zimic/utils/url/createRegexFromPath';
10
- import excludeURLParams from '@zimic/utils/url/excludeURLParams';
10
+ import excludeNonPathParams from '@zimic/utils/url/excludeNonPathParams';
11
11
  import joinURL from '@zimic/utils/url/joinURL';
12
12
 
13
13
  import FetchResponseError from './errors/FetchResponseError';
@@ -206,7 +206,7 @@ class FetchClient<Schema extends HttpSchema> implements Omit<Fetch<Schema>, 'def
206
206
 
207
207
  const baseURLWithoutTrailingSlash = baseURL.toString().replace(/\/$/, '');
208
208
 
209
- this.path = excludeURLParams(url)
209
+ this.path = excludeNonPathParams(url)
210
210
  .toString()
211
211
  .replace(baseURLWithoutTrailingSlash, '') as LiteralHttpSchemaPathFromNonLiteral<Schema, Method, Path>;
212
212
  }
@@ -1,4 +1,11 @@
1
- import { HttpHeaders, HttpHeadersSchema, HttpSchema, HttpSchemaMethod, HttpSchemaPath } from '@zimic/http';
1
+ import {
2
+ HttpHeaders,
3
+ HttpHeadersSchema,
4
+ HttpSchema,
5
+ HttpSchemaMethod,
6
+ HttpSchemaPath,
7
+ parseHttpBody,
8
+ } from '@zimic/http';
2
9
  import { PossiblePromise } from '@zimic/utils/types';
3
10
 
4
11
  import { FetchRequest, FetchRequestObject, FetchResponse, FetchResponseObject } from '../types/requests';
@@ -151,21 +158,27 @@ class FetchResponseError<
151
158
  resourceType: 'request' | 'response',
152
159
  resourceObject: FetchRequestObject | FetchResponseObject,
153
160
  ): PossiblePromise<FetchRequestObject | FetchResponseObject> {
154
- const resource = this[resourceType];
161
+ const resource = this[resourceType] as Request | Response;
155
162
 
156
163
  if (resource.bodyUsed) {
157
164
  console.warn(
158
- `[@zimic/fetch] Could not include the ${resourceType} body because it is already used. ` +
165
+ '[@zimic/fetch]',
166
+ `Could not include the ${resourceType} body because it is already used. ` +
159
167
  'If you access the body before calling `error.toObject()`, consider reading it from a cloned ' +
160
168
  `${resourceType}.\n\nLearn more: https://zimic.dev/docs/fetch/api/fetch-response-error#errortoobject`,
161
169
  );
162
170
  return resourceObject;
163
171
  }
164
172
 
165
- return resource.text().then((body: string) => {
166
- resourceObject.body = body.length > 0 ? body : null;
167
- return resourceObject;
168
- });
173
+ return parseHttpBody(resource)
174
+ .then((body) => {
175
+ resourceObject.body = body;
176
+ return resourceObject;
177
+ })
178
+ .catch((error: unknown) => {
179
+ console.error('[@zimic/fetch]', `Failed to parse ${resourceType} body:`, error);
180
+ return resourceObject;
181
+ });
169
182
  }
170
183
  }
171
184
 
@@ -161,7 +161,9 @@ export namespace FetchRequest {
161
161
  /**
162
162
  * A plain object representation of a {@link FetchRequest `FetchRequest`}, compatible with JSON.
163
163
  *
164
- * If the body is included in the object, it is represented as a string or null if empty.
164
+ * If the body is included in the object, it is automatically parsed based on the `content-type` header of the request.
165
+ *
166
+ * @see {@link https://zimic.dev/docs/fetch/api/fetch-response-error#errortoobject `error.toObject()`}
165
167
  */
166
168
  export type FetchRequestObject = Pick<
167
169
  FetchRequest.Loose,
@@ -181,11 +183,11 @@ export type FetchRequestObject = Pick<
181
183
  /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Response/headers) */
182
184
  headers: HttpHeadersSerialized<HttpHeadersSchema>;
183
185
  /**
184
- * The body of the response, represented as a string or null if empty.
186
+ * The body of the request. It is automatically parsed based on the `content-type` header of the request.
185
187
  *
186
- * [MDN Reference](https://developer.mozilla.org/docs/Web/API/Request/body)
188
+ * @see {@link https://zimic.dev/docs/fetch/api/fetch-response-error#errortoobject `error.toObject()`}
187
189
  */
188
- body?: string | null;
190
+ body?: HttpBody | null;
189
191
  };
190
192
 
191
193
  /** @see {@link https://zimic.dev/docs/fetch/api/fetch-response `FetchResponse` API reference} */
@@ -249,7 +251,9 @@ export namespace FetchResponse {
249
251
  /**
250
252
  * A plain object representation of a {@link FetchResponse `FetchResponse`}, compatible with JSON.
251
253
  *
252
- * If the body is included in the object, it is represented as a string or null if empty.
254
+ * If the body is included in the object, it is automatically parsed based on the `content-type` header of the response.
255
+ *
256
+ * @see {@link https://zimic.dev/docs/fetch/api/fetch-response-error#errortoobject `error.toObject()`}
253
257
  */
254
258
  export type FetchResponseObject = Pick<
255
259
  FetchResponse.Loose,
@@ -258,11 +262,11 @@ export type FetchResponseObject = Pick<
258
262
  /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Response/headers) */
259
263
  headers: HttpHeadersSerialized<HttpHeadersSchema>;
260
264
  /**
261
- * The body of the response, represented as a string or null if empty.
265
+ * The body of the response. It is automatically parsed based on the `content-type` header of the response.
262
266
  *
263
- * [MDN Reference](https://developer.mozilla.org/docs/Web/API/Request/body)
267
+ * @see {@link https://zimic.dev/docs/fetch/api/fetch-response-error#errortoobject `error.toObject()`}
264
268
  */
265
- body?: string | null;
269
+ body?: HttpBody | null;
266
270
  };
267
271
 
268
272
  /** @see {@link https://zimic.dev/docs/fetch/api/fetch#fetchrequest `fetch.Request` API reference} */