1000fetches 0.2.1 → 0.3.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.
Files changed (47) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +168 -109
  3. package/dist/client/index.d.ts +23 -0
  4. package/dist/contract/index.d.ts +6 -0
  5. package/dist/core.d.ts +83 -0
  6. package/dist/errors/errors.d.ts +111 -0
  7. package/dist/errors/handling.d.ts +2 -0
  8. package/dist/errors/index.d.ts +1 -0
  9. package/dist/index.cjs +2 -0
  10. package/dist/index.cjs.map +1 -0
  11. package/dist/index.d.ts +7 -347
  12. package/dist/index.mjs +2 -0
  13. package/dist/index.mjs.map +1 -0
  14. package/dist/request/abort/abort.d.ts +12 -0
  15. package/dist/request/abort/index.d.ts +1 -0
  16. package/dist/request/fetchErrors/fetchErrors.d.ts +4 -0
  17. package/dist/request/fetchErrors/index.d.ts +1 -0
  18. package/dist/request/middleware/index.d.ts +1 -0
  19. package/dist/request/middleware/middleware.d.ts +7 -0
  20. package/dist/request/request.d.ts +16 -0
  21. package/dist/request/retry/index.d.ts +1 -0
  22. package/dist/request/retry/retry.d.ts +20 -0
  23. package/dist/request/serialization/index.d.ts +1 -0
  24. package/dist/request/serialization/serialization.d.ts +9 -0
  25. package/dist/request/url.d.ts +3 -0
  26. package/dist/response.d.ts +12 -0
  27. package/dist/retry-BWvlSmME.cjs +2 -0
  28. package/dist/retry-BWvlSmME.cjs.map +1 -0
  29. package/dist/retry-D07aIs-1.js +2 -0
  30. package/dist/retry-D07aIs-1.js.map +1 -0
  31. package/dist/schema/index.d.ts +35 -0
  32. package/dist/status.d.ts +2 -0
  33. package/dist/types.d.ts +150 -0
  34. package/dist/utils/index.d.ts +1 -0
  35. package/dist/utils/path.d.ts +71 -0
  36. package/docs/BEST_PRACTICES.md +685 -0
  37. package/package.json +52 -56
  38. package/skills/1000fetches/SKILL.md +35 -0
  39. package/skills/1000fetches/references/client-setup-and-defaults.md +49 -0
  40. package/skills/1000fetches/references/contracts-and-errors.md +50 -0
  41. package/skills/1000fetches/references/path-params-and-urls.md +39 -0
  42. package/skills/1000fetches/references/retries-timeouts-and-middleware.md +32 -0
  43. package/skills/1000fetches/references/serialization-and-body-types.md +22 -0
  44. package/dist/index.cjs.js +0 -2
  45. package/dist/index.cjs.js.map +0 -1
  46. package/dist/index.es.js +0 -793
  47. package/dist/index.es.js.map +0 -1
@@ -0,0 +1,111 @@
1
+ import { StandardSchemaV1 } from '@standard-schema/spec';
2
+ interface HttpClientError {
3
+ name: string;
4
+ message: string;
5
+ cause?: Error;
6
+ stack?: string;
7
+ }
8
+ export declare class HttpError<TErrorData = unknown> extends Error implements HttpClientError {
9
+ readonly name = "HttpError";
10
+ readonly status: number;
11
+ readonly statusText: string;
12
+ readonly data: TErrorData;
13
+ readonly response: Response;
14
+ readonly url: string;
15
+ readonly method: string;
16
+ readonly cause?: Error;
17
+ constructor(message: string, status: number, statusText: string, data: TErrorData, response: Response, url: string, method: string, cause?: Error);
18
+ }
19
+ export declare class NetworkError extends Error implements HttpClientError {
20
+ readonly name = "NetworkError";
21
+ readonly cause?: Error;
22
+ constructor(message: string, cause?: Error);
23
+ }
24
+ export declare class SchemaValidationError extends Error implements HttpClientError {
25
+ readonly name: string;
26
+ readonly schema: unknown;
27
+ readonly data: unknown;
28
+ readonly issues?: ReadonlyArray<StandardSchemaV1.Issue>;
29
+ readonly cause?: Error;
30
+ constructor(message: string, schema: unknown, data: unknown, cause?: Error, issues?: ReadonlyArray<StandardSchemaV1.Issue>);
31
+ }
32
+ export declare class ContractValidationError extends SchemaValidationError {
33
+ readonly name = "ContractValidationError";
34
+ readonly branch: 'success' | 'error';
35
+ readonly status: number;
36
+ readonly statusText: string;
37
+ readonly response: Response;
38
+ readonly url: string;
39
+ readonly method: string;
40
+ constructor(message: string, schema: unknown, data: unknown, response: {
41
+ status: number;
42
+ statusText: string;
43
+ raw: Response;
44
+ url: string;
45
+ method: string;
46
+ }, branch: 'success' | 'error', cause?: Error, issues?: ReadonlyArray<StandardSchemaV1.Issue>);
47
+ }
48
+ export declare class InvalidContractError extends Error implements HttpClientError {
49
+ readonly name = "InvalidContractError";
50
+ readonly contract: unknown;
51
+ readonly status?: number;
52
+ readonly branch?: 'success' | 'error';
53
+ readonly cause?: Error;
54
+ constructor(message: string, contract: unknown, status?: number, branch?: 'success' | 'error', cause?: Error);
55
+ }
56
+ export declare class TimeoutError extends Error implements HttpClientError {
57
+ readonly name = "TimeoutError";
58
+ readonly cause?: Error;
59
+ constructor(message: string, cause?: Error);
60
+ }
61
+ /**
62
+ * Thrown when a request is cancelled by a caller-provided AbortSignal.
63
+ *
64
+ * Timeouts are reported as TimeoutError; this class represents explicit
65
+ * cancellation only.
66
+ */
67
+ export declare class AbortError extends Error implements HttpClientError {
68
+ readonly name = "AbortError";
69
+ readonly cause?: Error;
70
+ constructor(message?: string, cause?: Error);
71
+ }
72
+ export declare class PathParameterError extends Error implements HttpClientError {
73
+ readonly name = "PathParameterError";
74
+ readonly url: string;
75
+ readonly requiredParams: string[];
76
+ readonly providedParams: string[];
77
+ readonly cause?: Error;
78
+ constructor(message: string, url: string, requiredParams: string[], providedParams: string[], cause?: Error);
79
+ }
80
+ export declare class MiddlewareError extends Error implements HttpClientError {
81
+ readonly name = "MiddlewareError";
82
+ readonly type: 'request' | 'response';
83
+ readonly url?: string;
84
+ readonly method?: string;
85
+ readonly cause?: Error;
86
+ constructor(message: string, type: 'request' | 'response', url?: string, method?: string, cause?: Error);
87
+ }
88
+ export declare class SerializationError extends Error implements HttpClientError {
89
+ readonly name = "SerializationError";
90
+ readonly cause?: Error;
91
+ constructor(message: string, cause?: Error);
92
+ }
93
+ declare abstract class SchemaDefinitionError extends Error implements HttpClientError {
94
+ abstract readonly name: string;
95
+ readonly schema: unknown;
96
+ readonly cause?: Error;
97
+ constructor(message: string, schema: unknown, cause?: Error);
98
+ }
99
+ export declare class InvalidSchemaError extends SchemaDefinitionError {
100
+ readonly name = "InvalidSchemaError";
101
+ }
102
+ export declare class AsyncSchemaValidationError extends SchemaDefinitionError {
103
+ readonly name = "AsyncSchemaValidationError";
104
+ }
105
+ export declare class InvalidBaseUrlError extends Error implements HttpClientError {
106
+ readonly name = "InvalidBaseUrlError";
107
+ readonly baseUrl: string;
108
+ readonly cause?: Error;
109
+ constructor(message: string, baseUrl: string, cause?: Error);
110
+ }
111
+ export {};
@@ -0,0 +1,2 @@
1
+ export declare function createErrorMessage(context: string, error: unknown): string;
2
+ export declare function createStandardizedError(error: unknown, context: string): Error;
@@ -0,0 +1 @@
1
+ export { AbortError, AsyncSchemaValidationError, ContractValidationError, HttpError, InvalidBaseUrlError, InvalidContractError, InvalidSchemaError, MiddlewareError, NetworkError, PathParameterError, SchemaValidationError, SerializationError, TimeoutError, } from './errors';
package/dist/index.cjs ADDED
@@ -0,0 +1,2 @@
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});var t=class extends Error{name="HttpError";status;statusText;data;response;url;method;cause;constructor(t,e,r,s,a,n,o,i){const c=`HTTP ${e>=500?"Server Error":e>=400?"Client Error":e>=300?"Redirect":"Success"} (${e}): ${t}\nRequest: ${o} ${n}\nData: ${function(t){if(null==t||""===t)return"No response data";let e;try{e="string"==typeof t?t:JSON.stringify(t)}catch{e=String(t)}return e.length>500?e.substring(0,500)+"...":e}(s)}`;super(c,{cause:i}),this.status=e,this.statusText=r,this.data=s,this.response=a,this.url=n,this.method=o,this.cause=i}},e=class extends Error{name="NetworkError";cause;constructor(t,e){super(t,{cause:e}),this.cause=e}},r=class extends Error{name="SchemaValidationError";schema;data;issues;cause;constructor(t,e,r,s,a){super(t,{cause:s}),this.schema=e,this.data=r,this.issues=a,this.cause=s}},s=class extends r{name="ContractValidationError";branch;status;statusText;response;url;method;constructor(t,e,r,s,a,n,o){super(`${t}\nRequest: ${s.method} ${s.url}\nStatus: ${s.status} ${s.statusText}`,e,r,n,o),this.branch=a,this.status=s.status,this.statusText=s.statusText,this.response=s.raw,this.url=s.url,this.method=s.method}},a=class extends Error{name="InvalidContractError";contract;status;branch;cause;constructor(t,e,r,s,a){super(t,{cause:a}),this.contract=e,this.status=r,this.branch=s,this.cause=a}},n=class extends Error{name="TimeoutError";cause;constructor(t,e){super(t,{cause:e}),this.cause=e}},o=class extends Error{name="AbortError";cause;constructor(t="The operation was aborted",e){super(t,{cause:e}),this.cause=e}},i=class extends Error{name="PathParameterError";url;requiredParams;providedParams;cause;constructor(t,e,r,s,a){super(`${t}\nURL Template: ${e}\nExpected: [${r.map(t=>`"${t}"`).join(", ")}], Actual: [${s.map(t=>`"${t}"`).join(", ")}]`,{cause:a}),this.url=e,this.requiredParams=r,this.providedParams=s,this.cause=a}},c=class extends Error{name="MiddlewareError";type;url;method;cause;constructor(t,e,r,s,a){const n=r?`Request: ${s||"UNKNOWN"} ${r}`:"";super(n?`${t}\n${n}`:t,{cause:a}),this.type=e,this.url=r,this.method=s,this.cause=a}},u=class extends Error{name="SerializationError";cause;constructor(t,e){super(t,{cause:e}),this.cause=e}},d=class extends Error{schema;cause;constructor(t,e,r){super(t,{cause:r}),this.schema=e,this.cause=r}},l=class extends d{name="InvalidSchemaError"},h=class extends Error{name="InvalidBaseUrlError";baseUrl;cause;constructor(t,e,r){super(`${t}\nBase URL: ${e}`,{cause:r}),this.baseUrl=e,this.cause=r}};function f(t,e={}){return function(t,e){const r=t.match(/(^|\/):([^/\s?#]+)\?(?=\/)/);if(!r)return;const[,,s]=r;throw new i(`Optional path parameter "${s}" is not supported here. Optional path parameters are only supported at the end of the path.`,t,[s],e)}(t,Object.keys(e)),t.replace(/(^|\/):([^/\s?#]+?)(\?)?(?=\/|$|[?#])/g,(r,s,a,n)=>{const o="?"===n;if(!/^[a-zA-Z0-9_]+$/.test(a))throw new i(`Invalid path parameter name: "${a}"`,t,[a],Object.keys(e));const c=e[a];if(void 0===c){if(o)return"";throw new i(`Missing required path parameter: "${a}"`,t,[a],Object.keys(e))}return`${s}${encodeURIComponent(String(c))}`})}var p=Symbol("1000fetches.successStatusValidator");function m(t){return t>=200&&t<300}function y(t,e){const r=w(t);return void 0!==e.cache&&(r.cache=e.cache),void 0!==e.credentials&&(r.credentials=e.credentials),void 0!==e.mode&&(r.mode=e.mode),void 0!==e.redirect&&(r.redirect=e.redirect),r}function w(t){const e={...t??{}},r=e;return delete r.body,delete r.headers,delete r.method,delete r.signal,e}function b(t){if(ArrayBuffer.isView(t)){const e=new Uint8Array(t.buffer,t.byteOffset,t.byteLength);return{body:new Uint8Array(e).buffer}}return"string"==typeof t||t instanceof FormData||t instanceof URLSearchParams||t instanceof ArrayBuffer||t instanceof Blob||t instanceof ReadableStream?{body:t}:null!==(e=t)&&"object"==typeof e&&(Array.isArray(e)||"toJSON"in e&&"function"==typeof e.toJSON||"[object Object]"===Object.prototype.toString.call(e))?{body:JSON.stringify(t),contentType:"application/json"}:null==t?{body:""}:{body:String(t)};var e}function v(t){return t instanceof Date?t.toISOString():String(t)}function E(t,e){return T(e)?e:T(t)?function(t,e){const r=new URL(t),s=r.pathname.replace(/\/$/,""),{path:a,search:n,hash:o}=$(e);a.startsWith("/")?r.pathname=s+a:a&&(r.pathname=s+"/"+a);n&&(r.search=g(r.search,n));o&&(r.hash=o);return r.toString()}(t,e):function(t,e){const{path:r,search:s,hash:a}=$(t),{path:n,search:o,hash:i}=$(e);return`${n?function(t,e){return t?e?e.startsWith("/")?`${t}${e}`:`${t}/${e}`:t:e.startsWith("/")?e:`/${e}`}(r,n):r||n}${g(s,o)}${i||a}`}(t,e)}function x(t,e){if(e&&!T(t)&&("undefined"==typeof window||void 0===window.location||"null"===window.location.origin))throw new h(`Relative request URL "${t}" requires an absolute baseUrl in non-browser environments. Pass an absolute baseUrl or use a custom fetch implementation.`,t)}function $(t){const e=t.indexOf("#"),r=-1===e?"":t.slice(e),s=-1===e?t:t.slice(0,e),a=s.indexOf("?");return{path:-1===a?s:s.slice(0,a),search:-1===a?"":s.slice(a),hash:r}}function g(t,e){return t?e?`${t}&${e.slice(1)}`:t:e}function T(t){return/^[a-zA-Z][a-zA-Z\d+\-.]*:\/\//.test(t)}function S(t,e){return`${t}: ${e instanceof Error?e.message:String(e)}`}function R(t,e){return t instanceof Error?t:new Error(`${e}: ${String(t)}`)}async function O(t,e){const r=Object.fromEntries(t.headers.entries());let s,a;if(n=t.status,"HEAD"===e.method.toUpperCase()||204===n||205===n||304===n)return{data:void 0,status:t.status,statusText:t.statusText,headers:r,method:e.method,url:e.url,raw:t};var n;const o=t.clone(),i=e.responseType??function(t){const e=(t.headers.get("content-type")?.toLowerCase()??"").split(";",1)[0]?.trim()??"";if(function(t){return"application/json"===t||t.startsWith("application/")&&t.endsWith("+json")}(e))return"json";if(e.startsWith("text/"))return"text";if("application/octet-stream"===e||"application/pdf"===e||e.startsWith("image/")||e.startsWith("video/")||e.startsWith("audio/"))return"arrayBuffer";if("multipart/form-data"===e||"application/x-www-form-urlencoded"===e)return"formData"}(t);let c;const d=!0!==e.tolerateParseError||"blob"!==i&&"arrayBuffer"!==i&&"formData"!==i?void 0:t.clone();try{"json"===i?(c=await o.text(),s=JSON.parse(c)):"text"===i?s=await o.text():"blob"===i?s=await o.blob():"arrayBuffer"===i?s=await o.arrayBuffer():"formData"===i?s=await o.formData():(c=await o.text(),s=function(t){try{return JSON.parse(t)}catch{return t}}(c))}catch(l){if(a=new u(S("Failed to parse response body",l),l instanceof Error?l:void 0),!e.tolerateParseError)throw a;if(void 0!==c)s=c;else if(d)try{s=await d.text()}catch{s=""}else s=""}return{data:s,status:t.status,statusText:t.statusText,headers:r,method:e.method,url:e.url,raw:t,parseError:a}}function j(t,{didTimeout:e,finalSignal:r,timeout:s}){let a=R(t,"Request execution");return U(a)&&e?new n(`Request timeout after ${s}ms`,a):((U(a)||r?.aborted)&&(a=a instanceof o?a:new o(a.message,a)),a)}function P(t,e){return t<=0?Promise.resolve():e?.aborted?Promise.reject(N(e.reason)):new Promise((r,s)=>{const a=setTimeout(()=>{e?.removeEventListener("abort",n),r()},t),n=()=>{clearTimeout(a),e?.removeEventListener("abort",n),s(N(e?.reason))};e?.addEventListener("abort",n,{once:!0})})}function q(t){return t instanceof Error&&"AbortError"===t.name?new o("Request aborted by caller",t):N(t)}function A(t,e){if(!t&&!e)return{signal:void 0,cleanup:()=>{}};if(!t)return{signal:e,cleanup:()=>{}};if(!e)return{signal:t,cleanup:()=>{}};if(t.aborted)return{signal:t,cleanup:()=>{}};if(e.aborted)return{signal:e,cleanup:()=>{}};const r=new AbortController,s=t=>{const e=t.target;e instanceof AbortSignal?r.abort(e.reason):r.abort()};return t.addEventListener("abort",s,{once:!0}),e.addEventListener("abort",s,{once:!0}),{signal:r.signal,cleanup:()=>{t.removeEventListener("abort",s),e.removeEventListener("abort",s)}}}function U(t){return t instanceof Error&&"AbortError"===t.name}function N(t){return t instanceof o?t:t instanceof Error?new o(t.message,t):new o}async function L(t,r,s){try{return await t(r,s)}catch(a){const t=R(a,"Network request failed");if(U(t)||t instanceof e)throw t;throw new e(t.message,t)}}function I(e,r){return new t(`HTTP ${e.status} ${e.statusText}`,e.status,e.statusText,e.data,e.raw,e.url,e.method,r)}async function C({onResponseMiddleware:t,response:e,url:r,method:s}){if(!t)return e;try{const n=await t(e);if(!(null!==(a=n)&&"object"==typeof a&&"data"in a&&"status"in a&&"number"==typeof a.status&&"statusText"in a&&"string"==typeof a.statusText&&"headers"in a&&"object"==typeof a.headers&&null!==a.headers&&"method"in a&&"string"==typeof a.method&&"url"in a&&"string"==typeof a.url&&"raw"in a&&a.raw instanceof Response))throw new c("Response middleware must return a valid ResponseType object","response",r,s);return n}catch(n){if(n instanceof c)throw n;throw new c(S("Response middleware failed",n),"response",r,s,R(n,"Response middleware"))}var a}async function H({fetchImplementation:t,requestInit:e,requestRetry:r,clientRetry:s,url:a,method:n,timeout:o,signal:i,responseType:c,onResponseMiddleware:u,isExpectedStatus:d}){const l=function(t,e){return!1!==e&&(!0===t||"object"==typeof t||!0===e||"object"==typeof e)}(s,r)?await Promise.resolve().then(()=>require("./retry-BWvlSmME.cjs")):void 0,h=l?.createRetryPolicy(s,r),f=h?.maxRetries??0,p=!(e.body instanceof ReadableStream);let m;for(let w=0;w<=f;w+=1){const r=new AbortController;let s=!1;const b=setTimeout(()=>{s=!0,r.abort()},o),{signal:v,cleanup:E}=A(i,r.signal);let x=!1;const $=()=>{x||(x=!0,clearTimeout(b),E())};try{if(v?.aborted)throw q(v.reason);const r=await L(t,a,{...e,signal:v}),s=await O(r,{responseType:c,method:n,url:a,tolerateParseError:!d(r.status)}),o=await C({onResponseMiddleware:u,response:s,url:a,method:n});if(!d(o.status))throw I(o,s.parseError);return o}catch(y){if(m=j(y,{didTimeout:s,finalSignal:v,timeout:o}),w>=f||!l||!(await l.shouldRetry(m,w,h,{bodyReplayable:p,method:n,url:a})))throw m;const t=l.calculateRetryDelay(w,h,m);await l.notifyRetry(h,{bodyReplayable:p,delay:t,error:m,method:n,nextAttempt:w+1,retryCount:w,url:a}),$(),await P(t,i)}finally{$()}}throw new Error("Retry loop terminated unexpectedly")}function V(t={}){const{baseUrl:e="",headers:r={},timeout:s=3e4,fetch:a,serializeBody:n,serializeParams:o,defaults:i,onRequestMiddleware:u,onResponseMiddleware:d}=t,l=void 0===a;return async function(h,g={}){const T=g.method??"GET",O=g.pathParams,j=g[p],P=void 0===O?f(h):f(h,O);let q;i&&(q=await i({path:h,resolvedPath:P,method:T,params:g.params,pathParams:O,body:g.body,hasBody:void 0!==g.body,requestOptions:W(g),baseUrl:e,headers:{...r},timeout:s,retry:t.retry}));const A=e?E(e,P):P,U=function(t,e){const r=y(t?.fetchOptions,{cache:t?.cache,credentials:t?.credentials,mode:t?.mode,redirect:t?.redirect}),s=y(e.fetchOptions,{cache:e.cache,credentials:e.credentials,mode:e.mode,redirect:e.redirect});return{...r,...s}}(q,g),N=new Headers(r);k(N,q?.headers),k(N,g.headers);const L=function(t,e){return t?e?{...t,...e}:t:e}(q?.params,g.params),I=g.timeout??q?.timeout??s,C=g.retry??q?.retry,V=g.responseType??q?.responseType,B={url:A,method:T,params:L,headers:N,body:g.body,signal:g.signal,fetchOptions:U};let M=B;if(u)try{const t={...B,headers:new Headers(B.headers),fetchOptions:{...B.fetchOptions}},e=await u(t);if(void 0===e)M=t;else{if(!(null!==(D=e)&&"object"==typeof D&&"url"in D&&"string"==typeof D.url&&"method"in D&&"string"==typeof D.method&&"headers"in D&&D.headers instanceof Headers&&"fetchOptions"in D&&"object"==typeof D.fetchOptions&&null!==D.fetchOptions))throw new c("Request middleware must return a valid RequestContext object","request",M.url,M.method);M=e}}catch(J){if(J instanceof c)throw J;throw new c(S("Request middleware failed",J),"request",M.url,M.method,R(J,"Request middleware"))}var D;if(M.params){const t=o?o(M.params):function(t){const e=new URLSearchParams;for(const[r,s]of Object.entries(t))if(Array.isArray(s))for(const t of s)null!=t&&e.append(r,v(t));else null!=s&&e.append(r,v(s));return e.toString()}(M.params);t&&(M.url=function(t,e){const r=e.startsWith("?")?e.slice(1):e;if(!r)return t;const{path:s,search:a,hash:n}=$(t);return`${s}${a?`${a}&${r}`:`?${r}`}${n}`}(M.url,t))}x(M.url,l);const z={...w(M.fetchOptions),method:M.method,headers:M.headers};if(void 0!==M.body&&"GET"!==M.method&&"HEAD"!==M.method){let t,e;if(n){const e=n(M.body);t=null==e?"":e}else{const r=b(M.body);t=r.body,e=r.contentType}z.body=t,e&&!M.headers.has("content-type")&&M.headers.set("content-type",e),z.duplex="half"}return H({fetchImplementation:a??globalThis.fetch,requestInit:z,clientRetry:t.retry,requestRetry:C,url:M.url,method:M.method,timeout:I,signal:M.signal,responseType:V,onResponseMiddleware:d,isExpectedStatus:j??m})}}function W(t){return{...t,headers:t.headers?{...t.headers}:void 0,params:t.params?{...t.params}:void 0,pathParams:t.pathParams?{...t.pathParams}:void 0,fetchOptions:t.fetchOptions?{...t.fetchOptions}:void 0}}function k(t,e){if(e)for(const[r,s]of Object.entries(e))t.set(r,s)}async function B(e,r,s){try{const t=await r;return await D(e,z(e,t.status,!0),t,"success",{schemaValidator:s})}catch(a){if(!(a instanceof t))throw a;return await async function(e,r,s){const a=function(t){return{data:t.data,status:t.status,statusText:t.statusText,headers:Object.fromEntries(t.response.headers.entries()),method:t.method,url:t.url,raw:t.response}}(r),n=z(e,r.status,!1);if(n)return await D(e,n,a,"success",{schemaValidator:s});const o=function(t,e){if(!K(t)||!t.error)return;return J(t.error,e,!0)}(e,r.status);if(!o)throw r;const i=await G(o,a,"error",s);throw new t(`HTTP ${r.status} ${r.statusText}`,r.status,r.statusText,i,r.response,r.url,r.method,r.cause)}(e,a,s)}}function M(t,e,r){if(!F(t)){if(!Z(t))throw new a(("success"===r?"Success":"Error")+" response contract branch must be a schema or status map",e,void 0,r);for(const s of Object.keys(t))_(s,e,r)}}async function D(t,e,r,s,a){const n=await G(e,r,s,a.schemaValidator);return{...r,data:n}}function z(t,e,r){if(!K(t))return r?t:void 0;const s=J(t.success,e,r);if(!s&&r)throw new a(`No success response contract found for status ${e}`,t,e,"success");return s}function J(t,e,r){if(F(t))return r?t:void 0;const s=t;return s[String(e)]??(r?s.default:void 0)}async function G(t,e,a,n){try{return await n.validate(t,e.data)}catch(o){if(o instanceof l)throw o;throw new s(`${"success"===a?"Success":"Error"} response failed contract validation${o instanceof Error?`: ${o.message}`:""}`,t,e.data,e,a,o instanceof Error?o:void 0,o instanceof r?o.issues:void 0)}}function Z(t){return null!==t&&"object"==typeof t&&!Array.isArray(t)}function F(t){return null!==t&&("object"==typeof t||"function"==typeof t)&&"~standard"in t}function K(t){return Z(t)&&!F(t)}function _(t,e,r){if("default"===t)return;const s=Number(t);if(!Number.isInteger(s)||s<100||s>=600)throw new a('Response contract status map keys must be HTTP status codes or "default"',e,void 0,r);if("success"===r&&(s<200||s>=400))throw new a("Success response contract status keys must be 2xx or 3xx status codes",e,s,r);if("error"===r&&(s<400||s>=600))throw new a("Error response contract status keys must be 4xx or 5xx status codes",e,s,r)}function Q(t,e,s){if(s.issues)throw new r(JSON.stringify(s.issues),t,e,void 0,s.issues);return s.value}function X(){return{validate(t,e){if(null===(r=t)||"object"!=typeof r&&"function"!=typeof r||!("~standard"in r)||"object"!=typeof r["~standard"]||null===r["~standard"]||!("validate"in r["~standard"])||"function"!=typeof r["~standard"].validate||!("version"in r["~standard"])||1!==r["~standard"].version||!("vendor"in r["~standard"])||"string"!=typeof r["~standard"].vendor)throw new l("Schema must implement the Standard Schema interface",t);var r;const s=t["~standard"].validate(e);return null===(a=s)||"object"!=typeof a&&"function"!=typeof a||!("then"in a)||"function"!=typeof a.then?Q(t,e,s):Promise.resolve(s).then(r=>Q(t,e,r));var a}}}function Y(t){if(!t)return"";if(t.startsWith("/"))return t.replace(/\/$/,"");try{new URL(t)}catch{throw new h(`Invalid baseUrl: "${t}". Must be a valid absolute URL or relative path starting with "/".`,t)}return t.endsWith("/")?t.slice(0,-1):t}function tt(t){const e=t;return e.data=async()=>(await t).data,e.void=async()=>{await t},e}function et(t,e,r,s){let n,o;const i=e=>(n??=r(t,e),n),c=new Promise((t,r)=>{queueMicrotask(()=>{void 0===o?i(e).then(e=>t(e),r):r(o)})});c.catch(()=>{});const u=tt(c);return u.contract=t=>{try{if(function(t){if(!F(t)){if(!Z(t))throw new a("Response contract must be a schema or an object with a success branch",t);if(!("success"in t))throw new a("Response contract object must include a success branch",t,void 0,"success");M(t.success,t,"success"),"error"in t&&void 0!==t.error&&M(t.error,t,"error")}}(t),o=void 0,void 0!==n)throw new a("Cannot attach a response contract after the request has started",t);return tt(B(t,i(function(t,e){if(!K(e)||F(e.success))return t;const r=e.success;return Object.keys(r).some(t=>"default"!==t&&Number.isInteger(Number(t)))?{...t,[p]:t=>m(t)||Object.hasOwn(r,t)}:t}(e,t)),s))}catch(r){return void 0===n&&(o=r),tt(Promise.reject(r))}},u}exports.AbortError=o,exports.AsyncSchemaValidationError=class extends d{name="AsyncSchemaValidationError"},exports.ContractValidationError=s,exports.HttpError=t,exports.InvalidBaseUrlError=h,exports.InvalidContractError=a,exports.InvalidSchemaError=l,exports.MiddlewareError=c,exports.NetworkError=e,exports.PathParameterError=i,exports.SchemaValidationError=r,exports.SerializationError=u,exports.TimeoutError=n,exports.createHttpClient=function(t={}){const e=V({...t,baseUrl:Y(t.baseUrl)}),r=t.schemaValidator??X();function s(t){return(s,a,...n)=>et(s,{...n[0]??{},method:t,body:a},e,r)}return{get:function(t,...s){return et(t,{...s[0]??{},method:"GET"},e,r)},post:s("POST"),put:s("PUT"),patch:s("PATCH"),delete:(t,...s)=>et(t,{...s[0]??{},method:"DELETE"},e,r),request:(t,...s)=>et(t,s[0]??{},e,r)}},exports.createSchemaValidator=X;
2
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.cjs","names":[],"sources":["../src/errors/errors.ts","../src/utils/path.ts","../src/status.ts","../src/request/serialization/serialization.ts","../src/request/url.ts","../src/errors/handling.ts","../src/response.ts","../src/request/abort/abort.ts","../src/request/fetchErrors/fetchErrors.ts","../src/request/middleware/middleware.ts","../src/request/request.ts","../src/core.ts","../src/contract/index.ts","../src/schema/index.ts","../src/client/index.ts"],"sourcesContent":["import type { StandardSchemaV1 } from '@standard-schema/spec'\n\ninterface HttpClientError {\n name: string\n message: string\n cause?: Error\n stack?: string\n}\n\nfunction formatErrorData(data: unknown): string {\n if (data === null || data === undefined || data === '') {\n return 'No response data'\n }\n\n let dataString: string\n\n try {\n dataString = typeof data === 'string' ? data : JSON.stringify(data)\n } catch {\n dataString = String(data)\n }\n\n return dataString.length > 500\n ? dataString.substring(0, 500) + '...'\n : dataString\n}\n\nexport class HttpError<TErrorData = unknown>\n extends Error\n implements HttpClientError\n{\n public readonly name = 'HttpError'\n public readonly status: number\n public readonly statusText: string\n public readonly data: TErrorData\n public readonly response: Response\n public readonly url: string\n public readonly method: string\n public override readonly cause?: Error\n\n constructor(\n message: string,\n status: number,\n statusText: string,\n data: TErrorData,\n response: Response,\n url: string,\n method: string,\n cause?: Error\n ) {\n const statusCategory =\n status >= 500\n ? 'Server Error'\n : status >= 400\n ? 'Client Error'\n : status >= 300\n ? 'Redirect'\n : 'Success'\n\n const enhancedMessage = `HTTP ${statusCategory} (${status}): ${message}\nRequest: ${method} ${url}\nData: ${formatErrorData(data)}`\n\n super(enhancedMessage, { cause })\n this.status = status\n this.statusText = statusText\n this.data = data\n this.response = response\n this.url = url\n this.method = method\n this.cause = cause\n }\n}\n\nexport class NetworkError extends Error implements HttpClientError {\n public readonly name = 'NetworkError'\n public override readonly cause?: Error\n\n constructor(message: string, cause?: Error) {\n super(message, { cause })\n this.cause = cause\n }\n}\n\nexport class SchemaValidationError extends Error implements HttpClientError {\n public readonly name: string = 'SchemaValidationError'\n public readonly schema: unknown\n public readonly data: unknown\n public readonly issues?: ReadonlyArray<StandardSchemaV1.Issue>\n public override readonly cause?: Error\n\n constructor(\n message: string,\n schema: unknown,\n data: unknown,\n cause?: Error,\n issues?: ReadonlyArray<StandardSchemaV1.Issue>\n ) {\n super(message, { cause })\n this.schema = schema\n this.data = data\n this.issues = issues\n this.cause = cause\n }\n}\n\nexport class ContractValidationError extends SchemaValidationError {\n public override readonly name = 'ContractValidationError'\n public readonly branch: 'success' | 'error'\n public readonly status: number\n public readonly statusText: string\n public readonly response: Response\n public readonly url: string\n public readonly method: string\n\n constructor(\n message: string,\n schema: unknown,\n data: unknown,\n response: {\n status: number\n statusText: string\n raw: Response\n url: string\n method: string\n },\n branch: 'success' | 'error',\n cause?: Error,\n issues?: ReadonlyArray<StandardSchemaV1.Issue>\n ) {\n super(\n `${message}\nRequest: ${response.method} ${response.url}\nStatus: ${response.status} ${response.statusText}`,\n schema,\n data,\n cause,\n issues\n )\n this.branch = branch\n this.status = response.status\n this.statusText = response.statusText\n this.response = response.raw\n this.url = response.url\n this.method = response.method\n }\n}\n\nexport class InvalidContractError extends Error implements HttpClientError {\n public readonly name = 'InvalidContractError'\n public readonly contract: unknown\n public readonly status?: number\n public readonly branch?: 'success' | 'error'\n public override readonly cause?: Error\n\n constructor(\n message: string,\n contract: unknown,\n status?: number,\n branch?: 'success' | 'error',\n cause?: Error\n ) {\n super(message, { cause })\n this.contract = contract\n this.status = status\n this.branch = branch\n this.cause = cause\n }\n}\n\nexport class TimeoutError extends Error implements HttpClientError {\n public readonly name = 'TimeoutError'\n public override readonly cause?: Error\n\n constructor(message: string, cause?: Error) {\n super(message, { cause })\n this.cause = cause\n }\n}\n\n/**\n * Thrown when a request is cancelled by a caller-provided AbortSignal.\n *\n * Timeouts are reported as TimeoutError; this class represents explicit\n * cancellation only.\n */\nexport class AbortError extends Error implements HttpClientError {\n public readonly name = 'AbortError'\n public override readonly cause?: Error\n\n constructor(message = 'The operation was aborted', cause?: Error) {\n super(message, { cause })\n this.cause = cause\n }\n}\n\nexport class PathParameterError extends Error implements HttpClientError {\n public readonly name = 'PathParameterError'\n public readonly url: string\n public readonly requiredParams: string[]\n public readonly providedParams: string[]\n public override readonly cause?: Error\n\n constructor(\n message: string,\n url: string,\n requiredParams: string[],\n providedParams: string[],\n cause?: Error\n ) {\n const enhancedMessage = `${message}\nURL Template: ${url}\nExpected: [${requiredParams\n .map(p => `\"${p}\"`)\n .join(', ')}], Actual: [${providedParams.map(p => `\"${p}\"`).join(', ')}]`\n\n super(enhancedMessage, { cause })\n this.url = url\n this.requiredParams = requiredParams\n this.providedParams = providedParams\n this.cause = cause\n }\n}\n\nexport class MiddlewareError extends Error implements HttpClientError {\n public readonly name = 'MiddlewareError'\n public readonly type: 'request' | 'response'\n public readonly url?: string\n public readonly method?: string\n public override readonly cause?: Error\n\n constructor(\n message: string,\n type: 'request' | 'response',\n url?: string,\n method?: string,\n cause?: Error\n ) {\n const requestInfo = url ? `Request: ${method || 'UNKNOWN'} ${url}` : ''\n const enhancedMessage = requestInfo ? `${message}\\n${requestInfo}` : message\n\n super(enhancedMessage, { cause })\n this.type = type\n this.url = url\n this.method = method\n this.cause = cause\n }\n}\n\nexport class SerializationError extends Error implements HttpClientError {\n public readonly name = 'SerializationError'\n public override readonly cause?: Error\n\n constructor(message: string, cause?: Error) {\n super(message, { cause })\n this.cause = cause\n }\n}\n\nabstract class SchemaDefinitionError extends Error implements HttpClientError {\n public abstract readonly name: string\n public readonly schema: unknown\n public override readonly cause?: Error\n\n constructor(message: string, schema: unknown, cause?: Error) {\n super(message, { cause })\n this.schema = schema\n this.cause = cause\n }\n}\n\nexport class InvalidSchemaError extends SchemaDefinitionError {\n public readonly name = 'InvalidSchemaError'\n}\n\nexport class AsyncSchemaValidationError extends SchemaDefinitionError {\n public readonly name = 'AsyncSchemaValidationError'\n}\n\nexport class InvalidBaseUrlError extends Error implements HttpClientError {\n public readonly name = 'InvalidBaseUrlError'\n public readonly baseUrl: string\n public override readonly cause?: Error\n\n constructor(message: string, baseUrl: string, cause?: Error) {\n const enhancedMessage = `${message}\nBase URL: ${baseUrl}`\n\n super(enhancedMessage, { cause })\n this.baseUrl = baseUrl\n this.cause = cause\n }\n}\n","import { PathParameterError } from '../errors'\n\n/**\n * Strips host and optional port from URL, keeping only the path\n */\ntype StripHost<T extends string> = T extends `${infer _Host}/${infer Path}`\n ? `/${Path}`\n : T\n\n/**\n * Strips protocol and host from full URLs, keeping bare relative paths intact.\n */\ntype StripUrlOrigin<T extends string> = T extends `${string}://${infer After}`\n ? StripHost<After>\n : T\n\n/**\n * Strips query string from path (e.g., \"/users?x=1\" -> \"/users\")\n * Only strips ? that comes after the path, not ? that's part of path parameters\n */\ntype StripQuery<T extends string> = T extends `${infer Path}?${infer Query}`\n ? Query extends\n | `${string}=${string}`\n | `${string}&${string}`\n | `${string}=${string}&${string}`\n ? Path // Contains query parameters (has = or &)\n : Query extends `/${string}`\n ? T // It's another path segment, not a query\n : Query extends ``\n ? T // It's an optional param marker (?)\n : Path // Plain query params like ?param\n : T\n\n/**\n * Normalizes URL to path only, stripping protocol, host, port, and query\n */\ntype NormalizePath<T extends string> = StripQuery<StripUrlOrigin<T>>\n\n/**\n * Removes optional suffix from param name (e.g., \":id?\" -> \"id\", \":id\" -> \"id\")\n */\ntype CleanParamName<S extends string> = S extends `:${infer Name}?`\n ? Name\n : S extends `:${infer Name}`\n ? Name\n : S\n\n/**\n * Extracts required path parameters from a route\n */\ntype ExtractRequiredRouteParams<T extends string> =\n NormalizePath<T> extends `${infer _Before}:${infer AfterColon}`\n ? AfterColon extends `${infer Param}/${infer Rest}`\n ? Param extends `${string}?`\n ? ExtractRequiredRouteParams<`/${Rest}`>\n : CleanParamName<`:${Param}`> | ExtractRequiredRouteParams<`/${Rest}`>\n : AfterColon extends `${string}?`\n ? never\n : CleanParamName<`:${AfterColon}`>\n : never\n\n/**\n * Extracts optional path parameters from a route\n */\ntype ExtractOptionalRouteParams<T extends string> =\n NormalizePath<T> extends `${infer _Before}:${infer AfterColon}`\n ? AfterColon extends `${infer Param}/${infer Rest}`\n ? | (Param extends `${string}?` ? CleanParamName<`:${Param}`> : never)\n | ExtractOptionalRouteParams<`/${Rest}`>\n : AfterColon extends `${string}?`\n ? CleanParamName<`:${AfterColon}`>\n : never\n : never\n\ntype ExtractRouteParams<T extends string> =\n ExtractRequiredRouteParams<T> | ExtractOptionalRouteParams<T>\n\ntype HasNonTrailingOptionalRouteParams<T extends string> = string extends T\n ? false\n : NormalizePath<T> extends `${infer _Before}:${infer AfterColon}`\n ? AfterColon extends `${infer Param}/${infer Rest}`\n ? Param extends `${string}?`\n ? true\n : HasNonTrailingOptionalRouteParams<`/${Rest}`>\n : false\n : false\n\nexport type AssertSupportedPath<Path extends string> = string extends Path\n ? Path\n : HasNonTrailingOptionalRouteParams<Path> extends true\n ? never\n : Path\n\nexport type HasRequiredParams<T extends string> = [\n ExtractRequiredRouteParams<T>,\n] extends [never]\n ? false\n : true\n\ntype HasPathParams<T extends string> = [ExtractRouteParams<T>] extends [never]\n ? false\n : true\n\ntype Simplify<T> = { [K in keyof T]: T[K] }\n\n/**\n * PathParams type - extracts parameter names and their types\n */\nexport type PathParams<Path extends string> = [\n AssertSupportedPath<Path>,\n] extends [never]\n ? never\n : Simplify<\n {\n [K in ExtractRequiredRouteParams<Path>]: string | number\n } & {\n [K in ExtractOptionalRouteParams<Path>]?: string | number\n }\n >\n\n/**\n * RequirePathParams enforces pathParams when needed\n */\nexport type RequirePathParams<Path extends string, T> = [\n AssertSupportedPath<Path>,\n] extends [never]\n ? never\n : HasRequiredParams<Path> extends true\n ? T & { pathParams: PathParams<Path> }\n : HasPathParams<Path> extends true\n ? T & { pathParams?: PathParams<Path> }\n : T\n\n/**\n * Interpolates parameters into a URL template\n * Similar to React Router's generatePath function\n *\n * @example\n * ```ts\n * const path = generatePath('/users/:id/posts/:postId', { id: '123', postId: '456' });\n * // => '/users/123/posts/456'\n * ```\n */\nexport function generatePath<Path extends string>(\n path: AssertSupportedPath<Path>,\n ...args: HasRequiredParams<Path> extends true\n ? [params: PathParams<Path>]\n : HasPathParams<Path> extends true\n ? [params?: PathParams<Path>]\n : [params?: PathParams<Path>]\n): string\nexport function generatePath(\n path: string,\n params: Record<string, string | number | undefined> = {}\n): string {\n validateSupportedOptionalPath(path, Object.keys(params))\n\n return path.replace(\n /(^|\\/):([^/\\s?#]+?)(\\?)?(?=\\/|$|[?#])/g,\n (_match, prefix: string, paramName: string, optionalMarker?: string) => {\n const isOptional = optionalMarker === '?'\n\n // Validate parameter name\n if (!/^[a-zA-Z0-9_]+$/.test(paramName)) {\n throw new PathParameterError(\n `Invalid path parameter name: \"${paramName}\"`,\n path,\n [paramName],\n Object.keys(params)\n )\n }\n\n // Get and validate parameter value\n const paramValue = params[paramName]\n\n if (paramValue === undefined) {\n if (isOptional) {\n return ''\n }\n\n throw new PathParameterError(\n `Missing required path parameter: \"${paramName}\"`,\n path,\n [paramName],\n Object.keys(params)\n )\n }\n\n return `${prefix}${encodeURIComponent(String(paramValue))}`\n }\n )\n}\n\nfunction validateSupportedOptionalPath(\n path: string,\n providedParams: string[]\n): void {\n const invalidOptionalMatch = path.match(/(^|\\/):([^/\\s?#]+)\\?(?=\\/)/)\n\n if (!invalidOptionalMatch) {\n return\n }\n\n const [, , paramName] = invalidOptionalMatch\n\n throw new PathParameterError(\n `Optional path parameter \"${paramName}\" is not supported here. Optional path parameters are only supported at the end of the path.`,\n path,\n [paramName],\n providedParams\n )\n}\n","export const successStatusValidator: unique symbol = Symbol(\n '1000fetches.successStatusValidator'\n)\n\nexport function isSuccessfulStatus(status: number): boolean {\n return status >= 200 && status < 300\n}\n","import type { FetchOptions, RequestParamsType } from '../../types'\n\nexport function mergeFetchOptions(\n fetchOptions: FetchOptions | undefined,\n aliases: Pick<RequestInit, 'cache' | 'credentials' | 'mode' | 'redirect'>\n): FetchOptions {\n const merged: FetchOptions = sanitizeFetchOptions(fetchOptions)\n\n if (aliases.cache !== undefined) {\n merged.cache = aliases.cache\n }\n\n if (aliases.credentials !== undefined) {\n merged.credentials = aliases.credentials\n }\n\n if (aliases.mode !== undefined) {\n merged.mode = aliases.mode\n }\n\n if (aliases.redirect !== undefined) {\n merged.redirect = aliases.redirect\n }\n\n return merged\n}\n\nexport function sanitizeFetchOptions(\n fetchOptions: FetchOptions | undefined\n): FetchOptions {\n const safeOptions: FetchOptions = { ...(fetchOptions ?? {}) }\n const optionsRecord = safeOptions as Record<string, unknown>\n\n delete optionsRecord.body\n delete optionsRecord.headers\n delete optionsRecord.method\n delete optionsRecord.signal\n\n return safeOptions\n}\n\nexport function serializeQueryParams(params: RequestParamsType): string {\n const searchParams = new URLSearchParams()\n\n for (const [key, value] of Object.entries(params)) {\n if (Array.isArray(value)) {\n for (const item of value) {\n if (item !== undefined && item !== null) {\n searchParams.append(key, serializeQueryValue(item))\n }\n }\n } else if (value !== undefined && value !== null) {\n searchParams.append(\n key,\n serializeQueryValue(value as string | number | boolean | Date)\n )\n }\n }\n\n return searchParams.toString()\n}\n\nexport function serializeRequestBody(body: unknown): {\n body: BodyInit\n contentType?: string\n} {\n if (ArrayBuffer.isView(body)) {\n const bytes = new Uint8Array(body.buffer, body.byteOffset, body.byteLength)\n return { body: new Uint8Array(bytes).buffer }\n }\n\n if (\n typeof body === 'string' ||\n body instanceof FormData ||\n body instanceof URLSearchParams ||\n body instanceof ArrayBuffer ||\n body instanceof Blob ||\n body instanceof ReadableStream\n ) {\n return { body: body }\n }\n\n if (isObjectLike(body)) {\n return {\n body: JSON.stringify(body),\n contentType: 'application/json',\n }\n }\n\n if (body === null || body === undefined) {\n return { body: '' }\n }\n\n return { body: String(body) }\n}\n\nexport function isReplayableBody(body: BodyInit | null | undefined): boolean {\n return !(body instanceof ReadableStream)\n}\n\nfunction serializeQueryValue(value: string | number | boolean | Date): string {\n return value instanceof Date ? value.toISOString() : String(value)\n}\n\nfunction isObjectLike(\n value: unknown\n): value is Record<string, unknown> | unknown[] | { toJSON(): unknown } {\n return (\n value !== null &&\n typeof value === 'object' &&\n (Array.isArray(value) ||\n ('toJSON' in value && typeof value.toJSON === 'function') ||\n Object.prototype.toString.call(value) === '[object Object]')\n )\n}\n","import { InvalidBaseUrlError } from '../errors'\n\nexport function constructUrl(baseUrl: string, requestUrl: string): string {\n if (isAbsoluteUrl(requestUrl)) {\n return requestUrl\n }\n\n return isAbsoluteUrl(baseUrl)\n ? constructAbsoluteUrl(baseUrl, requestUrl)\n : constructRelativeUrl(baseUrl, requestUrl)\n}\n\nexport function appendQueryString(url: string, queryString: string): string {\n const normalizedQuery = queryString.startsWith('?')\n ? queryString.slice(1)\n : queryString\n\n if (!normalizedQuery) {\n return url\n }\n\n const { path, search, hash } = splitUrl(url)\n const nextSearch = search\n ? `${search}&${normalizedQuery}`\n : `?${normalizedQuery}`\n\n return `${path}${nextSearch}${hash}`\n}\n\nexport function assertRequestUrlSupported(\n url: string,\n usesNativeFetch: boolean\n): void {\n if (!usesNativeFetch || isAbsoluteUrl(url) || supportsRelativeRequestUrls()) {\n return\n }\n\n throw new InvalidBaseUrlError(\n `Relative request URL \"${url}\" requires an absolute baseUrl in non-browser environments. Pass an absolute baseUrl or use a custom fetch implementation.`,\n url\n )\n}\n\nfunction constructAbsoluteUrl(baseUrl: string, requestUrl: string): string {\n const baseUrlObj = new URL(baseUrl)\n const basePath = baseUrlObj.pathname.replace(/\\/$/, '')\n const { path, search, hash } = splitUrl(requestUrl)\n\n if (path.startsWith('/')) {\n baseUrlObj.pathname = basePath + path\n } else if (path) {\n baseUrlObj.pathname = basePath + '/' + path\n }\n\n if (search) {\n baseUrlObj.search = mergeSearch(baseUrlObj.search, search)\n }\n\n if (hash) {\n baseUrlObj.hash = hash\n }\n\n return baseUrlObj.toString()\n}\n\nfunction constructRelativeUrl(baseUrl: string, requestUrl: string): string {\n const {\n path: basePath,\n search: baseSearch,\n hash: baseHash,\n } = splitUrl(baseUrl)\n const {\n path: requestPath,\n search: requestSearch,\n hash: requestHash,\n } = splitUrl(requestUrl)\n\n const pathname = requestPath\n ? joinPathSegments(basePath, requestPath)\n : basePath || requestPath\n\n return `${pathname}${mergeSearch(baseSearch, requestSearch)}${\n requestHash || baseHash\n }`\n}\n\nfunction splitUrl(url: string): {\n path: string\n search: string\n hash: string\n} {\n const hashIndex = url.indexOf('#')\n const hash = hashIndex === -1 ? '' : url.slice(hashIndex)\n const withoutHash = hashIndex === -1 ? url : url.slice(0, hashIndex)\n const searchIndex = withoutHash.indexOf('?')\n\n return {\n path: searchIndex === -1 ? withoutHash : withoutHash.slice(0, searchIndex),\n search: searchIndex === -1 ? '' : withoutHash.slice(searchIndex),\n hash,\n }\n}\n\nfunction mergeSearch(baseSearch: string, requestSearch: string): string {\n if (!baseSearch) {\n return requestSearch\n }\n\n if (!requestSearch) {\n return baseSearch\n }\n\n return `${baseSearch}&${requestSearch.slice(1)}`\n}\n\nfunction joinPathSegments(basePath: string, requestPath: string): string {\n if (!basePath) {\n return requestPath.startsWith('/') ? requestPath : `/${requestPath}`\n }\n\n if (!requestPath) {\n return basePath\n }\n\n return requestPath.startsWith('/')\n ? `${basePath}${requestPath}`\n : `${basePath}/${requestPath}`\n}\n\nfunction isAbsoluteUrl(url: string): boolean {\n return /^[a-zA-Z][a-zA-Z\\d+\\-.]*:\\/\\//.test(url)\n}\n\nfunction supportsRelativeRequestUrls(): boolean {\n return (\n typeof window !== 'undefined' &&\n typeof window.location !== 'undefined' &&\n window.location.origin !== 'null'\n )\n}\n","export function createErrorMessage(context: string, error: unknown): string {\n return `${context}: ${error instanceof Error ? error.message : String(error)}`\n}\n\nexport function createStandardizedError(\n error: unknown,\n context: string\n): Error {\n if (error instanceof Error) {\n return error\n }\n\n return new Error(`${context}: ${String(error)}`)\n}\n","import { SerializationError } from './errors'\nimport type { HttpMethod, ResponseType } from './types'\nimport { createErrorMessage } from './errors/handling'\n\ntype ParsedResponse<T> = ResponseType<T> & {\n parseError?: SerializationError\n}\n\nexport async function processResponse<T = unknown>(\n response: Response,\n options: {\n responseType?: 'json' | 'text' | 'blob' | 'arrayBuffer' | 'formData'\n method: HttpMethod\n url: string\n tolerateParseError?: boolean\n }\n): Promise<ParsedResponse<T>> {\n const headers = Object.fromEntries(response.headers.entries())\n\n let data: unknown\n let parseError: SerializationError | undefined\n\n if (hasNoResponseBody(response.status, options.method)) {\n return {\n data: undefined as T,\n status: response.status,\n statusText: response.statusText,\n headers,\n method: options.method,\n url: options.url,\n raw: response,\n }\n }\n\n const responseBody = response.clone()\n const finalType = options.responseType ?? detectResponseType(response)\n let fallbackText: string | undefined\n const fallbackBody =\n options.tolerateParseError === true &&\n (finalType === 'blob' ||\n finalType === 'arrayBuffer' ||\n finalType === 'formData')\n ? response.clone()\n : undefined\n\n try {\n if (finalType === 'json') {\n fallbackText = await responseBody.text()\n data = JSON.parse(fallbackText)\n } else if (finalType === 'text') {\n data = await responseBody.text()\n } else if (finalType === 'blob') {\n data = await responseBody.blob()\n } else if (finalType === 'arrayBuffer') {\n data = await responseBody.arrayBuffer()\n } else if (finalType === 'formData') {\n data = await responseBody.formData()\n } else {\n fallbackText = await responseBody.text()\n data = parseJsonOrText(fallbackText)\n }\n } catch (error) {\n parseError = new SerializationError(\n createErrorMessage('Failed to parse response body', error),\n error instanceof Error ? error : undefined\n )\n\n if (!options.tolerateParseError) {\n throw parseError\n }\n\n if (fallbackText !== undefined) {\n data = fallbackText\n } else if (fallbackBody) {\n try {\n data = await fallbackBody.text()\n } catch {\n data = ''\n }\n } else {\n data = ''\n }\n }\n\n return {\n data: data as T,\n status: response.status,\n statusText: response.statusText,\n headers,\n method: options.method,\n url: options.url,\n raw: response,\n parseError,\n }\n}\n\nfunction detectResponseType(\n response: Response\n): 'json' | 'text' | 'arrayBuffer' | 'formData' | undefined {\n const contentType = response.headers.get('content-type')?.toLowerCase() ?? ''\n const mimeType = contentType.split(';', 1)[0]?.trim() ?? ''\n\n if (isJsonMimeType(mimeType)) {\n return 'json'\n }\n\n if (mimeType.startsWith('text/')) {\n return 'text'\n }\n\n if (\n mimeType === 'application/octet-stream' ||\n mimeType === 'application/pdf' ||\n mimeType.startsWith('image/') ||\n mimeType.startsWith('video/') ||\n mimeType.startsWith('audio/')\n ) {\n return 'arrayBuffer'\n }\n\n if (\n mimeType === 'multipart/form-data' ||\n mimeType === 'application/x-www-form-urlencoded'\n ) {\n return 'formData'\n }\n\n return undefined\n}\n\nfunction parseJsonOrText(text: string): unknown {\n try {\n return JSON.parse(text)\n } catch {\n return text\n }\n}\n\nfunction hasNoResponseBody(status: number, method: HttpMethod): boolean {\n return (\n method.toUpperCase() === 'HEAD' ||\n status === 204 ||\n status === 205 ||\n status === 304\n )\n}\n\nfunction isJsonMimeType(mimeType: string): boolean {\n return (\n mimeType === 'application/json' ||\n (mimeType.startsWith('application/') && mimeType.endsWith('+json'))\n )\n}\n","import { AbortError, TimeoutError } from '../../errors'\nimport { createStandardizedError } from '../../errors/handling'\n\nexport function normalizeExecutionError(\n error: unknown,\n {\n didTimeout,\n finalSignal,\n timeout,\n }: {\n didTimeout: boolean\n finalSignal?: AbortSignal\n timeout: number\n }\n): Error {\n let lastError = createStandardizedError(error, 'Request execution')\n\n if (isAbortError(lastError) && didTimeout) {\n return new TimeoutError(`Request timeout after ${timeout}ms`, lastError)\n }\n\n if (isAbortError(lastError) || finalSignal?.aborted) {\n lastError =\n lastError instanceof AbortError\n ? lastError\n : new AbortError(lastError.message, lastError)\n }\n\n return lastError\n}\n\nexport function sleep(ms: number, signal?: AbortSignal): Promise<void> {\n if (ms <= 0) {\n return Promise.resolve()\n }\n\n if (signal?.aborted) {\n return Promise.reject(createAbortError(signal.reason))\n }\n\n return new Promise((resolve, reject) => {\n const timeoutId = setTimeout(() => {\n signal?.removeEventListener('abort', handleAbort)\n resolve()\n }, ms)\n\n const handleAbort = () => {\n clearTimeout(timeoutId)\n signal?.removeEventListener('abort', handleAbort)\n reject(createAbortError(signal?.reason))\n }\n\n signal?.addEventListener('abort', handleAbort, { once: true })\n })\n}\n\nexport function createPreAbortedRequestError(reason: unknown): Error {\n if (reason instanceof Error && reason.name === 'AbortError') {\n return new AbortError('Request aborted by caller', reason)\n }\n\n return createAbortError(reason)\n}\n\nexport function createCombinedSignal(\n requestSignal?: AbortSignal,\n timeoutSignal?: AbortSignal\n): { signal?: AbortSignal; cleanup: () => void } {\n if (!requestSignal && !timeoutSignal) {\n return {\n signal: undefined,\n cleanup: () => undefined,\n }\n }\n\n if (!requestSignal) {\n return {\n signal: timeoutSignal,\n cleanup: () => undefined,\n }\n }\n\n if (!timeoutSignal) {\n return {\n signal: requestSignal,\n cleanup: () => undefined,\n }\n }\n\n if (requestSignal.aborted) {\n return {\n signal: requestSignal,\n cleanup: () => undefined,\n }\n }\n\n if (timeoutSignal.aborted) {\n return {\n signal: timeoutSignal,\n cleanup: () => undefined,\n }\n }\n\n const combinedController = new AbortController()\n\n const handleAbort = (event: Event) => {\n const sourceSignal = event.target\n\n if (sourceSignal instanceof AbortSignal) {\n combinedController.abort(sourceSignal.reason)\n return\n }\n\n combinedController.abort()\n }\n\n requestSignal.addEventListener('abort', handleAbort, { once: true })\n timeoutSignal.addEventListener('abort', handleAbort, { once: true })\n\n return {\n signal: combinedController.signal,\n cleanup: () => {\n requestSignal.removeEventListener('abort', handleAbort)\n timeoutSignal.removeEventListener('abort', handleAbort)\n },\n }\n}\n\nexport function isAbortError(error: unknown): boolean {\n return error instanceof Error && error.name === 'AbortError'\n}\n\nfunction createAbortError(reason: unknown): Error {\n if (reason instanceof AbortError) {\n return reason\n }\n\n if (reason instanceof Error) {\n return new AbortError(reason.message, reason)\n }\n\n return new AbortError()\n}\n","import { HttpError, NetworkError } from '../../errors'\nimport type { CustomFetch, ResponseType } from '../../types'\nimport { createStandardizedError } from '../../errors/handling'\nimport { isAbortError } from '../abort'\n\nexport async function fetchWithNetworkError(\n fetchImplementation: CustomFetch,\n url: string,\n requestInit: RequestInit\n): Promise<Response> {\n try {\n return await fetchImplementation(url, requestInit)\n } catch (error) {\n const standardizedError = createStandardizedError(\n error,\n 'Network request failed'\n )\n\n if (\n isAbortError(standardizedError) ||\n standardizedError instanceof NetworkError\n ) {\n throw standardizedError\n }\n\n throw new NetworkError(standardizedError.message, standardizedError)\n }\n}\n\nexport function createHttpError(\n response: ResponseType<unknown>,\n cause?: Error\n): HttpError {\n return new HttpError(\n `HTTP ${response.status} ${response.statusText}`,\n response.status,\n response.statusText,\n response.data,\n response.raw,\n response.url,\n response.method,\n cause\n )\n}\n","import { MiddlewareError } from '../../errors'\nimport type { HttpMethod, ResponseType } from '../../types'\nimport {\n createErrorMessage,\n createStandardizedError,\n} from '../../errors/handling'\n\nexport async function applyResponseMiddleware<TResponse>({\n onResponseMiddleware,\n response,\n url,\n method,\n}: {\n onResponseMiddleware?: (\n response: ResponseType<unknown>\n ) => ResponseType<unknown> | Promise<ResponseType<unknown>>\n response: ResponseType<TResponse>\n url: string\n method: HttpMethod\n}): Promise<ResponseType<TResponse>> {\n if (!onResponseMiddleware) {\n return response\n }\n\n try {\n const middlewareResult = await onResponseMiddleware(response)\n if (!isResponseTypeLike(middlewareResult)) {\n throw new MiddlewareError(\n 'Response middleware must return a valid ResponseType object',\n 'response',\n url,\n method\n )\n }\n\n return middlewareResult as ResponseType<TResponse>\n } catch (error) {\n if (error instanceof MiddlewareError) {\n throw error\n }\n\n throw new MiddlewareError(\n createErrorMessage('Response middleware failed', error),\n 'response',\n url,\n method,\n createStandardizedError(error, 'Response middleware')\n )\n }\n}\n\nfunction isResponseTypeLike(value: unknown): value is ResponseType<unknown> {\n return (\n value !== null &&\n typeof value === 'object' &&\n 'data' in value &&\n 'status' in value &&\n typeof value.status === 'number' &&\n 'statusText' in value &&\n typeof value.statusText === 'string' &&\n 'headers' in value &&\n typeof value.headers === 'object' &&\n value.headers !== null &&\n 'method' in value &&\n typeof value.method === 'string' &&\n 'url' in value &&\n typeof value.url === 'string' &&\n 'raw' in value &&\n value.raw instanceof Response\n )\n}\n","import { processResponse } from '../response'\nimport { isReplayableBody } from './serialization'\nimport {\n createCombinedSignal,\n createPreAbortedRequestError,\n normalizeExecutionError,\n sleep,\n} from './abort'\nimport { createHttpError, fetchWithNetworkError } from './fetchErrors'\nimport { applyResponseMiddleware } from './middleware'\nimport type {\n CustomFetch,\n ExtendedRequestInit,\n HttpMethod,\n RequestOptions,\n ResponseType,\n RetryOptions,\n} from '../types'\n\ninterface ExecuteHttpRequestWithRetryOptions {\n fetchImplementation: CustomFetch\n requestInit: ExtendedRequestInit\n requestRetry?: RetryOptions | boolean\n clientRetry?: RetryOptions | boolean\n url: string\n method: HttpMethod\n timeout: number\n signal?: AbortSignal\n responseType?: RequestOptions['responseType']\n onResponseMiddleware?: (\n response: ResponseType<unknown>\n ) => ResponseType<unknown> | Promise<ResponseType<unknown>>\n isExpectedStatus: (status: number) => boolean\n}\n\nexport async function executeHttpRequestWithRetry<TResponse>({\n fetchImplementation,\n requestInit: baseRequestInit,\n requestRetry,\n clientRetry,\n url,\n method,\n timeout,\n signal,\n responseType,\n onResponseMiddleware,\n isExpectedStatus,\n}: ExecuteHttpRequestWithRetryOptions): Promise<ResponseType<TResponse>> {\n const retryHelpers = shouldLoadRetryPolicy(clientRetry, requestRetry)\n ? await import('./retry')\n : undefined\n const mergedRetryOptions = retryHelpers?.createRetryPolicy(\n clientRetry,\n requestRetry\n )\n const maxRetries = mergedRetryOptions?.maxRetries ?? 0\n const bodyReplayable = isReplayableBody(baseRequestInit.body)\n let lastError: Error | undefined\n\n for (let attempt = 0; attempt <= maxRetries; attempt += 1) {\n const controller = new AbortController()\n let didTimeout = false\n const timeoutId = setTimeout(() => {\n didTimeout = true\n controller.abort()\n }, timeout)\n\n const { signal: finalSignal, cleanup: cleanupSignal } =\n createCombinedSignal(signal, controller.signal)\n let attemptCleanedUp = false\n const cleanupAttempt = () => {\n if (attemptCleanedUp) {\n return\n }\n\n attemptCleanedUp = true\n clearTimeout(timeoutId)\n cleanupSignal()\n }\n\n try {\n if (finalSignal?.aborted) {\n throw createPreAbortedRequestError(finalSignal.reason)\n }\n\n const requestInit: ExtendedRequestInit = {\n ...baseRequestInit,\n signal: finalSignal,\n }\n\n const response = await fetchWithNetworkError(\n fetchImplementation,\n url,\n requestInit\n )\n\n const responseData = await processResponse<TResponse>(response, {\n responseType,\n method,\n url,\n tolerateParseError: !isExpectedStatus(response.status),\n })\n\n const finalResponse = await applyResponseMiddleware({\n onResponseMiddleware,\n response: responseData,\n url,\n method,\n })\n\n if (!isExpectedStatus(finalResponse.status)) {\n throw createHttpError(finalResponse, responseData.parseError)\n }\n\n return finalResponse\n } catch (error) {\n lastError = normalizeExecutionError(error, {\n didTimeout,\n finalSignal,\n timeout,\n })\n\n if (\n attempt >= maxRetries ||\n !retryHelpers ||\n !(await retryHelpers.shouldRetry(\n lastError,\n attempt,\n mergedRetryOptions,\n {\n bodyReplayable,\n method,\n url,\n }\n ))\n ) {\n throw lastError\n }\n\n const delay = retryHelpers.calculateRetryDelay(\n attempt,\n mergedRetryOptions,\n lastError\n )\n await retryHelpers.notifyRetry(mergedRetryOptions, {\n bodyReplayable,\n delay,\n error: lastError,\n method,\n nextAttempt: attempt + 1,\n retryCount: attempt,\n url,\n })\n cleanupAttempt()\n await sleep(delay, signal)\n } finally {\n cleanupAttempt()\n }\n }\n\n throw new Error('Retry loop terminated unexpectedly')\n}\n\nfunction shouldLoadRetryPolicy(\n clientRetry?: RetryOptions | boolean,\n requestRetry?: RetryOptions | boolean\n): boolean {\n return (\n requestRetry !== false &&\n (clientRetry === true ||\n typeof clientRetry === 'object' ||\n requestRetry === true ||\n typeof requestRetry === 'object')\n )\n}\n","import { MiddlewareError } from './errors'\nimport type { SchemaValidator } from './schema'\nimport type {\n CustomFetch,\n ExtendedRequestInit,\n FetchOptions,\n HttpHeaders,\n HttpMethod,\n RequestContext,\n RequestParamsType,\n ResponseType,\n RetryOptions,\n SerializeBody,\n SerializeParams,\n} from './types'\nimport {\n type AssertSupportedPath,\n generatePath,\n type PathParams,\n} from './utils/path'\nimport { isSuccessfulStatus, successStatusValidator } from './status'\nimport {\n mergeFetchOptions,\n sanitizeFetchOptions,\n serializeQueryParams,\n serializeRequestBody,\n} from './request/serialization'\nimport {\n appendQueryString,\n assertRequestUrlSupported,\n constructUrl,\n} from './request/url'\nimport { executeHttpRequestWithRetry } from './request/request'\nimport { createErrorMessage, createStandardizedError } from './errors/handling'\n\nexport interface HttpRequestOptions<\n TBody = unknown,\n TParams extends RequestParamsType = RequestParamsType,\n> {\n method?: HttpMethod\n headers?: HttpHeaders\n /** Query parameters */\n params?: TParams\n /** Path parameters for URL template */\n pathParams?: Record<string, string | number | undefined>\n /** Request body */\n body?: TBody\n timeout?: number\n signal?: AbortSignal\n /** Fetch options */\n credentials?: RequestCredentials\n cache?: RequestCache\n mode?: RequestMode\n redirect?: RequestRedirect\n /** Additional Fetch/Node options passed through to the underlying fetch call */\n fetchOptions?: FetchOptions\n /** Response type override */\n responseType?: 'json' | 'text' | 'blob' | 'arrayBuffer' | 'formData'\n /** Per-request retry configuration */\n retry?: RetryOptions | boolean\n}\n\ntype InternalHttpRequestOptions<\n TBody = unknown,\n TParams extends RequestParamsType = RequestParamsType,\n> = HttpRequestOptions<TBody, TParams> & {\n [successStatusValidator]?: (status: number) => boolean\n}\n\nexport interface RequestDefaults {\n headers?: HttpHeaders\n params?: RequestParamsType\n timeout?: number\n credentials?: RequestCredentials\n cache?: RequestCache\n mode?: RequestMode\n redirect?: RequestRedirect\n fetchOptions?: FetchOptions\n responseType?: HttpRequestOptions['responseType']\n retry?: RetryOptions | boolean\n}\n\nexport interface RequestDefaultsContext<\n TBody = unknown,\n TParams extends RequestParamsType = RequestParamsType,\n Path extends string = string,\n> {\n /** Raw path or URL passed by the caller before path parameter generation */\n path: Path\n /** Path after template parameter generation, before baseUrl and query params */\n resolvedPath: string\n method: HttpMethod\n params?: TParams\n pathParams?: Record<string, string | number | undefined>\n body?: TBody\n hasBody: boolean\n requestOptions: Readonly<HttpRequestOptions<TBody, TParams>>\n baseUrl: string\n headers: HttpHeaders\n timeout: number\n retry?: RetryOptions | boolean\n}\n\nexport interface HttpClientConfig<TSerializedBody = unknown> {\n /** Base URL for all requests */\n baseUrl?: string\n /** Default headers */\n headers?: HttpHeaders\n /** Default timeout */\n timeout?: number\n /** Schema validator */\n schemaValidator?: SchemaValidator\n /** Default retry configuration */\n retry?: RetryOptions | boolean\n /** Custom fetch implementation */\n fetch?: CustomFetch\n /** Custom body serializer */\n serializeBody?: SerializeBody<TSerializedBody>\n /** Custom params serializer */\n serializeParams?: SerializeParams\n /** Per-request defaults resolved before request options and middleware */\n defaults?: <\n TBody extends TSerializedBody = TSerializedBody,\n TParams extends RequestParamsType = RequestParamsType,\n Path extends string = string,\n >(\n context: RequestDefaultsContext<TBody, TParams, Path>\n ) => RequestDefaults | void | Promise<RequestDefaults | void>\n /** Request middleware - can modify request before sending */\n onRequestMiddleware?: <TBody = unknown>(\n context: RequestContext<TBody>\n ) => RequestContext<TBody> | void | Promise<RequestContext<TBody> | void>\n /** Response middleware - can modify response after receiving */\n onResponseMiddleware?: (\n response: ResponseType<unknown>\n ) => ResponseType<unknown> | Promise<ResponseType<unknown>>\n}\n\n/**\n * Creates an HTTP request handler with the given configuration.\n * This is the core function that handles all HTTP requests with retry logic,\n * middleware, serialization, defaults, and timeouts.\n */\nexport function createHttpRequest<TSerializedBody = unknown>(\n config: HttpClientConfig<TSerializedBody> = {}\n) {\n const {\n baseUrl = '',\n headers: defaultHeaders = {},\n timeout: defaultTimeout = 30_000,\n fetch: customFetch,\n serializeBody: customSerializeBody,\n serializeParams: customSerializeParams,\n defaults,\n onRequestMiddleware,\n onResponseMiddleware,\n } = config\n const usesNativeFetch = customFetch === undefined\n\n return async function fetcher<\n Path extends string = string,\n TResponse = unknown,\n TBody extends TSerializedBody = TSerializedBody,\n TParams extends RequestParamsType = RequestParamsType,\n >(\n url: Path,\n options: HttpRequestOptions<TBody, TParams> = {}\n ): Promise<ResponseType<TResponse>> {\n const method = options.method ?? 'GET'\n const pathParams = options.pathParams\n const customSuccessStatusValidator = (\n options as InternalHttpRequestOptions<TBody, TParams>\n )[successStatusValidator]\n\n const resolvedPath =\n pathParams === undefined\n ? generatePath(url as AssertSupportedPath<Path>)\n : generatePath(\n url as AssertSupportedPath<Path>,\n pathParams as PathParams<Path>\n )\n\n let dynamicDefaults: RequestDefaults | void | undefined\n if (defaults) {\n dynamicDefaults = await defaults({\n path: url,\n resolvedPath,\n method,\n params: options.params,\n pathParams,\n body: options.body,\n hasBody: options.body !== undefined,\n requestOptions: cloneRequestOptions(options),\n baseUrl,\n headers: { ...defaultHeaders },\n timeout: defaultTimeout,\n retry: config.retry,\n })\n }\n\n const resolvedUrl = baseUrl\n ? constructUrl(baseUrl, resolvedPath)\n : resolvedPath\n\n const requestFetchOptions = mergeRequestFetchOptions(\n dynamicDefaults,\n options\n )\n const mergedHeaders = new Headers(defaultHeaders)\n applyHeaders(mergedHeaders, dynamicDefaults?.headers)\n applyHeaders(mergedHeaders, options.headers)\n\n const params = mergeParams(dynamicDefaults?.params, options.params)\n const timeout =\n options.timeout ?? dynamicDefaults?.timeout ?? defaultTimeout\n const requestRetry = options.retry ?? dynamicDefaults?.retry\n const responseType = options.responseType ?? dynamicDefaults?.responseType\n\n const baseRequestContext: RequestContext<TBody> = {\n url: resolvedUrl,\n method,\n params,\n headers: mergedHeaders,\n body: options.body,\n signal: options.signal,\n fetchOptions: requestFetchOptions,\n }\n\n let requestContext: RequestContext<TBody> = baseRequestContext\n\n if (onRequestMiddleware) {\n try {\n // prevent middleware from mutating the original context\n const contextCopy: RequestContext<TBody> = {\n ...baseRequestContext,\n headers: new Headers(baseRequestContext.headers),\n fetchOptions: { ...baseRequestContext.fetchOptions },\n }\n\n const middlewareResult = await onRequestMiddleware(contextCopy)\n\n if (middlewareResult === undefined) {\n requestContext = contextCopy\n } else if (!isRequestContextLike(middlewareResult)) {\n throw new MiddlewareError(\n 'Request middleware must return a valid RequestContext object',\n 'request',\n requestContext.url,\n requestContext.method\n )\n } else {\n requestContext = middlewareResult\n }\n } catch (error) {\n if (error instanceof MiddlewareError) {\n throw error\n }\n\n throw new MiddlewareError(\n createErrorMessage('Request middleware failed', error),\n 'request',\n requestContext.url,\n requestContext.method,\n createStandardizedError(error, 'Request middleware')\n )\n }\n }\n\n if (requestContext.params) {\n const serializedParams = customSerializeParams\n ? customSerializeParams(requestContext.params)\n : serializeQueryParams(requestContext.params)\n\n if (serializedParams) {\n requestContext.url = appendQueryString(\n requestContext.url,\n serializedParams\n )\n }\n }\n\n assertRequestUrlSupported(requestContext.url, usesNativeFetch)\n\n const baseRequestInit: ExtendedRequestInit = {\n ...sanitizeFetchOptions(requestContext.fetchOptions),\n method: requestContext.method,\n headers: requestContext.headers,\n }\n\n if (\n requestContext.body !== undefined &&\n requestContext.method !== 'GET' &&\n requestContext.method !== 'HEAD'\n ) {\n let body: BodyInit\n let contentType: string | undefined\n\n if (customSerializeBody) {\n const serializedBody = customSerializeBody(requestContext.body)\n if (serializedBody == null) {\n body = ''\n } else {\n body = serializedBody\n }\n } else {\n const serialized = serializeRequestBody(requestContext.body)\n body = serialized.body\n contentType = serialized.contentType\n }\n\n baseRequestInit.body = body\n\n if (contentType && !requestContext.headers.has('content-type')) {\n requestContext.headers.set('content-type', contentType)\n }\n\n baseRequestInit.duplex = 'half'\n }\n\n return executeHttpRequestWithRetry<TResponse>({\n fetchImplementation: customFetch ?? globalThis.fetch,\n requestInit: baseRequestInit,\n clientRetry: config.retry,\n requestRetry,\n url: requestContext.url,\n method: requestContext.method,\n timeout,\n signal: requestContext.signal,\n responseType,\n onResponseMiddleware,\n isExpectedStatus: customSuccessStatusValidator ?? isSuccessfulStatus,\n })\n }\n}\n\nfunction cloneRequestOptions<TBody, TParams extends RequestParamsType>(\n options: HttpRequestOptions<TBody, TParams>\n): Readonly<HttpRequestOptions<TBody, TParams>> {\n return {\n ...options,\n headers: options.headers ? { ...options.headers } : undefined,\n params: options.params ? { ...options.params } : undefined,\n pathParams: options.pathParams ? { ...options.pathParams } : undefined,\n fetchOptions: options.fetchOptions\n ? { ...options.fetchOptions }\n : undefined,\n }\n}\n\nfunction applyHeaders(headers: Headers, values: HttpHeaders | undefined): void {\n if (!values) {\n return\n }\n\n for (const [name, value] of Object.entries(values)) {\n headers.set(name, value)\n }\n}\n\nfunction mergeParams<TParams extends RequestParamsType>(\n defaults: RequestParamsType | undefined,\n params: TParams | undefined\n): RequestParamsType | undefined {\n if (!defaults) {\n return params\n }\n\n if (!params) {\n return defaults\n }\n\n return {\n ...defaults,\n ...params,\n }\n}\n\nfunction mergeRequestFetchOptions<TBody, TParams extends RequestParamsType>(\n defaults: RequestDefaults | void | undefined,\n options: HttpRequestOptions<TBody, TParams>\n): FetchOptions {\n const defaultFetchOptions = mergeFetchOptions(defaults?.fetchOptions, {\n cache: defaults?.cache,\n credentials: defaults?.credentials,\n mode: defaults?.mode,\n redirect: defaults?.redirect,\n })\n const requestFetchOptions = mergeFetchOptions(options.fetchOptions, {\n cache: options.cache,\n credentials: options.credentials,\n mode: options.mode,\n redirect: options.redirect,\n })\n\n return {\n ...defaultFetchOptions,\n ...requestFetchOptions,\n }\n}\n\nfunction isRequestContextLike(\n value: unknown\n): value is RequestContext<unknown> {\n return (\n value !== null &&\n typeof value === 'object' &&\n 'url' in value &&\n typeof value.url === 'string' &&\n 'method' in value &&\n typeof value.method === 'string' &&\n 'headers' in value &&\n value.headers instanceof Headers &&\n 'fetchOptions' in value &&\n typeof value.fetchOptions === 'object' &&\n value.fetchOptions !== null\n )\n}\n","import type { HttpRequestOptions } from '../core'\nimport {\n ContractValidationError,\n HttpError,\n InvalidContractError,\n InvalidSchemaError,\n SchemaValidationError,\n} from '../errors'\nimport type { SchemaValidator } from '../schema'\nimport { isSuccessfulStatus, successStatusValidator } from '../status'\nimport type {\n InferContractSuccess,\n InferSchemaOutput,\n RequestParamsType,\n ResponseContract,\n ResponseContractBranch,\n ResponseType,\n Schema,\n} from '../types'\n\nexport function validateResponseContractShape(\n contract: ResponseContract\n): void {\n if (isSchemaLike(contract)) {\n return\n }\n\n if (!isObjectRecord(contract)) {\n throw new InvalidContractError(\n 'Response contract must be a schema or an object with a success branch',\n contract\n )\n }\n\n if (!('success' in contract)) {\n throw new InvalidContractError(\n 'Response contract object must include a success branch',\n contract,\n undefined,\n 'success'\n )\n }\n\n validateResponseContractBranch(contract.success, contract, 'success')\n\n if ('error' in contract && contract.error !== undefined) {\n validateResponseContractBranch(contract.error, contract, 'error')\n }\n}\n\nexport function createContractRequestOptions<\n TBody,\n TParams extends RequestParamsType,\n>(\n options: HttpRequestOptions<TBody, TParams>,\n contract: ResponseContract\n): HttpRequestOptions<TBody, TParams> {\n if (!isContractObject(contract) || isSchemaLike(contract.success)) {\n return options\n }\n\n const successMap = contract.success\n\n if (\n !Object.keys(successMap).some(\n key => key !== 'default' && Number.isInteger(Number(key))\n )\n ) {\n return options\n }\n\n return {\n ...options,\n [successStatusValidator]: (status: number) =>\n isSuccessfulStatus(status) || Object.hasOwn(successMap, status),\n } as HttpRequestOptions<TBody, TParams>\n}\n\nexport async function validateResponsePromiseWithContract<\n C extends ResponseContract,\n>(\n contract: C,\n responsePromise: Promise<ResponseType<unknown>>,\n schemaValidator: SchemaValidator\n): Promise<ResponseType<InferContractSuccess<C>>> {\n try {\n const response = await responsePromise\n const schema = resolveSuccessSchema(contract, response.status, true)!\n return await validateResponseData(contract, schema, response, 'success', {\n schemaValidator,\n })\n } catch (error) {\n if (!(error instanceof HttpError)) {\n throw error\n }\n\n return await validateHttpError(contract, error, schemaValidator)\n }\n}\n\nfunction validateResponseContractBranch(\n branch: unknown,\n contract: ResponseContract,\n branchName: 'success' | 'error'\n): void {\n if (isSchemaLike(branch)) {\n return\n }\n\n if (isObjectRecord(branch)) {\n for (const key of Object.keys(branch)) {\n assertStatusMapKey(key, contract, branchName)\n }\n\n return\n }\n\n throw new InvalidContractError(\n `${\n branchName === 'success' ? 'Success' : 'Error'\n } response contract branch must be a schema or status map`,\n contract,\n undefined,\n branchName\n )\n}\n\nasync function validateHttpError<C extends ResponseContract>(\n contract: C,\n error: HttpError,\n schemaValidator: SchemaValidator\n): Promise<ResponseType<InferContractSuccess<C>>> {\n const failedResponse = createResponseFromHttpError(error)\n const successSchema = resolveSuccessSchema(contract, error.status, false)\n\n if (successSchema) {\n return await validateResponseData(\n contract,\n successSchema,\n failedResponse,\n 'success',\n { schemaValidator }\n )\n }\n\n const errorSchema = resolveErrorSchema(contract, error.status)\n\n if (!errorSchema) {\n throw error\n }\n\n const validatedErrorData = await validateResponseContract(\n errorSchema,\n failedResponse,\n 'error',\n schemaValidator\n )\n\n throw new HttpError(\n `HTTP ${error.status} ${error.statusText}`,\n error.status,\n error.statusText,\n validatedErrorData,\n error.response,\n error.url,\n error.method,\n error.cause\n )\n}\n\nasync function validateResponseData<\n C extends ResponseContract,\n S extends Schema,\n>(\n _contract: C,\n schema: S,\n response: ResponseType<unknown>,\n branch: 'success' | 'error',\n options: { schemaValidator: SchemaValidator }\n): Promise<ResponseType<InferContractSuccess<C>>> {\n const validatedData = await validateResponseContract(\n schema,\n response,\n branch,\n options.schemaValidator\n )\n\n return {\n ...response,\n data: validatedData,\n } as ResponseType<InferContractSuccess<C>>\n}\n\nfunction resolveSuccessSchema(\n contract: ResponseContract,\n status: number,\n includeDefault: boolean\n): Schema | undefined {\n if (!isContractObject(contract)) {\n return includeDefault ? contract : undefined\n }\n\n const schema = resolveBranchSchema(contract.success, status, includeDefault)\n\n if (!schema && includeDefault) {\n throw new InvalidContractError(\n `No success response contract found for status ${status}`,\n contract,\n status,\n 'success'\n )\n }\n\n return schema\n}\n\nfunction resolveErrorSchema(\n contract: ResponseContract,\n status: number\n): Schema | undefined {\n if (!isContractObject(contract) || !contract.error) {\n return undefined\n }\n\n return resolveBranchSchema(contract.error, status, true)\n}\n\nfunction resolveBranchSchema(\n branch: ResponseContractBranch,\n status: number,\n includeDefault: boolean\n): Schema | undefined {\n if (isSchemaLike(branch)) {\n return includeDefault ? branch : undefined\n }\n\n const statusMap = branch as Record<string, Schema | undefined>\n return (\n statusMap[String(status)] ??\n (includeDefault ? statusMap.default : undefined)\n )\n}\n\nasync function validateResponseContract<S extends Schema>(\n schema: S,\n response: ResponseType<unknown>,\n branch: 'success' | 'error',\n schemaValidator: SchemaValidator\n): Promise<InferSchemaOutput<S>> {\n try {\n return (await schemaValidator.validate(\n schema,\n response.data\n )) as InferSchemaOutput<S>\n } catch (error) {\n if (error instanceof InvalidSchemaError) {\n throw error\n }\n\n const branchLabel = branch === 'success' ? 'Success' : 'Error'\n const details = error instanceof Error ? `: ${error.message}` : ''\n\n throw new ContractValidationError(\n `${branchLabel} response failed contract validation${details}`,\n schema,\n response.data,\n response,\n branch,\n error instanceof Error ? error : undefined,\n error instanceof SchemaValidationError ? error.issues : undefined\n )\n }\n}\n\nfunction createResponseFromHttpError(error: HttpError): ResponseType<unknown> {\n return {\n data: error.data,\n status: error.status,\n statusText: error.statusText,\n headers: Object.fromEntries(error.response.headers.entries()),\n method: error.method,\n url: error.url,\n raw: error.response,\n }\n}\n\nfunction isObjectRecord(value: unknown): value is Record<string, unknown> {\n return value !== null && typeof value === 'object' && !Array.isArray(value)\n}\n\nfunction isSchemaLike(value: unknown): value is Schema {\n return (\n value !== null &&\n (typeof value === 'object' || typeof value === 'function') &&\n '~standard' in value\n )\n}\n\nfunction isContractObject(\n value: ResponseContract\n): value is Exclude<ResponseContract, Schema> {\n return isObjectRecord(value) && !isSchemaLike(value)\n}\n\nfunction assertStatusMapKey(\n key: string,\n contract: ResponseContract,\n branchName: 'success' | 'error'\n): void {\n if (key === 'default') {\n return\n }\n\n const status = Number(key)\n\n if (!Number.isInteger(status) || status < 100 || status >= 600) {\n throw new InvalidContractError(\n 'Response contract status map keys must be HTTP status codes or \"default\"',\n contract,\n undefined,\n branchName\n )\n }\n\n if (branchName === 'success' && (status < 200 || status >= 400)) {\n throw new InvalidContractError(\n 'Success response contract status keys must be 2xx or 3xx status codes',\n contract,\n status,\n branchName\n )\n }\n\n if (branchName === 'error' && (status < 400 || status >= 600)) {\n throw new InvalidContractError(\n 'Error response contract status keys must be 4xx or 5xx status codes',\n contract,\n status,\n branchName\n )\n }\n}\n","import type { StandardSchemaV1 } from '@standard-schema/spec'\nimport { InvalidSchemaError, SchemaValidationError } from '../errors'\nimport { Schema } from '../types'\n\n/**\n * Type guard to check if an object conforms to the Standard Schema V1 specification\n */\nfunction isStandardSchema(obj: unknown): obj is StandardSchemaV1 {\n return (\n obj !== null &&\n (typeof obj === 'object' || typeof obj === 'function') &&\n '~standard' in obj &&\n typeof obj['~standard'] === 'object' &&\n obj['~standard'] !== null &&\n 'validate' in obj['~standard'] &&\n typeof obj['~standard'].validate === 'function' &&\n 'version' in obj['~standard'] &&\n obj['~standard'].version === 1 &&\n 'vendor' in obj['~standard'] &&\n typeof obj['~standard'].vendor === 'string'\n )\n}\n\n/**\n * Interface for schema validators that can validate data against schemas.\n *\n * This interface allows you to create custom schema validators that work\n * with different validation libraries (Zod, Valibot, Arktype, etc.).\n */\nexport interface SchemaValidator {\n /**\n * Validate data against a schema.\n *\n * @template T - The expected type after validation\n * @param schema - The schema to validate against\n * @param data - The data to validate\n * @returns The validated data with the correct type, synchronously or asynchronously\n * @throws {SchemaValidationError} If the data doesn't match the schema\n */\n validate<T>(schema: Schema<T>, data: unknown): T | Promise<T>\n}\n\nfunction isPromiseLike<T>(value: unknown): value is PromiseLike<T> {\n return (\n value !== null &&\n (typeof value === 'object' || typeof value === 'function') &&\n 'then' in value &&\n typeof value.then === 'function'\n )\n}\n\nfunction readValidationResult<T>(\n schema: Schema<T>,\n data: unknown,\n result: StandardSchemaV1.Result<T>\n): T {\n if (result.issues) {\n throw new SchemaValidationError(\n JSON.stringify(result.issues),\n schema,\n data,\n undefined,\n result.issues\n )\n }\n\n return result.value\n}\n\n/**\n * Create a default schema validator that supports Standard Schema.\n *\n * This validator works with schemas that implement the Standard Schema\n * interface, including both synchronous and asynchronous validators.\n *\n * @returns A schema validator instance\n *\n * @example\n * ```ts\n * const validator = createSchemaValidator()\n *\n * const parsed = validator.validate(schema, data)\n * ```\n */\nexport function createSchemaValidator(): SchemaValidator {\n return {\n validate<T>(schema: Schema<T>, data: unknown): T | Promise<T> {\n if (!isStandardSchema(schema)) {\n throw new InvalidSchemaError(\n 'Schema must implement the Standard Schema interface',\n schema\n )\n }\n\n const result = schema['~standard'].validate(data) as\n StandardSchemaV1.Result<T> | PromiseLike<StandardSchemaV1.Result<T>>\n\n if (isPromiseLike<StandardSchemaV1.Result<T>>(result)) {\n return Promise.resolve(result).then(asyncResult =>\n readValidationResult(schema, data, asyncResult)\n )\n }\n\n return readValidationResult(schema, data, result)\n },\n }\n}\n","import type { HttpClientConfig, HttpRequestOptions } from '../core'\nimport { createHttpRequest } from '../core'\nimport {\n createContractRequestOptions,\n validateResponseContractShape,\n validateResponsePromiseWithContract,\n} from '../contract'\nimport { InvalidBaseUrlError, InvalidContractError } from '../errors'\nimport { createSchemaValidator } from '../schema'\nimport type { SchemaValidator } from '../schema'\nimport type {\n ContractableResponse,\n EnforcedPathParamsOptions,\n ExtractableResponse,\n InferContractSuccess,\n RequestParamsType,\n ResponseContract,\n ResponseType,\n} from '../types'\nimport type {\n AssertSupportedPath,\n HasRequiredParams,\n RequirePathParams,\n} from '../utils'\n\ntype PathOptionsArgs<Path extends string, TOptions> = [\n AssertSupportedPath<Path>,\n] extends [never]\n ? [options: never]\n : HasRequiredParams<AssertSupportedPath<Path>> extends true\n ? [options: TOptions]\n : [options?: TOptions]\n\ntype EnforcedHttpRequestOptions<\n TBody,\n TParams extends RequestParamsType,\n Path extends string,\n> = RequirePathParams<\n AssertSupportedPath<Path>,\n string extends Path\n ? HttpRequestOptions<TBody, TParams>\n : Omit<HttpRequestOptions<TBody, TParams>, 'pathParams'>\n>\n\nfunction validateAndNormalizeBaseUrl(baseUrl?: string): string {\n if (!baseUrl) {\n return ''\n }\n\n if (baseUrl.startsWith('/')) {\n return baseUrl.replace(/\\/$/, '')\n }\n\n try {\n new URL(baseUrl)\n } catch {\n throw new InvalidBaseUrlError(\n `Invalid baseUrl: \"${baseUrl}\". Must be a valid absolute URL or relative path starting with \"/\".`,\n baseUrl\n )\n }\n\n return baseUrl.endsWith('/') ? baseUrl.slice(0, -1) : baseUrl\n}\n\nfunction createExtractableResponse<T>(\n promise: Promise<ResponseType<T>>\n): ExtractableResponse<T> {\n const extractable = promise as ExtractableResponse<T>\n extractable.data = async () => (await promise).data\n extractable.void = async () => {\n await promise\n }\n return extractable\n}\n\n/**\n * Creates a chainable response that allows adding contract validation and extracting data\n */\nfunction createContractableResponse<\n Path extends string,\n TResponse,\n TSerializedBody,\n TBody extends TSerializedBody,\n TParams extends RequestParamsType,\n>(\n url: Path,\n options: HttpRequestOptions<TBody, TParams>,\n requestHandler: ReturnType<typeof createHttpRequest<TSerializedBody>>,\n schemaValidator: SchemaValidator\n): ContractableResponse<TResponse> {\n let transportPromise: Promise<ResponseType<unknown>> | undefined\n let baseStartError: unknown\n\n const startTransport = (\n requestOptions: HttpRequestOptions<TBody, TParams>\n ) => {\n transportPromise ??= requestHandler<Path, unknown, TBody, TParams>(\n url,\n requestOptions\n )\n return transportPromise\n }\n\n const basePromise = new Promise<ResponseType<TResponse>>(\n (resolve, reject) => {\n queueMicrotask(() => {\n if (baseStartError !== undefined) {\n reject(baseStartError)\n return\n }\n\n startTransport(options).then(\n response => resolve(response as ResponseType<TResponse>),\n reject\n )\n })\n }\n )\n\n void basePromise.catch(() => undefined)\n\n const baseResponse = createExtractableResponse(\n basePromise\n ) as ContractableResponse<TResponse>\n\n baseResponse.contract = <C extends ResponseContract>(\n contract: C\n ): ExtractableResponse<InferContractSuccess<C>> => {\n try {\n validateResponseContractShape(contract)\n baseStartError = undefined\n\n if (transportPromise !== undefined) {\n throw new InvalidContractError(\n 'Cannot attach a response contract after the request has started',\n contract\n )\n }\n\n const contractOptions = createContractRequestOptions(options, contract)\n const responsePromise = startTransport(contractOptions)\n\n return createExtractableResponse(\n validateResponsePromiseWithContract(\n contract,\n responsePromise,\n schemaValidator\n )\n )\n } catch (error) {\n if (transportPromise === undefined) {\n baseStartError = error\n }\n\n return createExtractableResponse(Promise.reject(error))\n }\n }\n\n return baseResponse\n}\n\n/**\n * Creates a complete HTTP client with method builders\n */\nexport function createHttpClient<TSerializedBody = unknown>(\n config: HttpClientConfig<TSerializedBody> = {}\n) {\n const validatedConfig: HttpClientConfig<TSerializedBody> = {\n ...config,\n baseUrl: validateAndNormalizeBaseUrl(config.baseUrl),\n }\n\n const requestHandler = createHttpRequest<TSerializedBody>(validatedConfig)\n const schemaValidator = config.schemaValidator ?? createSchemaValidator()\n\n function get<\n Path extends string = string,\n TParams extends RequestParamsType = RequestParamsType,\n >(\n url: Path,\n ...args: PathOptionsArgs<\n Path,\n EnforcedPathParamsOptions<never, TParams, Path>\n >\n ) {\n return createContractableResponse<\n Path,\n unknown,\n TSerializedBody,\n never,\n TParams\n >(\n url,\n {\n ...(args[0] ?? {}),\n method: 'GET',\n },\n requestHandler,\n schemaValidator\n )\n }\n\n function createBodyMethod(method: 'POST' | 'PUT' | 'PATCH') {\n return <\n Path extends string = string,\n TBody extends TSerializedBody = TSerializedBody,\n TParams extends RequestParamsType = RequestParamsType,\n >(\n url: Path,\n body?: TBody,\n ...args: PathOptionsArgs<\n Path,\n EnforcedPathParamsOptions<TBody, TParams, Path>\n >\n ) =>\n createContractableResponse<\n Path,\n unknown,\n TSerializedBody,\n TBody,\n TParams\n >(\n url,\n {\n ...(args[0] ?? {}),\n method,\n body,\n },\n requestHandler,\n schemaValidator\n )\n }\n\n return {\n get,\n\n post: createBodyMethod('POST'),\n\n put: createBodyMethod('PUT'),\n\n patch: createBodyMethod('PATCH'),\n\n delete: <\n Path extends string = string,\n TParams extends RequestParamsType = RequestParamsType,\n >(\n url: Path,\n ...args: PathOptionsArgs<\n Path,\n EnforcedPathParamsOptions<never, TParams, Path>\n >\n ) =>\n createContractableResponse<\n Path,\n unknown,\n TSerializedBody,\n never,\n TParams\n >(\n url,\n {\n ...(args[0] ?? {}),\n method: 'DELETE',\n },\n requestHandler,\n schemaValidator\n ),\n\n /**\n * Generic request method for custom HTTP methods and full control\n */\n request: <\n Path extends string = string,\n TBody extends TSerializedBody = TSerializedBody,\n TParams extends RequestParamsType = RequestParamsType,\n >(\n url: Path,\n ...args: PathOptionsArgs<\n Path,\n EnforcedHttpRequestOptions<TBody, TParams, Path>\n >\n ) =>\n createContractableResponse<\n Path,\n unknown,\n TSerializedBody,\n TBody,\n TParams\n >(url, args[0] ?? {}, requestHandler, schemaValidator),\n }\n}\n\nexport type HttpClient = ReturnType<typeof createHttpClient>\n"],"mappings":"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"}