@zimic/fetch 0.1.0-canary.9 → 0.1.1-canary.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -22,26 +22,34 @@ var FetchResponseError = class extends Error {
22
22
  };
23
23
  var FetchResponseError_default = FetchResponseError;
24
24
 
25
- // src/utils/urls.ts
26
- function excludeNonPathParams(url) {
25
+ // ../zimic-utils/dist/chunk-PAWJFY3S.mjs
26
+ var __defProp2 = Object.defineProperty;
27
+ var __name2 = /* @__PURE__ */ __name((target, value) => __defProp2(target, "name", { value, configurable: true }), "__name");
28
+
29
+ // ../zimic-utils/dist/chunk-RIVHLEFF.mjs
30
+ var URL_PATH_PARAM_REGEX = /\/:([^/]+)/g;
31
+ function createRegExpFromURL(url) {
32
+ URL_PATH_PARAM_REGEX.lastIndex = 0;
33
+ const urlWithReplacedPathParams = encodeURI(url).replace(/([.()*?+$\\])/g, "\\$1").replace(URL_PATH_PARAM_REGEX, "/(?<$1>[^/]+)").replace(/^(\/)|(\/)$/g, "");
34
+ return new RegExp(`^(?:/)?${urlWithReplacedPathParams}(?:/)?$`);
35
+ }
36
+ __name(createRegExpFromURL, "createRegExpFromURL");
37
+ __name2(createRegExpFromURL, "createRegExpFromURL");
38
+ var createRegExpFromURL_default = createRegExpFromURL;
39
+
40
+ // ../zimic-utils/dist/url/excludeURLParams.mjs
41
+ function excludeURLParams(url) {
27
42
  url.hash = "";
28
43
  url.search = "";
29
44
  url.username = "";
30
45
  url.password = "";
31
46
  return url;
32
47
  }
33
- __name(excludeNonPathParams, "excludeNonPathParams");
34
- function prepareURLForRegex(url) {
35
- const encodedURL = encodeURI(url);
36
- return encodedURL.replace(/([.()*?+$\\])/g, "\\$1");
37
- }
38
- __name(prepareURLForRegex, "prepareURLForRegex");
39
- var URL_PATH_PARAM_REGEX = /\/:([^/]+)/g;
40
- function createRegexFromURL(url) {
41
- const urlWithReplacedPathParams = prepareURLForRegex(url).replace(URL_PATH_PARAM_REGEX, "/(?<$1>[^/]+)").replace(/(\/+)$/, "(?:/+)?");
42
- return new RegExp(`^${urlWithReplacedPathParams}$`);
43
- }
44
- __name(createRegexFromURL, "createRegexFromURL");
48
+ __name(excludeURLParams, "excludeURLParams");
49
+ __name2(excludeURLParams, "excludeURLParams");
50
+ var excludeURLParams_default = excludeURLParams;
51
+
52
+ // ../zimic-utils/dist/url/joinURL.mjs
45
53
  function joinURL(...parts) {
46
54
  return parts.map((part, index) => {
47
55
  const isFirstPart = index === 0;
@@ -57,6 +65,8 @@ function joinURL(...parts) {
57
65
  }).filter((part) => part.length > 0).join("/");
58
66
  }
59
67
  __name(joinURL, "joinURL");
68
+ __name2(joinURL, "joinURL");
69
+ var joinURL_default = joinURL;
60
70
 
61
71
  // src/client/FetchClient.ts
62
72
  var FetchClient = class {
@@ -66,8 +76,13 @@ var FetchClient = class {
66
76
  fetch;
67
77
  constructor({ onRequest, onResponse, ...defaults }) {
68
78
  this.fetch = this.createFetchFunction();
69
- this.fetch.defaults = defaults;
70
- this.fetch.Request = this.createRequestClass(defaults);
79
+ this.fetch.defaults = {
80
+ ...defaults,
81
+ headers: defaults.headers ?? {},
82
+ searchParams: defaults.searchParams ?? {}
83
+ };
84
+ this.fetch.loose = this.fetch;
85
+ this.fetch.Request = this.createRequestClass(this.fetch.defaults);
71
86
  this.fetch.onRequest = onRequest;
72
87
  this.fetch.onResponse = onResponse;
73
88
  }
@@ -90,8 +105,7 @@ var FetchClient = class {
90
105
  if (this.fetch.onRequest) {
91
106
  const requestAfterInterceptor = await this.fetch.onRequest(
92
107
  // Optimize type checking by narrowing the type of request
93
- request,
94
- this.fetch
108
+ request
95
109
  );
96
110
  if (requestAfterInterceptor !== request) {
97
111
  const isFetchRequest = requestAfterInterceptor instanceof this.fetch.Request;
@@ -105,8 +119,7 @@ var FetchClient = class {
105
119
  if (this.fetch.onResponse) {
106
120
  const responseAfterInterceptor = await this.fetch.onResponse(
107
121
  // Optimize type checking by narrowing the type of response
108
- response,
109
- this.fetch
122
+ response
110
123
  );
111
124
  const isFetchResponse = responseAfterInterceptor instanceof Response && "request" in responseAfterInterceptor && responseAfterInterceptor.request instanceof this.fetch.Request;
112
125
  response = isFetchResponse ? responseAfterInterceptor : this.defineFetchResponseProperties(fetchRequest, responseAfterInterceptor);
@@ -121,10 +134,17 @@ var FetchClient = class {
121
134
  enumerable: true,
122
135
  configurable: false
123
136
  });
124
- const responseError = fetchResponse.ok ? null : new FetchResponseError_default(fetchRequest, fetchResponse);
137
+ let responseError;
125
138
  Object.defineProperty(fetchResponse, "error", {
126
- value: responseError,
127
- writable: false,
139
+ get() {
140
+ if (responseError === void 0) {
141
+ responseError = fetchResponse.ok ? null : new FetchResponseError_default(
142
+ fetchRequest,
143
+ fetchResponse
144
+ );
145
+ }
146
+ return responseError;
147
+ },
128
148
  enumerable: true,
129
149
  configurable: false
130
150
  });
@@ -136,24 +156,39 @@ var FetchClient = class {
136
156
  __name(this, "Request");
137
157
  }
138
158
  path;
139
- constructor(input, rawInit) {
140
- const init = { ...defaults, ...rawInit };
159
+ constructor(input, init) {
160
+ const initWithDefaults = { ...defaults, ...init };
161
+ const headersFromDefaults = new http.HttpHeaders(defaults.headers);
162
+ const headersFromInit = new http.HttpHeaders(init.headers);
141
163
  let url;
164
+ const baseURL = new URL(initWithDefaults.baseURL);
142
165
  if (input instanceof globalThis.Request) {
143
- super(
144
- // Optimize type checking by narrowing the type of input
145
- input,
146
- init
147
- );
166
+ const request = input;
167
+ const headersFromRequest = new http.HttpHeaders(input.headers);
168
+ initWithDefaults.headers = {
169
+ ...headersFromDefaults.toObject(),
170
+ ...headersFromRequest.toObject(),
171
+ ...headersFromInit.toObject()
172
+ };
173
+ super(request, initWithDefaults);
148
174
  url = new URL(input.url);
149
175
  } else {
150
- url = input instanceof URL ? new URL(input) : new URL(joinURL(init.baseURL, input));
151
- if (init.searchParams) {
152
- url.search = new http.HttpSearchParams(init.searchParams).toString();
153
- }
154
- super(url, init);
176
+ initWithDefaults.headers = {
177
+ ...headersFromDefaults.toObject(),
178
+ ...headersFromInit.toObject()
179
+ };
180
+ url = input instanceof URL ? new URL(input) : new URL(joinURL_default(baseURL, input));
181
+ const searchParamsFromDefaults = new http.HttpSearchParams(defaults.searchParams);
182
+ const searchParamsFromInit = new http.HttpSearchParams(initWithDefaults.searchParams);
183
+ initWithDefaults.searchParams = {
184
+ ...searchParamsFromDefaults.toObject(),
185
+ ...searchParamsFromInit.toObject()
186
+ };
187
+ url.search = new http.HttpSearchParams(initWithDefaults.searchParams).toString();
188
+ super(url, initWithDefaults);
155
189
  }
156
- this.path = excludeNonPathParams(url).toString().replace(init.baseURL, "");
190
+ const baseURLWithoutTrailingSlash = baseURL.toString().replace(/\/$/, "");
191
+ this.path = excludeURLParams_default(url).toString().replace(baseURLWithoutTrailingSlash, "");
157
192
  }
158
193
  clone() {
159
194
  const rawClone = super.clone();
@@ -165,14 +200,14 @@ var FetchClient = class {
165
200
  }
166
201
  return Request2;
167
202
  }
168
- isRequest(request, path, method) {
169
- return request instanceof Request && request.method === method && "path" in request && typeof request.path === "string" && createRegexFromURL(path).test(request.path);
203
+ isRequest(request, method, path) {
204
+ return request instanceof Request && request.method === method && "path" in request && typeof request.path === "string" && createRegExpFromURL_default(path).test(request.path);
170
205
  }
171
- isResponse(response, path, method) {
172
- return response instanceof Response && "request" in response && "error" in response && this.isRequest(response.request, path, method);
206
+ isResponse(response, method, path) {
207
+ return response instanceof Response && "request" in response && this.isRequest(response.request, method, path) && "error" in response && (response.error === null || response.error instanceof FetchResponseError_default);
173
208
  }
174
- isResponseError(error, path, method) {
175
- return error instanceof FetchResponseError_default && error.request.method === method && typeof error.request.path === "string" && createRegexFromURL(path).test(error.request.path);
209
+ isResponseError(error, method, path) {
210
+ return error instanceof FetchResponseError_default && this.isRequest(error.request, method, path) && this.isResponse(error.response, method, path);
176
211
  }
177
212
  };
178
213
  var FetchClient_default = FetchClient;
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/client/errors/FetchResponseError.ts","../src/utils/urls.ts","../src/client/FetchClient.ts","../src/client/factory.ts"],"names":["Request","HttpSearchParams"],"mappings":"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","file":"index.js","sourcesContent":["import { HttpMethod, HttpMethodSchema } from '@zimic/http';\n\nimport { FetchRequest, FetchResponse } from '../types/requests';\n\nclass FetchResponseError<\n Path extends string = string,\n Method extends HttpMethod = HttpMethod,\n MethodSchema extends HttpMethodSchema = HttpMethodSchema,\n> extends Error {\n constructor(\n public request: FetchRequest<Path, Method, MethodSchema>,\n public response: FetchResponse<Path, Method, MethodSchema, true>,\n ) {\n super(`${request.method} ${request.url} failed with status ${response.status}: ${response.statusText}`);\n this.name = 'FetchResponseError';\n }\n\n get cause() {\n return this.response;\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 excludeNonPathParams(url: URL) {\n url.hash = '';\n url.search = '';\n url.username = '';\n url.password = '';\n return url;\n}\n\nfunction prepareURLForRegex(url: string) {\n const encodedURL = encodeURI(url);\n return encodedURL.replace(/([.()*?+$\\\\])/g, '\\\\$1');\n}\n\nconst URL_PATH_PARAM_REGEX = /\\/:([^/]+)/g;\n\nexport function createRegexFromURL(url: string) {\n const urlWithReplacedPathParams = prepareURLForRegex(url)\n .replace(URL_PATH_PARAM_REGEX, '/(?<$1>[^/]+)')\n .replace(/(\\/+)$/, '(?:/+)?');\n\n return new RegExp(`^${urlWithReplacedPathParams}$`);\n}\n\nexport function joinURL(...parts: (string | URL)[]) {\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","import {\n HttpSchemaPath,\n HttpSchemaMethod,\n HttpSearchParams,\n LiteralHttpSchemaPathFromNonLiteral,\n HttpSchema,\n} from '@zimic/http';\n\nimport { Default } from '@/types/utils';\nimport { createRegexFromURL, excludeNonPathParams, joinURL } from '@/utils/urls';\n\nimport FetchResponseError from './errors/FetchResponseError';\nimport { FetchInput, FetchOptions, Fetch } from './types/public';\nimport { FetchRequestConstructor, FetchRequestInit, FetchRequest, FetchResponse } from './types/requests';\n\nclass FetchClient<Schema extends HttpSchema> {\n fetch: Fetch<Schema>;\n\n constructor({ onRequest, onResponse, ...defaults }: FetchOptions<Schema>) {\n this.fetch = this.createFetchFunction();\n this.fetch.defaults = defaults;\n this.fetch.Request = this.createRequestClass(defaults);\n this.fetch.onRequest = onRequest;\n this.fetch.onResponse = onResponse;\n }\n\n private createFetchFunction() {\n const fetch = async <\n Path extends HttpSchemaPath.NonLiteral<Schema, Method>,\n Method extends HttpSchemaMethod<Schema>,\n >(\n input: FetchInput<Schema, Path, Method>,\n init: FetchRequestInit<Schema, LiteralHttpSchemaPathFromNonLiteral<Schema, Method, Path>, Method>,\n ) => {\n const request = await this.createFetchRequest<Path, Method>(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 LiteralHttpSchemaPathFromNonLiteral<Schema, Method, Path>,\n Method\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 Path extends HttpSchemaPath.NonLiteral<Schema, Method>,\n Method extends HttpSchemaMethod<Schema>,\n >(\n input: FetchInput<Schema, Path, Method>,\n init: FetchRequestInit<Schema, LiteralHttpSchemaPathFromNonLiteral<Schema, Method, Path>, Method>,\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 this.fetch,\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, Path, Method>, init);\n }\n }\n\n return request;\n }\n\n private async createFetchResponse<\n Path extends HttpSchemaPath<Schema, Method>,\n Method extends HttpSchemaMethod<Schema>,\n >(fetchRequest: FetchRequest<Path, Method, Default<Schema[Path][Method]>>, rawResponse: Response) {\n let response = this.defineFetchResponseProperties<Path, Method>(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 this.fetch,\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<Path, Method>(fetchRequest, responseAfterInterceptor);\n }\n\n return response;\n }\n\n private defineFetchResponseProperties<\n Path extends HttpSchemaPath<Schema, Method>,\n Method extends HttpSchemaMethod<Schema>,\n >(fetchRequest: FetchRequest<Path, Method, Default<Schema[Path][Method]>>, response: Response) {\n const fetchResponse = response as FetchResponse<Path, Method, Default<Schema[Path][Method]>>;\n\n Object.defineProperty(fetchResponse, 'request', {\n value: fetchRequest satisfies FetchResponse.Loose['request'],\n writable: false,\n enumerable: true,\n configurable: false,\n });\n\n const responseError = (\n fetchResponse.ok ? null : new FetchResponseError(fetchRequest, fetchResponse)\n ) satisfies FetchResponse.Loose['error'];\n\n Object.defineProperty(fetchResponse, 'error', {\n value: responseError,\n writable: false,\n enumerable: true,\n configurable: false,\n });\n\n return fetchResponse;\n }\n\n private createRequestClass(defaults: FetchRequestInit.Defaults) {\n class Request<\n Path extends HttpSchemaPath.NonLiteral<Schema, Method>,\n Method extends HttpSchemaMethod<Schema>,\n > extends globalThis.Request {\n path: LiteralHttpSchemaPathFromNonLiteral<Schema, Method, Path>;\n\n constructor(\n input: FetchInput<Schema, Path, Method>,\n rawInit: FetchRequestInit<Schema, LiteralHttpSchemaPathFromNonLiteral<Schema, Method, Path>, Method>,\n ) {\n const init = { ...defaults, ...rawInit };\n\n let url: URL;\n\n if (input instanceof globalThis.Request) {\n super(\n // Optimize type checking by narrowing the type of input\n input as globalThis.Request,\n init,\n );\n\n url = new URL(input.url);\n } else {\n url = input instanceof URL ? new URL(input) : new URL(joinURL(init.baseURL, input));\n\n if (init.searchParams) {\n url.search = new HttpSearchParams(init.searchParams).toString();\n }\n\n super(url, init);\n }\n\n this.path = excludeNonPathParams(url)\n .toString()\n .replace(init.baseURL, '') as LiteralHttpSchemaPathFromNonLiteral<Schema, Method, Path>;\n }\n\n clone(): Request<Path, Method> {\n const rawClone = super.clone();\n\n return new Request<Path, Method>(\n rawClone as unknown as FetchInput<Schema, Path, Method>,\n rawClone as unknown as FetchRequestInit<\n Schema,\n LiteralHttpSchemaPathFromNonLiteral<Schema, Method, Path>,\n Method\n >,\n );\n }\n }\n\n return Request as FetchRequestConstructor<Schema>;\n }\n\n isRequest<Path extends HttpSchemaPath<Schema, Method>, Method extends HttpSchemaMethod<Schema>>(\n request: unknown,\n path: Path,\n method: Method,\n ): request is FetchRequest<Path, Method, Default<Schema[Path][Method]>> {\n return (\n request instanceof Request &&\n request.method === method &&\n 'path' in request &&\n typeof request.path === 'string' &&\n createRegexFromURL(path).test(request.path)\n );\n }\n\n isResponse<Path extends HttpSchemaPath<Schema, Method>, Method extends HttpSchemaMethod<Schema>>(\n response: unknown,\n path: Path,\n method: Method,\n ): response is FetchResponse<Path, Method, Default<Schema[Path][Method]>> {\n return (\n response instanceof Response &&\n 'request' in response &&\n 'error' in response &&\n this.isRequest(response.request, path, method)\n );\n }\n\n isResponseError<Path extends HttpSchemaPath<Schema, Method>, Method extends HttpSchemaMethod<Schema>>(\n error: unknown,\n path: Path,\n method: Method,\n ): error is FetchResponseError<Path, Method, Default<Schema[Path][Method]>> {\n return (\n error instanceof FetchResponseError &&\n error.request.method === method &&\n typeof error.request.path === 'string' &&\n createRegexFromURL(path).test(error.request.path)\n );\n }\n}\n\nexport default FetchClient;\n","import { HttpSchema } from '@zimic/http';\n\nimport FetchClient from './FetchClient';\nimport { FetchOptions, Fetch as PublicFetch } from './types/public';\n\nfunction createFetch<Schema extends HttpSchema>(\n options: FetchOptions<HttpSchema<Schema>>,\n): PublicFetch<HttpSchema<Schema>> {\n const { fetch } = new FetchClient<HttpSchema<Schema>>(options);\n return fetch;\n}\n\nexport default createFetch;\n"]}
1
+ {"version":3,"sources":["../src/client/errors/FetchResponseError.ts","../../zimic-utils/dist/chunk-PAWJFY3S.mjs","../../zimic-utils/src/url/createRegExpFromURL.ts","../../zimic-utils/src/url/excludeURLParams.ts","../../zimic-utils/src/url/joinURL.ts","../src/client/FetchClient.ts","../src/client/factory.ts"],"names":["__defProp","__name","Request","HttpHeaders","HttpSearchParams"],"mappings":"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","file":"index.js","sourcesContent":["import { HttpSchema, HttpSchemaMethod, HttpSchemaPath } from '@zimic/http';\n\nimport { FetchRequest, FetchResponse } from '../types/requests';\n\n/**\n * An error representing a response with a failure status code (4XX or 5XX).\n *\n * @example\n * import { type HttpSchema } from '@zimic/http';\n * import { createFetch } from '@zimic/fetch';\n *\n * interface User {\n * id: string;\n * username: string;\n * }\n *\n * type Schema = HttpSchema<{\n * '/users/:userId': {\n * GET: {\n * response: {\n * 200: { body: User };\n * 404: { body: { message: string } };\n * };\n * };\n * };\n * }>;\n *\n * const fetch = createFetch<Schema>({\n * baseURL: 'http://localhost:3000',\n * });\n *\n * const response = await fetch(`/users/${userId}`, {\n * method: 'GET',\n * });\n *\n * if (!response.ok) {\n * console.log(response.status); // 404\n *\n * console.log(response.error); // FetchResponseError<Schema, 'GET', '/users'>\n * console.log(response.error.request); // FetchRequest<Schema, 'GET', '/users'>\n * console.log(response.error.response); // FetchResponse<Schema, 'GET', '/users'>\n * }\n *\n * @see {@link https://github.com/zimicjs/zimic/wiki/api‐zimic‐fetch#fetchresponseerror `FetchResponseError` API reference}\n */\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 get cause() {\n return this.response;\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","var __defProp = Object.defineProperty;\nvar __name = (target, value) => __defProp(target, \"name\", { value, configurable: true });\n\nexport { __name };\n//# sourceMappingURL=chunk-PAWJFY3S.mjs.map\n//# sourceMappingURL=chunk-PAWJFY3S.mjs.map","export const URL_PATH_PARAM_REGEX = /\\/:([^/]+)/g;\n\nfunction createRegExpFromURL(url: string) {\n URL_PATH_PARAM_REGEX.lastIndex = 0;\n\n const urlWithReplacedPathParams = encodeURI(url)\n .replace(/([.()*?+$\\\\])/g, '\\\\$1')\n .replace(URL_PATH_PARAM_REGEX, '/(?<$1>[^/]+)')\n .replace(/^(\\/)|(\\/)$/g, '');\n\n return new RegExp(`^(?:/)?${urlWithReplacedPathParams}(?:/)?$`);\n}\n\nexport default createRegExpFromURL;\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 createRegexFromURL from '@zimic/utils/url/createRegExpFromURL';\nimport excludeURLParams from '@zimic/utils/url/excludeURLParams';\nimport joinURL from '@zimic/utils/url/joinURL';\n\nimport FetchResponseError from './errors/FetchResponseError';\nimport {\n FetchInput,\n FetchOptions,\n Fetch,\n FetchClient as PublicFetchClient,\n FetchDefaults,\n FetchFunction,\n} from './types/public';\nimport { FetchRequestConstructor, FetchRequestInit, FetchRequest, FetchResponse } from './types/requests';\n\nclass FetchClient<Schema extends HttpSchema>\n implements Omit<PublicFetchClient<Schema>, 'defaults' | 'loose' | 'Request'>\n{\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 FetchFunction.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 satisfies FetchResponse.Loose['request'],\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 const headersFromRequest = new HttpHeaders(input.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 createRegexFromURL(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/**\n * Creates a {@link https://github.com/zimicjs/zimic/wiki/api‐zimic‐fetch#fetch fetch instance} typed with an HTTP\n * schema, closely compatible with the {@link https://developer.mozilla.org/docs/Web/API/Fetch_API native Fetch API}. All\n * requests and responses are typed by default with the schema, including methods, paths, status codes, parameters, and\n * bodies.\n *\n * Requests sent by the fetch instance have their URL automatically prefixed with the base URL of the instance.\n * {@link https://github.com/zimicjs/zimic/wiki/api‐zimic‐fetch#fetch.defaults Default options} are also applied to the\n * requests, if provided.\n *\n * @example\n * import { type HttpSchema } from '@zimic/http';\n * import { createFetch } from '@zimic/fetch';\n *\n * interface User {\n * id: string;\n * username: string;\n * }\n *\n * type Schema = HttpSchema<{\n * '/users': {\n * POST: {\n * request: {\n * headers: { 'content-type': 'application/json' };\n * body: { username: string };\n * };\n * response: {\n * 201: { body: User };\n * };\n * };\n *\n * GET: {\n * request: {\n * searchParams: {\n * query?: string;\n * page?: number;\n * limit?: number;\n * };\n * };\n * response: {\n * 200: { body: User[] };\n * };\n * };\n * };\n * }>;\n *\n * const fetch = createFetch<Schema>({\n * baseURL: 'http://localhost:3000',\n * });\n *\n * @see {@link https://github.com/zimicjs/zimic/wiki/api‐zimic‐fetch#createfetch `createFetch(options)` API reference}\n * @see {@link https://github.com/zimicjs/zimic/wiki/api‐zimic‐fetch#fetch `fetch` API reference}\n */\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 { HttpSearchParams } from '@zimic/http';
1
+ import { HttpHeaders, HttpSearchParams } from '@zimic/http';
2
2
 
3
3
  var __defProp = Object.defineProperty;
4
4
  var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
@@ -20,26 +20,34 @@ var FetchResponseError = class extends Error {
20
20
  };
21
21
  var FetchResponseError_default = FetchResponseError;
22
22
 
23
- // src/utils/urls.ts
24
- function excludeNonPathParams(url) {
23
+ // ../zimic-utils/dist/chunk-PAWJFY3S.mjs
24
+ var __defProp2 = Object.defineProperty;
25
+ var __name2 = /* @__PURE__ */ __name((target, value) => __defProp2(target, "name", { value, configurable: true }), "__name");
26
+
27
+ // ../zimic-utils/dist/chunk-RIVHLEFF.mjs
28
+ var URL_PATH_PARAM_REGEX = /\/:([^/]+)/g;
29
+ function createRegExpFromURL(url) {
30
+ URL_PATH_PARAM_REGEX.lastIndex = 0;
31
+ const urlWithReplacedPathParams = encodeURI(url).replace(/([.()*?+$\\])/g, "\\$1").replace(URL_PATH_PARAM_REGEX, "/(?<$1>[^/]+)").replace(/^(\/)|(\/)$/g, "");
32
+ return new RegExp(`^(?:/)?${urlWithReplacedPathParams}(?:/)?$`);
33
+ }
34
+ __name(createRegExpFromURL, "createRegExpFromURL");
35
+ __name2(createRegExpFromURL, "createRegExpFromURL");
36
+ var createRegExpFromURL_default = createRegExpFromURL;
37
+
38
+ // ../zimic-utils/dist/url/excludeURLParams.mjs
39
+ function excludeURLParams(url) {
25
40
  url.hash = "";
26
41
  url.search = "";
27
42
  url.username = "";
28
43
  url.password = "";
29
44
  return url;
30
45
  }
31
- __name(excludeNonPathParams, "excludeNonPathParams");
32
- function prepareURLForRegex(url) {
33
- const encodedURL = encodeURI(url);
34
- return encodedURL.replace(/([.()*?+$\\])/g, "\\$1");
35
- }
36
- __name(prepareURLForRegex, "prepareURLForRegex");
37
- var URL_PATH_PARAM_REGEX = /\/:([^/]+)/g;
38
- function createRegexFromURL(url) {
39
- const urlWithReplacedPathParams = prepareURLForRegex(url).replace(URL_PATH_PARAM_REGEX, "/(?<$1>[^/]+)").replace(/(\/+)$/, "(?:/+)?");
40
- return new RegExp(`^${urlWithReplacedPathParams}$`);
41
- }
42
- __name(createRegexFromURL, "createRegexFromURL");
46
+ __name(excludeURLParams, "excludeURLParams");
47
+ __name2(excludeURLParams, "excludeURLParams");
48
+ var excludeURLParams_default = excludeURLParams;
49
+
50
+ // ../zimic-utils/dist/url/joinURL.mjs
43
51
  function joinURL(...parts) {
44
52
  return parts.map((part, index) => {
45
53
  const isFirstPart = index === 0;
@@ -55,6 +63,8 @@ function joinURL(...parts) {
55
63
  }).filter((part) => part.length > 0).join("/");
56
64
  }
57
65
  __name(joinURL, "joinURL");
66
+ __name2(joinURL, "joinURL");
67
+ var joinURL_default = joinURL;
58
68
 
59
69
  // src/client/FetchClient.ts
60
70
  var FetchClient = class {
@@ -64,8 +74,13 @@ var FetchClient = class {
64
74
  fetch;
65
75
  constructor({ onRequest, onResponse, ...defaults }) {
66
76
  this.fetch = this.createFetchFunction();
67
- this.fetch.defaults = defaults;
68
- this.fetch.Request = this.createRequestClass(defaults);
77
+ this.fetch.defaults = {
78
+ ...defaults,
79
+ headers: defaults.headers ?? {},
80
+ searchParams: defaults.searchParams ?? {}
81
+ };
82
+ this.fetch.loose = this.fetch;
83
+ this.fetch.Request = this.createRequestClass(this.fetch.defaults);
69
84
  this.fetch.onRequest = onRequest;
70
85
  this.fetch.onResponse = onResponse;
71
86
  }
@@ -88,8 +103,7 @@ var FetchClient = class {
88
103
  if (this.fetch.onRequest) {
89
104
  const requestAfterInterceptor = await this.fetch.onRequest(
90
105
  // Optimize type checking by narrowing the type of request
91
- request,
92
- this.fetch
106
+ request
93
107
  );
94
108
  if (requestAfterInterceptor !== request) {
95
109
  const isFetchRequest = requestAfterInterceptor instanceof this.fetch.Request;
@@ -103,8 +117,7 @@ var FetchClient = class {
103
117
  if (this.fetch.onResponse) {
104
118
  const responseAfterInterceptor = await this.fetch.onResponse(
105
119
  // Optimize type checking by narrowing the type of response
106
- response,
107
- this.fetch
120
+ response
108
121
  );
109
122
  const isFetchResponse = responseAfterInterceptor instanceof Response && "request" in responseAfterInterceptor && responseAfterInterceptor.request instanceof this.fetch.Request;
110
123
  response = isFetchResponse ? responseAfterInterceptor : this.defineFetchResponseProperties(fetchRequest, responseAfterInterceptor);
@@ -119,10 +132,17 @@ var FetchClient = class {
119
132
  enumerable: true,
120
133
  configurable: false
121
134
  });
122
- const responseError = fetchResponse.ok ? null : new FetchResponseError_default(fetchRequest, fetchResponse);
135
+ let responseError;
123
136
  Object.defineProperty(fetchResponse, "error", {
124
- value: responseError,
125
- writable: false,
137
+ get() {
138
+ if (responseError === void 0) {
139
+ responseError = fetchResponse.ok ? null : new FetchResponseError_default(
140
+ fetchRequest,
141
+ fetchResponse
142
+ );
143
+ }
144
+ return responseError;
145
+ },
126
146
  enumerable: true,
127
147
  configurable: false
128
148
  });
@@ -134,24 +154,39 @@ var FetchClient = class {
134
154
  __name(this, "Request");
135
155
  }
136
156
  path;
137
- constructor(input, rawInit) {
138
- const init = { ...defaults, ...rawInit };
157
+ constructor(input, init) {
158
+ const initWithDefaults = { ...defaults, ...init };
159
+ const headersFromDefaults = new HttpHeaders(defaults.headers);
160
+ const headersFromInit = new HttpHeaders(init.headers);
139
161
  let url;
162
+ const baseURL = new URL(initWithDefaults.baseURL);
140
163
  if (input instanceof globalThis.Request) {
141
- super(
142
- // Optimize type checking by narrowing the type of input
143
- input,
144
- init
145
- );
164
+ const request = input;
165
+ const headersFromRequest = new HttpHeaders(input.headers);
166
+ initWithDefaults.headers = {
167
+ ...headersFromDefaults.toObject(),
168
+ ...headersFromRequest.toObject(),
169
+ ...headersFromInit.toObject()
170
+ };
171
+ super(request, initWithDefaults);
146
172
  url = new URL(input.url);
147
173
  } else {
148
- url = input instanceof URL ? new URL(input) : new URL(joinURL(init.baseURL, input));
149
- if (init.searchParams) {
150
- url.search = new HttpSearchParams(init.searchParams).toString();
151
- }
152
- super(url, init);
174
+ initWithDefaults.headers = {
175
+ ...headersFromDefaults.toObject(),
176
+ ...headersFromInit.toObject()
177
+ };
178
+ url = input instanceof URL ? new URL(input) : new URL(joinURL_default(baseURL, input));
179
+ const searchParamsFromDefaults = new HttpSearchParams(defaults.searchParams);
180
+ const searchParamsFromInit = new HttpSearchParams(initWithDefaults.searchParams);
181
+ initWithDefaults.searchParams = {
182
+ ...searchParamsFromDefaults.toObject(),
183
+ ...searchParamsFromInit.toObject()
184
+ };
185
+ url.search = new HttpSearchParams(initWithDefaults.searchParams).toString();
186
+ super(url, initWithDefaults);
153
187
  }
154
- this.path = excludeNonPathParams(url).toString().replace(init.baseURL, "");
188
+ const baseURLWithoutTrailingSlash = baseURL.toString().replace(/\/$/, "");
189
+ this.path = excludeURLParams_default(url).toString().replace(baseURLWithoutTrailingSlash, "");
155
190
  }
156
191
  clone() {
157
192
  const rawClone = super.clone();
@@ -163,14 +198,14 @@ var FetchClient = class {
163
198
  }
164
199
  return Request2;
165
200
  }
166
- isRequest(request, path, method) {
167
- return request instanceof Request && request.method === method && "path" in request && typeof request.path === "string" && createRegexFromURL(path).test(request.path);
201
+ isRequest(request, method, path) {
202
+ return request instanceof Request && request.method === method && "path" in request && typeof request.path === "string" && createRegExpFromURL_default(path).test(request.path);
168
203
  }
169
- isResponse(response, path, method) {
170
- return response instanceof Response && "request" in response && "error" in response && this.isRequest(response.request, path, method);
204
+ isResponse(response, method, path) {
205
+ return response instanceof Response && "request" in response && this.isRequest(response.request, method, path) && "error" in response && (response.error === null || response.error instanceof FetchResponseError_default);
171
206
  }
172
- isResponseError(error, path, method) {
173
- return error instanceof FetchResponseError_default && error.request.method === method && typeof error.request.path === "string" && createRegexFromURL(path).test(error.request.path);
207
+ isResponseError(error, method, path) {
208
+ return error instanceof FetchResponseError_default && this.isRequest(error.request, method, path) && this.isResponse(error.response, method, path);
174
209
  }
175
210
  };
176
211
  var FetchClient_default = FetchClient;
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/client/errors/FetchResponseError.ts","../src/utils/urls.ts","../src/client/FetchClient.ts","../src/client/factory.ts"],"names":["Request"],"mappings":"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","file":"index.mjs","sourcesContent":["import { HttpMethod, HttpMethodSchema } from '@zimic/http';\n\nimport { FetchRequest, FetchResponse } from '../types/requests';\n\nclass FetchResponseError<\n Path extends string = string,\n Method extends HttpMethod = HttpMethod,\n MethodSchema extends HttpMethodSchema = HttpMethodSchema,\n> extends Error {\n constructor(\n public request: FetchRequest<Path, Method, MethodSchema>,\n public response: FetchResponse<Path, Method, MethodSchema, true>,\n ) {\n super(`${request.method} ${request.url} failed with status ${response.status}: ${response.statusText}`);\n this.name = 'FetchResponseError';\n }\n\n get cause() {\n return this.response;\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 excludeNonPathParams(url: URL) {\n url.hash = '';\n url.search = '';\n url.username = '';\n url.password = '';\n return url;\n}\n\nfunction prepareURLForRegex(url: string) {\n const encodedURL = encodeURI(url);\n return encodedURL.replace(/([.()*?+$\\\\])/g, '\\\\$1');\n}\n\nconst URL_PATH_PARAM_REGEX = /\\/:([^/]+)/g;\n\nexport function createRegexFromURL(url: string) {\n const urlWithReplacedPathParams = prepareURLForRegex(url)\n .replace(URL_PATH_PARAM_REGEX, '/(?<$1>[^/]+)')\n .replace(/(\\/+)$/, '(?:/+)?');\n\n return new RegExp(`^${urlWithReplacedPathParams}$`);\n}\n\nexport function joinURL(...parts: (string | URL)[]) {\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","import {\n HttpSchemaPath,\n HttpSchemaMethod,\n HttpSearchParams,\n LiteralHttpSchemaPathFromNonLiteral,\n HttpSchema,\n} from '@zimic/http';\n\nimport { Default } from '@/types/utils';\nimport { createRegexFromURL, excludeNonPathParams, joinURL } from '@/utils/urls';\n\nimport FetchResponseError from './errors/FetchResponseError';\nimport { FetchInput, FetchOptions, Fetch } from './types/public';\nimport { FetchRequestConstructor, FetchRequestInit, FetchRequest, FetchResponse } from './types/requests';\n\nclass FetchClient<Schema extends HttpSchema> {\n fetch: Fetch<Schema>;\n\n constructor({ onRequest, onResponse, ...defaults }: FetchOptions<Schema>) {\n this.fetch = this.createFetchFunction();\n this.fetch.defaults = defaults;\n this.fetch.Request = this.createRequestClass(defaults);\n this.fetch.onRequest = onRequest;\n this.fetch.onResponse = onResponse;\n }\n\n private createFetchFunction() {\n const fetch = async <\n Path extends HttpSchemaPath.NonLiteral<Schema, Method>,\n Method extends HttpSchemaMethod<Schema>,\n >(\n input: FetchInput<Schema, Path, Method>,\n init: FetchRequestInit<Schema, LiteralHttpSchemaPathFromNonLiteral<Schema, Method, Path>, Method>,\n ) => {\n const request = await this.createFetchRequest<Path, Method>(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 LiteralHttpSchemaPathFromNonLiteral<Schema, Method, Path>,\n Method\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 Path extends HttpSchemaPath.NonLiteral<Schema, Method>,\n Method extends HttpSchemaMethod<Schema>,\n >(\n input: FetchInput<Schema, Path, Method>,\n init: FetchRequestInit<Schema, LiteralHttpSchemaPathFromNonLiteral<Schema, Method, Path>, Method>,\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 this.fetch,\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, Path, Method>, init);\n }\n }\n\n return request;\n }\n\n private async createFetchResponse<\n Path extends HttpSchemaPath<Schema, Method>,\n Method extends HttpSchemaMethod<Schema>,\n >(fetchRequest: FetchRequest<Path, Method, Default<Schema[Path][Method]>>, rawResponse: Response) {\n let response = this.defineFetchResponseProperties<Path, Method>(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 this.fetch,\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<Path, Method>(fetchRequest, responseAfterInterceptor);\n }\n\n return response;\n }\n\n private defineFetchResponseProperties<\n Path extends HttpSchemaPath<Schema, Method>,\n Method extends HttpSchemaMethod<Schema>,\n >(fetchRequest: FetchRequest<Path, Method, Default<Schema[Path][Method]>>, response: Response) {\n const fetchResponse = response as FetchResponse<Path, Method, Default<Schema[Path][Method]>>;\n\n Object.defineProperty(fetchResponse, 'request', {\n value: fetchRequest satisfies FetchResponse.Loose['request'],\n writable: false,\n enumerable: true,\n configurable: false,\n });\n\n const responseError = (\n fetchResponse.ok ? null : new FetchResponseError(fetchRequest, fetchResponse)\n ) satisfies FetchResponse.Loose['error'];\n\n Object.defineProperty(fetchResponse, 'error', {\n value: responseError,\n writable: false,\n enumerable: true,\n configurable: false,\n });\n\n return fetchResponse;\n }\n\n private createRequestClass(defaults: FetchRequestInit.Defaults) {\n class Request<\n Path extends HttpSchemaPath.NonLiteral<Schema, Method>,\n Method extends HttpSchemaMethod<Schema>,\n > extends globalThis.Request {\n path: LiteralHttpSchemaPathFromNonLiteral<Schema, Method, Path>;\n\n constructor(\n input: FetchInput<Schema, Path, Method>,\n rawInit: FetchRequestInit<Schema, LiteralHttpSchemaPathFromNonLiteral<Schema, Method, Path>, Method>,\n ) {\n const init = { ...defaults, ...rawInit };\n\n let url: URL;\n\n if (input instanceof globalThis.Request) {\n super(\n // Optimize type checking by narrowing the type of input\n input as globalThis.Request,\n init,\n );\n\n url = new URL(input.url);\n } else {\n url = input instanceof URL ? new URL(input) : new URL(joinURL(init.baseURL, input));\n\n if (init.searchParams) {\n url.search = new HttpSearchParams(init.searchParams).toString();\n }\n\n super(url, init);\n }\n\n this.path = excludeNonPathParams(url)\n .toString()\n .replace(init.baseURL, '') as LiteralHttpSchemaPathFromNonLiteral<Schema, Method, Path>;\n }\n\n clone(): Request<Path, Method> {\n const rawClone = super.clone();\n\n return new Request<Path, Method>(\n rawClone as unknown as FetchInput<Schema, Path, Method>,\n rawClone as unknown as FetchRequestInit<\n Schema,\n LiteralHttpSchemaPathFromNonLiteral<Schema, Method, Path>,\n Method\n >,\n );\n }\n }\n\n return Request as FetchRequestConstructor<Schema>;\n }\n\n isRequest<Path extends HttpSchemaPath<Schema, Method>, Method extends HttpSchemaMethod<Schema>>(\n request: unknown,\n path: Path,\n method: Method,\n ): request is FetchRequest<Path, Method, Default<Schema[Path][Method]>> {\n return (\n request instanceof Request &&\n request.method === method &&\n 'path' in request &&\n typeof request.path === 'string' &&\n createRegexFromURL(path).test(request.path)\n );\n }\n\n isResponse<Path extends HttpSchemaPath<Schema, Method>, Method extends HttpSchemaMethod<Schema>>(\n response: unknown,\n path: Path,\n method: Method,\n ): response is FetchResponse<Path, Method, Default<Schema[Path][Method]>> {\n return (\n response instanceof Response &&\n 'request' in response &&\n 'error' in response &&\n this.isRequest(response.request, path, method)\n );\n }\n\n isResponseError<Path extends HttpSchemaPath<Schema, Method>, Method extends HttpSchemaMethod<Schema>>(\n error: unknown,\n path: Path,\n method: Method,\n ): error is FetchResponseError<Path, Method, Default<Schema[Path][Method]>> {\n return (\n error instanceof FetchResponseError &&\n error.request.method === method &&\n typeof error.request.path === 'string' &&\n createRegexFromURL(path).test(error.request.path)\n );\n }\n}\n\nexport default FetchClient;\n","import { HttpSchema } from '@zimic/http';\n\nimport FetchClient from './FetchClient';\nimport { FetchOptions, Fetch as PublicFetch } from './types/public';\n\nfunction createFetch<Schema extends HttpSchema>(\n options: FetchOptions<HttpSchema<Schema>>,\n): PublicFetch<HttpSchema<Schema>> {\n const { fetch } = new FetchClient<HttpSchema<Schema>>(options);\n return fetch;\n}\n\nexport default createFetch;\n"]}
1
+ {"version":3,"sources":["../src/client/errors/FetchResponseError.ts","../../zimic-utils/dist/chunk-PAWJFY3S.mjs","../../zimic-utils/src/url/createRegExpFromURL.ts","../../zimic-utils/src/url/excludeURLParams.ts","../../zimic-utils/src/url/joinURL.ts","../src/client/FetchClient.ts","../src/client/factory.ts"],"names":["__defProp","__name","Request"],"mappings":"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","file":"index.mjs","sourcesContent":["import { HttpSchema, HttpSchemaMethod, HttpSchemaPath } from '@zimic/http';\n\nimport { FetchRequest, FetchResponse } from '../types/requests';\n\n/**\n * An error representing a response with a failure status code (4XX or 5XX).\n *\n * @example\n * import { type HttpSchema } from '@zimic/http';\n * import { createFetch } from '@zimic/fetch';\n *\n * interface User {\n * id: string;\n * username: string;\n * }\n *\n * type Schema = HttpSchema<{\n * '/users/:userId': {\n * GET: {\n * response: {\n * 200: { body: User };\n * 404: { body: { message: string } };\n * };\n * };\n * };\n * }>;\n *\n * const fetch = createFetch<Schema>({\n * baseURL: 'http://localhost:3000',\n * });\n *\n * const response = await fetch(`/users/${userId}`, {\n * method: 'GET',\n * });\n *\n * if (!response.ok) {\n * console.log(response.status); // 404\n *\n * console.log(response.error); // FetchResponseError<Schema, 'GET', '/users'>\n * console.log(response.error.request); // FetchRequest<Schema, 'GET', '/users'>\n * console.log(response.error.response); // FetchResponse<Schema, 'GET', '/users'>\n * }\n *\n * @see {@link https://github.com/zimicjs/zimic/wiki/api‐zimic‐fetch#fetchresponseerror `FetchResponseError` API reference}\n */\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 get cause() {\n return this.response;\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","var __defProp = Object.defineProperty;\nvar __name = (target, value) => __defProp(target, \"name\", { value, configurable: true });\n\nexport { __name };\n//# sourceMappingURL=chunk-PAWJFY3S.mjs.map\n//# sourceMappingURL=chunk-PAWJFY3S.mjs.map","export const URL_PATH_PARAM_REGEX = /\\/:([^/]+)/g;\n\nfunction createRegExpFromURL(url: string) {\n URL_PATH_PARAM_REGEX.lastIndex = 0;\n\n const urlWithReplacedPathParams = encodeURI(url)\n .replace(/([.()*?+$\\\\])/g, '\\\\$1')\n .replace(URL_PATH_PARAM_REGEX, '/(?<$1>[^/]+)')\n .replace(/^(\\/)|(\\/)$/g, '');\n\n return new RegExp(`^(?:/)?${urlWithReplacedPathParams}(?:/)?$`);\n}\n\nexport default createRegExpFromURL;\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 createRegexFromURL from '@zimic/utils/url/createRegExpFromURL';\nimport excludeURLParams from '@zimic/utils/url/excludeURLParams';\nimport joinURL from '@zimic/utils/url/joinURL';\n\nimport FetchResponseError from './errors/FetchResponseError';\nimport {\n FetchInput,\n FetchOptions,\n Fetch,\n FetchClient as PublicFetchClient,\n FetchDefaults,\n FetchFunction,\n} from './types/public';\nimport { FetchRequestConstructor, FetchRequestInit, FetchRequest, FetchResponse } from './types/requests';\n\nclass FetchClient<Schema extends HttpSchema>\n implements Omit<PublicFetchClient<Schema>, 'defaults' | 'loose' | 'Request'>\n{\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 FetchFunction.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 satisfies FetchResponse.Loose['request'],\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 const headersFromRequest = new HttpHeaders(input.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 createRegexFromURL(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/**\n * Creates a {@link https://github.com/zimicjs/zimic/wiki/api‐zimic‐fetch#fetch fetch instance} typed with an HTTP\n * schema, closely compatible with the {@link https://developer.mozilla.org/docs/Web/API/Fetch_API native Fetch API}. All\n * requests and responses are typed by default with the schema, including methods, paths, status codes, parameters, and\n * bodies.\n *\n * Requests sent by the fetch instance have their URL automatically prefixed with the base URL of the instance.\n * {@link https://github.com/zimicjs/zimic/wiki/api‐zimic‐fetch#fetch.defaults Default options} are also applied to the\n * requests, if provided.\n *\n * @example\n * import { type HttpSchema } from '@zimic/http';\n * import { createFetch } from '@zimic/fetch';\n *\n * interface User {\n * id: string;\n * username: string;\n * }\n *\n * type Schema = HttpSchema<{\n * '/users': {\n * POST: {\n * request: {\n * headers: { 'content-type': 'application/json' };\n * body: { username: string };\n * };\n * response: {\n * 201: { body: User };\n * };\n * };\n *\n * GET: {\n * request: {\n * searchParams: {\n * query?: string;\n * page?: number;\n * limit?: number;\n * };\n * };\n * response: {\n * 200: { body: User[] };\n * };\n * };\n * };\n * }>;\n *\n * const fetch = createFetch<Schema>({\n * baseURL: 'http://localhost:3000',\n * });\n *\n * @see {@link https://github.com/zimicjs/zimic/wiki/api‐zimic‐fetch#createfetch `createFetch(options)` API reference}\n * @see {@link https://github.com/zimicjs/zimic/wiki/api‐zimic‐fetch#fetch `fetch` API reference}\n */\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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zimic/fetch",
3
- "description": "TypeScript-first Fetch Client",
3
+ "description": "TypeScript-first fetch-like API client",
4
4
  "keywords": [
5
5
  "zimic",
6
6
  "fetch",
@@ -13,7 +13,7 @@
13
13
  "api",
14
14
  "static"
15
15
  ],
16
- "version": "0.1.0-canary.9",
16
+ "version": "0.1.1-canary.1",
17
17
  "repository": {
18
18
  "type": "git",
19
19
  "url": "https://github.com/zimicjs/zimic.git",
@@ -56,19 +56,20 @@
56
56
  "./package.json": "./package.json"
57
57
  },
58
58
  "devDependencies": {
59
- "@types/node": "^22.13.5",
60
- "@vitest/browser": "^3.0.6",
61
- "@vitest/coverage-istanbul": "^3.0.6",
59
+ "@types/node": "^22.13.8",
60
+ "@vitest/browser": "^3.0.7",
61
+ "@vitest/coverage-istanbul": "^3.0.7",
62
62
  "dotenv-cli": "^8.0.0",
63
63
  "eslint": "^9.21.0",
64
64
  "playwright": "^1.50.1",
65
- "tsup": "^8.3.6",
66
- "typescript": "^5.7.3",
67
- "vitest": "^3.0.6",
65
+ "tsup": "^8.4.0",
66
+ "typescript": "^5.8.2",
67
+ "vitest": "^3.0.7",
68
68
  "@zimic/eslint-config-node": "0.0.0",
69
- "@zimic/interceptor": "0.14.0-canary.19",
69
+ "@zimic/tsconfig": "0.0.0",
70
+ "@zimic/interceptor": "0.14.0",
70
71
  "@zimic/lint-staged-config": "0.0.0",
71
- "@zimic/tsconfig": "0.0.0"
72
+ "@zimic/utils": "0.0.0"
72
73
  },
73
74
  "peerDependencies": {
74
75
  "@zimic/http": "^0.1.0 || ^0.1.0-canary.0",
@@ -86,7 +87,6 @@
86
87
  "test": "dotenv -v NODE_ENV=test -- vitest",
87
88
  "test:turbo": "dotenv -v CI=true -- pnpm run test run --coverage",
88
89
  "types:check": "tsc --noEmit",
89
- "deps:init": "playwright install chromium",
90
- "prepublish:patch-relative-paths": "sed -E -i 's/\\]\\(\\.\\/([^\\)]+)\\)/](..\\/..\\/\\1)/g;s/\"\\.\\/([^\"]+)\"/\"..\\/..\\/\\1\"/g'"
90
+ "deps:init": "playwright install chromium"
91
91
  }
92
92
  }