1000fetches 0.1.3 → 0.1.4

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.cjs.js CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});class t extends Error{name="HttpError";status;statusText;data;response;url;method;cause;constructor(t,e,r,s,a,o,n,i){super(`HTTP ${e} ${r}: ${t} (${n} ${o})`,{cause:i}),this.status=e,this.statusText=r,this.data=s,this.response=a,this.url=o,this.method=n}}class e extends Error{name="NetworkError";cause;constructor(t,e){super(t,{cause:e})}}class r extends Error{name="SchemaValidationError";schema;data;cause;constructor(t,e,r,s){super(t,{cause:s}),this.schema=e,this.data=r}}class s extends Error{name="TimeoutError";cause;constructor(t,e){super(t,{cause:e})}}class a extends Error{name="PathParameterError";url;requiredParams;providedParams;cause;constructor(t,e,r,s,a){super(t,{cause:a}),this.url=e,this.requiredParams=r,this.providedParams=s}}class o extends Error{name="InterceptorError";interceptorType;url;method;cause;constructor(t,e,r,s,a){super(t,{cause:a}),this.interceptorType=e,this.url=r,this.method=s}}class n extends Error{name="SerializationError";cause;constructor(t,e){super(t,{cause:e})}}function i(t){return null!==t&&("object"==typeof t||"function"==typeof t)&&"~standard"in t&&"object"==typeof t["~standard"]&&null!==t["~standard"]&&"validate"in t["~standard"]&&"function"==typeof t["~standard"].validate&&"version"in t["~standard"]&&"number"==typeof t["~standard"].version&&"vendor"in t["~standard"]&&"string"==typeof t["~standard"].vendor}function c(){return{validate(t,e){if(!i(t))throw new Error("Invalid schema: Schema must implement the Standard Schema interface");const r=function(t){return{parse:e=>{const r=t["~standard"].validate(e);if(r instanceof Promise)throw new Error("Async Standard Schema validation is not supported");if("issues"in r&&r.issues){const t=Array.from(r.issues).map(t=>t.message).join("; ");throw new Error(`Standard Schema validation failed: ${t}`)}return r.value}}}(t);return r.parse(e)},isSchema:t=>i(t)}}const u={maxRetries:3,retryDelay:300,backoffFactor:2,retryStatusCodes:[429,500,502,503,504],retryNetworkErrors:!0,maxRetryDelay:3e4,shouldRetry:()=>!0};exports.HttpClient=class{baseUrl;defaultHeaders;defaultTimeout;schemaValidator;requestInterceptors;responseInterceptors;defaultRetryOptions;constructor(t={}){this.baseUrl=function(t){const e="undefined"!=typeof window&&void 0!==window.location&&"null"!==window.location.origin;if(!t)return e?window.location.origin:"";if(t.startsWith("/"))return e?new URL(t,window.location.origin).href.replace(/\/$/,""):t.replace(/\/$/,"");try{new URL(t)}catch{throw new Error(`Invalid baseUrl: "${t}". Must be a valid absolute URL or relative path starting with "/".`)}return t.endsWith("/")?t.slice(0,-1):t}(t.baseUrl),this.defaultHeaders=t.headers||{},this.defaultTimeout=t.timeout||3e4,this.schemaValidator=t.schemaValidator||{validate(t,e){if(!i(t))throw new Error("Invalid schema: Schema must implement the Standard Schema interface");return c().validate(t,e)},isSchema:t=>i(t)},this.requestInterceptors=t.requestInterceptors||[],this.responseInterceptors=t.responseInterceptors||[],this.defaultRetryOptions=t.retryOptions}addRequestInterceptor(t){this.requestInterceptors.push(t)}addResponseInterceptor(t){this.responseInterceptors.push(t)}async shouldRetry(a,o,n){if(!1===n)return!1;const i=this.getRetryOptions(n);if(o>=i.maxRetries)return!1;if("function"==typeof i.shouldRetry)try{return await i.shouldRetry(a,o)}catch(c){console.warn("Custom shouldRetry function failed:",c)}return!!(a instanceof e&&i.retryNetworkErrors)||(!!(a instanceof t&&i.retryStatusCodes.includes(a.status))||!(a instanceof r)&&a instanceof s)}getRetryDelay(t,e){const r=e.retryDelay*Math.pow(e.backoffFactor,t),s=Math.min(r,e.maxRetryDelay),a=s+.2*s*(2*Math.random()-1);return Math.max(1,Math.floor(a))}getRetryOptions(t){return!1===t?{...u,maxRetries:0}:!0===t?{...u,...this.defaultRetryOptions}:"object"==typeof t?{...u,...this.defaultRetryOptions,...t}:{...u,...this.defaultRetryOptions}}sleep(t){return new Promise(e=>setTimeout(e,t))}request(t,e,r={}){return function(t){const e=t;return e.data=async()=>(await t).data,e}(this.requestWithRetry(t,e,r))}async requestWithRetry(t,r,s){let a=0;for(;;)try{return await this.executeRequest(t,r,s)}catch(o){if(!(o instanceof Error))throw new e(String(o),void 0);if(await this.shouldRetry(o,a,s.retry)){const t=this.getRetryOptions(s.retry),e=this.getRetryDelay(a,t);await this.sleep(e),a++;continue}throw o}}async executeRequest(i,c,u={}){let d=this.resolveUrl(c,u.pathParams),h={url:d,method:i,params:u.params,headers:this.prepareHeaders(u.headers),body:u.body,fetchOptions:{credentials:u.credentials,cache:u.cache,mode:u.mode,redirect:u.redirect}};for(const t of this.requestInterceptors)try{h=await t(h)}catch(E){throw new o(`Request interceptor failed: ${E instanceof Error?E.message:String(E)}`,"request",d,i,E instanceof Error?E:void 0)}if(d=h.url,h.params&&Object.keys(h.params).length>0){const t=new URLSearchParams;for(const[r,s]of Object.entries(h.params))void 0!==s&&t.append(r,String(s));const e=t.toString();e&&(d+=(d.includes("?")?"&":"?")+e)}const l={method:h.method,headers:h.headers,...h.fetchOptions};if(void 0!==h.body&&("POST"===h.method||"PUT"===h.method||"PATCH"===h.method))if(h.body instanceof FormData||h.body instanceof Blob||h.body instanceof ArrayBuffer||h.body instanceof URLSearchParams||"string"==typeof h.body)l.body=h.body;else try{l.body=JSON.stringify(h.body)}catch(E){throw new n(`Failed to serialize request body: ${E instanceof Error?E.message:"Invalid data structure"}`,E instanceof Error?E:void 0)}const p=u.timeout||this.defaultTimeout,f=new AbortController,m=setTimeout(()=>f.abort(),p),y=h.signal||u.signal;let w;const b=y?(()=>{const t=this.mergeAbortSignals(y,f.signal);return w=t.cleanup,t.signal})():f.signal;try{const t=await fetch(d,{...l,signal:b});let e=await this.processResponse(t,u,i,d);return u.schema&&(e.data=this.validateWithSchema(u.schema,e.data)),e}catch(E){if(E instanceof DOMException&&"AbortError"===E.name||E instanceof Error&&"AbortError"===E.name||E instanceof Error&&E.message.toLowerCase().includes("timeout"))throw new s(`Request timed out after ${p}ms`,E instanceof Error?E:void 0);if(E instanceof t||E instanceof r||E instanceof o||E instanceof a||E instanceof n)throw E;throw new e(E instanceof Error?E.message:String(E),E instanceof Error?E:void 0)}finally{clearTimeout(m),w?.()}}validateWithSchema(t,e,s="Response schema validation failed"){try{return this.schemaValidator.validate(t,e)}catch(a){throw new r(`${s}: ${a instanceof Error?a.message:"Unknown error"}`,t,e,a instanceof Error?a:void 0)}}prepareHeaders(t={}){const e=new Headers;for(const[r,s]of Object.entries(this.defaultHeaders))null!=s&&e.set(r,String(s));for(const[r,s]of Object.entries(t))null!=s&&e.set(r,String(s));return e}extractHeaders(t){const e={};return t.forEach((t,r)=>{e[r]=t}),e}createHttpError(e,r,s,a,o,n){return new t(`Request failed with status code ${e.status}`,e.status,o||e.statusText,r,e,s,a,n)}async parseResponseBody(t,e){const r=t.headers.get("content-type")??"";try{if("text"===e.responseType)return await t.text();if("blob"===e.responseType)return await t.blob();if("arrayBuffer"===e.responseType)return await t.arrayBuffer();if(r.includes("application/json")){const e=await t.text();return e?JSON.parse(e):null}return await t.text()}catch(s){if(204===t.status)return;if(r.includes("application/json")&&s instanceof SyntaxError)throw new Error(`Failed to parse JSON response: ${s.message}`);throw s}}async processResponse(t,e,r,s){const a=this.extractHeaders(t.headers),n=e.validateStatus||(t=>t>=200&&t<300),i=await this.parseResponseBody(t,e);if(!n(t.status))throw this.createHttpError(t,i,s,r);const c={data:i,status:t.status,statusText:t.statusText,headers:a,method:r,url:s,raw:t};let u=c;const d=c.status;for(const l of this.responseInterceptors)try{u=await l(u)}catch(h){throw new o(`Response interceptor failed: ${h instanceof Error?h.message:String(h)}`,"response",s,r,h instanceof Error?h:void 0)}if(u.status!==d&&!n(u.status))throw this.createHttpError(t,u.data,s,r,u.statusText);return u}mergeAbortSignals(t,e){if(t.aborted||e.aborted){const t=new AbortController;return t.abort(),{signal:t.signal}}const r=new AbortController,s=()=>{r.abort(),a()},a=()=>{t.removeEventListener("abort",s),e.removeEventListener("abort",s)};return t.addEventListener("abort",s),e.addEventListener("abort",s),{signal:r.signal,cleanup:a}}get(t,e){return this.request("GET",t,e||{})}post(t,e,r){return this.request("POST",t,{...r||{},body:e})}put(t,e,r){return this.request("PUT",t,{...r||{},body:e})}patch(t,e,r){return this.request("PATCH",t,{...r||{},body:e})}delete(t,e){return this.request("DELETE",t,e||{})}validatePathParams(t,e){if(!e){const e=this.extractRequiredPathParams(t);if(e.length>0)throw new a(`Missing required path parameters for URL "${t}": ${e.join(", ")}. Please provide pathParams: { ${e.map(t=>`${t}: value`).join(", ")} }`,t,e,[]);return}const r=this.extractRequiredPathParams(t),s=Object.keys(e),o=r.filter(t=>!s.includes(t));if(o.length>0)throw new a(`Missing required path parameters: ${o.join(", ")}. Provided: ${s.join(", ")}`,t,r,s)}extractRequiredPathParams(t){if(t.includes("?"))throw new a("Optional path parameters (e.g., :variable?) are not supported",t,[],[]);const e=t.match(/:([a-zA-Z0-9_]+)/g);return e?e.map(t=>t.slice(1)):[]}resolveUrl(t,e){this.validatePathParams(t,e);const r=e?function(t,e={}){return t.replace(/:([a-zA-Z0-9_]+)/g,(r,s)=>{if(void 0===e[s])throw new a(`Missing required path parameter: ${s}`,t,[s],Object.keys(e));return String(e[s])})}(t,e):t;if(/^https?:\/\//i.test(r))return r;const s=r.startsWith("/")?r.slice(1):r;return`${this.baseUrl}/${s}`}},exports.HttpError=t,exports.InterceptorError=o,exports.NetworkError=e,exports.PathParameterError=a,exports.SchemaValidationError=r,exports.SerializationError=n,exports.TimeoutError=s;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});class t extends Error{name="HttpError";status;statusText;data;response;url;method;cause;constructor(t,e,r,s,a,o,n,i){super(`HTTP ${e} ${r}: ${t} (${n} ${o})`,{cause:i}),this.status=e,this.statusText=r,this.data=s,this.response=a,this.url=o,this.method=n}}class e extends Error{name="NetworkError";cause;constructor(t,e){super(t,{cause:e})}}class r extends Error{name="SchemaValidationError";schema;data;cause;constructor(t,e,r,s){super(t,{cause:s}),this.schema=e,this.data=r}}class s extends Error{name="TimeoutError";cause;constructor(t,e){super(t,{cause:e})}}class a extends Error{name="PathParameterError";url;requiredParams;providedParams;cause;constructor(t,e,r,s,a){super(t,{cause:a}),this.url=e,this.requiredParams=r,this.providedParams=s}}class o extends Error{name="InterceptorError";interceptorType;url;method;cause;constructor(t,e,r,s,a){super(t,{cause:a}),this.interceptorType=e,this.url=r,this.method=s}}class n extends Error{name="SerializationError";cause;constructor(t,e){super(t,{cause:e})}}function i(t){return null!==t&&("object"==typeof t||"function"==typeof t)&&"~standard"in t&&"object"==typeof t["~standard"]&&null!==t["~standard"]&&"validate"in t["~standard"]&&"function"==typeof t["~standard"].validate&&"version"in t["~standard"]&&"number"==typeof t["~standard"].version&&"vendor"in t["~standard"]&&"string"==typeof t["~standard"].vendor}function c(){return{validate(t,e){if(!i(t))throw new Error("Invalid schema: Schema must implement the Standard Schema interface");const r=function(t){return{parse:e=>{const r=t["~standard"].validate(e);if(r instanceof Promise)throw new Error("Async Standard Schema validation is not supported");if("issues"in r&&r.issues){const t=Array.from(r.issues).map(t=>t.message).join("; ");throw new Error(`Standard Schema validation failed: ${t}`)}return r.value}}}(t);return r.parse(e)},isSchema:t=>i(t)}}const u={maxRetries:3,retryDelay:300,backoffFactor:2,retryStatusCodes:[429,500,502,503,504],retryNetworkErrors:!0,maxRetryDelay:3e4,shouldRetry:()=>!0};exports.HttpClient=class{baseUrl;defaultHeaders;defaultTimeout;schemaValidator;requestInterceptors;responseInterceptors;defaultRetryOptions;constructor(t={}){this.baseUrl=function(t){const e="undefined"!=typeof window&&void 0!==window.location&&"null"!==window.location.origin;if(!t)return e?window.location.origin:"";if(t.startsWith("/"))return e?new URL(t,window.location.origin).href.replace(/\/$/,""):t.replace(/\/$/,"");try{new URL(t)}catch{throw new Error(`Invalid baseUrl: "${t}". Must be a valid absolute URL or relative path starting with "/".`)}return t.endsWith("/")?t.slice(0,-1):t}(t.baseUrl),this.defaultHeaders=t.headers??{},this.defaultTimeout=t.timeout??3e4,this.schemaValidator=t.schemaValidator||{validate(t,e){if(!i(t))throw new Error("Invalid schema: Schema must implement the Standard Schema interface");return c().validate(t,e)},isSchema:t=>i(t)},this.requestInterceptors=t.requestInterceptors??[],this.responseInterceptors=t.responseInterceptors??[],this.defaultRetryOptions=t.retryOptions}addRequestInterceptor(t){this.requestInterceptors.push(t)}addResponseInterceptor(t){this.responseInterceptors.push(t)}async shouldRetry(a,o,n){if(!1===n)return!1;const i=this.getRetryOptions(n);if(o>=i.maxRetries)return!1;if("function"==typeof i.shouldRetry)try{return await i.shouldRetry(a,o)}catch(c){console.warn("Custom shouldRetry function failed:",c)}return!!(a instanceof e&&i.retryNetworkErrors)||(!!(a instanceof t&&i.retryStatusCodes.includes(a.status))||!(a instanceof r)&&a instanceof s)}getRetryDelay(t,e){const r=e.retryDelay*Math.pow(e.backoffFactor,t),s=Math.min(r,e.maxRetryDelay),a=s+.2*s*(2*Math.random()-1);return Math.max(1,Math.floor(a))}getRetryOptions(t){return!1===t?{...u,maxRetries:0}:!0===t?{...u,...this.defaultRetryOptions}:"object"==typeof t?{...u,...this.defaultRetryOptions,...t}:{...u,...this.defaultRetryOptions}}sleep(t){return new Promise(e=>setTimeout(e,t))}request(t,e,r={}){return function(t){const e=t;return e.data=async()=>(await t).data,e}(this.requestWithRetry(t,e,r))}async requestWithRetry(t,r,s){let a=0;for(;;)try{return await this.executeRequest(t,r,s)}catch(o){if(!(o instanceof Error))throw new e(String(o),void 0);if(await this.shouldRetry(o,a,s.retry)){const t=this.getRetryOptions(s.retry),e=this.getRetryDelay(a,t);await this.sleep(e),a++;continue}throw o}}async executeRequest(i,c,u={}){let d=this.resolveUrl(c,u.pathParams),h={url:d,method:i,params:u.params,headers:this.prepareHeaders(u.headers),body:u.body,fetchOptions:{credentials:u.credentials,cache:u.cache,mode:u.mode,redirect:u.redirect}};for(const t of this.requestInterceptors)try{h=await t(h)}catch(b){throw new o(`Request interceptor failed: ${b instanceof Error?b.message:String(b)}`,"request",d,i,b instanceof Error?b:void 0)}if(d=h.url,h.params&&Object.keys(h.params).length>0){const t=new URLSearchParams;for(const[r,s]of Object.entries(h.params))void 0!==s&&t.append(r,String(s));const e=t.toString();e&&(d+=(d.includes("?")?"&":"?")+e)}const l={method:h.method,headers:h.headers,...h.fetchOptions};if(void 0!==h.body&&("POST"===h.method||"PUT"===h.method||"PATCH"===h.method))if(h.body instanceof FormData||h.body instanceof Blob||h.body instanceof ArrayBuffer||h.body instanceof URLSearchParams||"string"==typeof h.body)l.body=h.body;else try{l.body=JSON.stringify(h.body)}catch(b){throw new n(`Failed to serialize request body: ${b instanceof Error?b.message:"Invalid data structure"}`,b instanceof Error?b:void 0)}const p=u.timeout||this.defaultTimeout,f=new AbortController,m=setTimeout(()=>f.abort(),p),y=h.signal||u.signal;let w;const E=y?(()=>{const t=this.mergeAbortSignals(y,f.signal);return w=t.cleanup,t.signal})():f.signal;try{const t=await fetch(d,{...l,signal:E});let e=await this.processResponse(t,u,i,d);return u.schema&&(e.data=this.validateWithSchema(u.schema,e.data)),e}catch(b){if(b instanceof DOMException&&"AbortError"===b.name||b instanceof Error&&"AbortError"===b.name||b instanceof Error&&b.message.toLowerCase().includes("timeout"))throw new s(`Request timed out after ${p}ms`,b instanceof Error?b:void 0);if(b instanceof t||b instanceof r||b instanceof o||b instanceof a||b instanceof n)throw b;throw new e(b instanceof Error?b.message:String(b),b instanceof Error?b:void 0)}finally{clearTimeout(m),w?.()}}validateWithSchema(t,e,s="Response schema validation failed"){try{return this.schemaValidator.validate(t,e)}catch(a){throw new r(`${s}: ${a instanceof Error?a.message:"Unknown error"}`,t,e,a instanceof Error?a:void 0)}}prepareHeaders(t={}){const e=new Headers;for(const[r,s]of Object.entries(this.defaultHeaders))null!=s&&e.set(r,String(s));for(const[r,s]of Object.entries(t))null!=s&&e.set(r,String(s));return e}extractHeaders(t){const e={};return t.forEach((t,r)=>{e[r]=t}),e}createHttpError(e,r,s,a,o,n){return new t(`Request failed with status code ${e.status}`,e.status,o||e.statusText,r,e,s,a,n)}async parseResponseBody(t,e){const r=t.headers.get("content-type")??"";try{if("text"===e.responseType)return await t.text();if("blob"===e.responseType)return await t.blob();if("arrayBuffer"===e.responseType)return await t.arrayBuffer();if(r.includes("application/json")){const e=await t.text();return e?JSON.parse(e):null}return await t.text()}catch(s){if(204===t.status)return;if(r.includes("application/json")&&s instanceof SyntaxError)throw new Error(`Failed to parse JSON response: ${s.message}`);throw s}}async processResponse(t,e,r,s){const a=this.extractHeaders(t.headers),n=e.validateStatus||(t=>t>=200&&t<300),i=await this.parseResponseBody(t,e);if(!n(t.status))throw this.createHttpError(t,i,s,r);const c={data:i,status:t.status,statusText:t.statusText,headers:a,method:r,url:s,raw:t};let u=c;const d=c.status;for(const l of this.responseInterceptors)try{u=await l(u)}catch(h){throw new o(`Response interceptor failed: ${h instanceof Error?h.message:String(h)}`,"response",s,r,h instanceof Error?h:void 0)}if(u.status!==d&&!n(u.status))throw this.createHttpError(t,u.data,s,r,u.statusText);return u}mergeAbortSignals(t,e){if(t.aborted||e.aborted){const t=new AbortController;return t.abort(),{signal:t.signal}}const r=new AbortController,s=()=>{r.abort(),a()},a=()=>{t.removeEventListener("abort",s),e.removeEventListener("abort",s)};return t.addEventListener("abort",s),e.addEventListener("abort",s),{signal:r.signal,cleanup:a}}get(t,e){return this.request("GET",t,e||{})}post(t,e,r){return this.request("POST",t,{...r||{},body:e})}put(t,e,r){return this.request("PUT",t,{...r||{},body:e})}patch(t,e,r){return this.request("PATCH",t,{...r||{},body:e})}delete(t,e){return this.request("DELETE",t,e||{})}validatePathParams(t,e){if(!e){const e=this.extractRequiredPathParams(t);if(e.length>0)throw new a(`Missing required path parameters for URL "${t}": ${e.join(", ")}. Please provide pathParams: { ${e.map(t=>`${t}: value`).join(", ")} }`,t,e,[]);return}const r=this.extractRequiredPathParams(t),s=Object.keys(e),o=r.filter(t=>!s.includes(t));if(o.length>0)throw new a(`Missing required path parameters: ${o.join(", ")}. Provided: ${s.join(", ")}`,t,r,s)}extractRequiredPathParams(t){if(!t)return[];const e=t.split("?").at(0)?.split("#").at(0);if(!e?.includes(":"))return[];const r=e.match(/:([a-zA-Z0-9_]+)/g);return r?r.map(t=>t.slice(1)):[]}resolveUrl(t,e){this.validatePathParams(t,e);const r=e?function(t,e={}){return t.replace(/:([a-zA-Z0-9_]+)/g,(r,s)=>{if(void 0===e[s])throw new a(`Missing required path parameter: ${s}`,t,[s],Object.keys(e));return String(e[s])})}(t,e):t;if(/^https?:\/\//i.test(r))return r;const s=r.startsWith("/")?r.slice(1):r;return`${this.baseUrl}/${s}`}},exports.HttpError=t,exports.InterceptorError=o,exports.NetworkError=e,exports.PathParameterError=a,exports.SchemaValidationError=r,exports.SerializationError=n,exports.TimeoutError=s;
2
2
  //# sourceMappingURL=index.cjs.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs.js","sources":["../src/errors.ts","../src/standard-schema.ts","../src/client.ts","../src/schema.ts","../src/utils/path.ts"],"sourcesContent":["interface HttpClientError {\n name: string\n message: string\n cause?: Error\n stack?: string\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 enhancedMessage = `HTTP ${status} ${statusText}: ${message} (${method} ${url})`\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 }\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 }\n}\n\nexport class SchemaValidationError extends Error implements HttpClientError {\n public readonly name = 'SchemaValidationError'\n public readonly schema: unknown\n public readonly data: unknown\n public override readonly cause?: Error\n\n constructor(message: string, schema: unknown, data: unknown, cause?: Error) {\n super(message, { cause })\n this.schema = schema\n this.data = data\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 }\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 super(message, { cause })\n this.url = url\n this.requiredParams = requiredParams\n this.providedParams = providedParams\n }\n}\n\nexport class InterceptorError extends Error implements HttpClientError {\n public readonly name = 'InterceptorError'\n public readonly interceptorType: '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 interceptorType: 'request' | 'response',\n url?: string,\n method?: string,\n cause?: Error\n ) {\n super(message, { cause })\n this.interceptorType = interceptorType\n this.url = url\n this.method = method\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 }\n}\n","import { SchemaValidator } from './schema'\n\n/**\n * Standard Schema V1 interface implementation\n *\n * This interface defines the structure for schema validation libraries\n * that conform to the Standard Schema specification.\n *\n * @see https://github.com/standard-schema/standard-schema\n */\nexport interface StandardSchemaV1<Input = unknown, Output = Input> {\n /** The Standard Schema properties containing validation logic and metadata */\n readonly '~standard': StandardSchemaV1.Props<Input, Output>\n}\n\n/**\n * Namespace containing Standard Schema V1 type definitions\n *\n * Provides type-safe interfaces for schema validation results,\n * error handling, and type inference.\n */\nexport namespace StandardSchemaV1 {\n /**\n * Core properties interface for Standard Schema V1\n *\n * Contains the essential metadata and validation function\n * that every Standard Schema implementation must provide.\n */\n export interface Props<Input = unknown, Output = Input> {\n /** The version number of the Standard Schema specification */\n readonly version: 1\n /** The name of the schema validation library (e.g., 'zod', 'valibot') */\n readonly vendor: string\n /**\n * Validates unknown input values against the schema\n *\n * @param value - The value to validate\n * @returns Promise or direct result containing validation outcome\n */\n readonly validate: (\n value: unknown\n ) => Result<Output> | Promise<Result<Output>>\n /** Type information for input and output types */\n readonly types?: Types<Input, Output> | undefined\n }\n\n /**\n * Union type representing the result of schema validation\n *\n * Can be either a successful validation with the validated value,\n * or a failed validation with error details.\n */\n export type Result<Output> = SuccessResult<Output> | FailureResult\n\n /**\n * Interface for successful validation results\n *\n * Contains the validated and typed output value.\n */\n export interface SuccessResult<Output> {\n /** The validated and typed output value */\n readonly value: Output\n /** Undefined since validation succeeded */\n readonly issues?: undefined\n }\n\n /**\n * Interface for failed validation results\n *\n * Contains detailed error information about validation failures.\n */\n export interface FailureResult {\n /** Array of validation error details */\n readonly issues: ReadonlyArray<Issue>\n }\n\n /**\n * Interface for individual validation error details\n *\n * Provides error message and optional path information\n * to help identify where validation failed.\n */\n export interface Issue {\n /** Human-readable error message describing the validation failure */\n readonly message: string\n /**\n * Path to the property that failed validation\n *\n * Useful for nested object validation to pinpoint the exact location\n * of validation failures.\n */\n readonly path?: ReadonlyArray<PropertyKey | PathSegment> | undefined\n }\n\n /**\n * Interface for path segment information in validation errors\n *\n * Used to provide detailed path information for validation failures\n * in complex nested structures.\n */\n export interface PathSegment {\n /** The property key representing this path segment */\n readonly key: PropertyKey\n }\n\n /**\n * Interface for type information associated with a schema\n *\n * Provides compile-time type information for input and output types\n * to enable better TypeScript integration and IntelliSense support.\n */\n export interface Types<Input = unknown, Output = Input> {\n /** The input type that the schema expects */\n readonly input: Input\n /** The output type that the schema produces after validation */\n readonly output: Output\n }\n\n /**\n * Type utility to infer the input type from a Standard Schema\n *\n * Extracts the input type that a schema expects for validation.\n *\n * @example\n * ```ts\n * type UserInput = StandardSchemaV1.InferInput<typeof userSchema>\n * ```\n */\n export type InferInput<Schema extends StandardSchemaV1> = NonNullable<\n Schema['~standard']['types']\n >['input']\n\n /**\n * Type utility to infer the output type from a Standard Schema\n *\n * Extracts the output type that a schema produces after validation.\n *\n * @example\n * ```ts\n * type UserOutput = StandardSchemaV1.InferOutput<typeof userSchema>\n * ```\n */\n export type InferOutput<Schema extends StandardSchemaV1> = NonNullable<\n Schema['~standard']['types']\n >['output']\n}\n\n/**\n * Type guard to check if an object conforms to the Standard Schema V1 specification\n *\n * Validates that an object has the required structure and properties\n * to be considered a valid Standard Schema implementation.\n *\n * @param obj - The object to check\n * @returns True if the object is a valid Standard Schema V1 implementation\n *\n * @example\n * ```ts\n * if (isStandardSchema(schema)) {\n * // Use the schema with type safety\n * const result = schema['~standard'].validate(data);\n * }\n * ```\n */\nexport function 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 typeof obj['~standard'].version === 'number' &&\n 'vendor' in obj['~standard'] &&\n typeof obj['~standard'].vendor === 'string'\n )\n}\n\n/**\n * Creates an adapter for Standard Schema V1 implementations\n *\n * Converts Standard Schema validation results into a format compatible\n * with the HTTP client's schema validation system.\n *\n * @param schema - The Standard Schema V1 implementation to adapt\n * @returns Adapter object with parse method\n *\n * @example\n * ```ts\n * const zodAdapter = standardSchemaAdapter(zodUserSchema);\n * const validatedUser = zodAdapter.parse(userData);\n * ```\n */\nexport function standardSchemaAdapter<T>(schema: StandardSchemaV1<unknown, T>) {\n return {\n /**\n * Parses and validates data using the Standard Schema\n *\n * @param data - The data to validate\n * @returns The validated and typed data\n * @throws Error if validation fails\n */\n parse: (data: unknown): T => {\n const result = schema['~standard'].validate(data)\n\n if (result instanceof Promise) {\n throw new Error('Async Standard Schema validation is not supported')\n }\n\n if ('issues' in result && result.issues) {\n const errorMessages = Array.from(result.issues)\n .map(issue => issue.message)\n .join('; ')\n throw new Error(`Standard Schema validation failed: ${errorMessages}`)\n }\n\n return result.value as T\n },\n }\n}\n\n/**\n * Creates a schema validator that supports Standard Schema V1 implementations\n *\n * Provides a validator that can work with any schema library that implements\n * the Standard Schema V1 specification, enabling interoperability between\n * different validation libraries.\n *\n * @returns SchemaValidator that supports Standard Schema V1\n *\n * @example\n * ```ts\n * const validator = createStandardSchemaValidator();\n * const client = new HttpClient({ schemaValidator: validator });\n * ```\n */\nexport function createStandardSchemaValidator(): SchemaValidator {\n return {\n /**\n * Validates data against a Standard Schema V1 implementation\n *\n * @param schema - The Standard Schema V1 to validate against\n * @param data - The data to validate\n * @returns The validated and typed data\n * @throws Error if validation fails or schema is invalid\n */\n validate<T>(schema: StandardSchemaV1<unknown, T>, data: unknown): T {\n if (!isStandardSchema(schema)) {\n throw new Error(\n 'Invalid schema: Schema must implement the Standard Schema interface'\n )\n }\n\n const adapter = standardSchemaAdapter<T>(schema)\n return adapter.parse(data)\n },\n\n /**\n * Checks if an object is a valid Standard Schema V1 implementation\n *\n * @param obj - The object to check\n * @returns True if the object is a valid Standard Schema V1\n */\n isSchema(obj: unknown): boolean {\n return isStandardSchema(obj)\n },\n }\n}\n","import {\n HttpError,\n InterceptorError,\n NetworkError,\n PathParameterError,\n SchemaValidationError,\n SerializationError,\n TimeoutError,\n} from './errors'\nimport { createSchemaValidator, type SchemaValidator } from './schema'\nimport type {\n EnforcedPathParamsOptions,\n HttpClientOptions,\n HttpMethod,\n RequestContext,\n RequestInterceptor,\n RequestOptions,\n RequestParamsType,\n ResponseInterceptor,\n ResponsePromise,\n ResponseType,\n RetryOptions,\n Schema,\n TypedRequestOptions,\n} from './types'\nimport { generatePath, type HasRequiredParams, type PathParams } from './utils'\n\n/**\n * Default retry configuration for HTTP requests\n */\nconst DEFAULT_RETRY_OPTIONS: Required<RetryOptions> = {\n maxRetries: 3,\n retryDelay: 300,\n backoffFactor: 2,\n retryStatusCodes: [429, 500, 502, 503, 504],\n retryNetworkErrors: true,\n maxRetryDelay: 30000,\n shouldRetry: () => true,\n}\n\nfunction validateAndNormalizeBaseUrl(baseUrl?: string): string {\n const hasLocation =\n typeof window !== 'undefined' &&\n typeof window.location !== 'undefined' &&\n window.location.origin !== 'null'\n\n if (!baseUrl) {\n // In browser environment, default to location.origin for relative paths\n return hasLocation ? window.location.origin : ''\n }\n\n // Allow relative paths like \"/api\" - they'll be resolved against location.origin or need absolute URLs in Node\n if (baseUrl.startsWith('/')) {\n // In Node.js or non-browser environments, relative paths are preserved as-is\n return hasLocation\n ? new URL(baseUrl, window.location.origin).href.replace(/\\/$/, '')\n : baseUrl.replace(/\\/$/, '')\n }\n\n try {\n new URL(baseUrl)\n } catch {\n throw new Error(\n `Invalid baseUrl: \"${baseUrl}\". Must be a valid absolute URL or relative path starting with \"/\".`\n )\n }\n\n return baseUrl.endsWith('/') ? baseUrl.slice(0, -1) : baseUrl\n}\n\n/**\n * Wraps a response promise with data extraction method\n * @param promise - The base response promise\n * @returns Promise with data method attached\n */\nfunction wrapResponsePromise<T>(\n promise: Promise<ResponseType<T>>\n): ResponsePromise<T> {\n const wrappedPromise = promise as ResponsePromise<T>\n\n wrappedPromise.data = async () => {\n const response = await promise\n return response.data\n }\n\n return wrappedPromise\n}\n\n/**\n * A modern, type-safe HTTP client with built-in schema validation, interceptors, retry logic, and compile-time path parameter validation.\n *\n * The HttpClient provides a fluent API for making HTTP requests with full TypeScript support,\n * automatic retry logic, request/response interceptors, and schema validation using popular\n * validation libraries like Zod, Valibot, and Arktype.\n *\n * @example\n * ```ts\n * import { HttpClient } from '1000fetches'\n * import { z } from 'zod'\n *\n * // Create a client instance\n * const client = new HttpClient({\n * baseUrl: 'https://api.example.com',\n * timeout: 5000,\n * headers: { 'Authorization': 'Bearer token' }\n * });\n *\n * const userSchema = z.object({\n * id: z.string(),\n * name: z.string(),\n * email: z.string()\n * });\n *\n * const response = await client.get('/users/:id', {\n * pathParams: { id: '123' },\n * schema: userSchema\n * });\n */\nexport class HttpClient {\n private baseUrl: string\n private defaultHeaders: Record<string, string>\n private defaultTimeout: number\n private schemaValidator: SchemaValidator\n private requestInterceptors: RequestInterceptor[]\n private responseInterceptors: ResponseInterceptor[]\n private defaultRetryOptions?: RetryOptions\n\n /**\n * Create a new HttpClient instance.\n *\n * @param options - Configuration options for the HTTP client\n *\n * @example\n * ```ts\n * // Basic configuration\n * const client = new HttpClient({\n * baseUrl: 'https://api.example.com'\n * });\n *\n * // With custom headers and timeout\n * const client = new HttpClient({\n * baseUrl: 'https://api.example.com',\n * headers: { 'Authorization': 'Bearer token' },\n * timeout: 10000\n * });\n *\n * // With custom schema validator\n * const client = new HttpClient({\n * baseUrl: 'https://api.example.com',\n * schemaValidator: createCustomValidator()\n * });\n *\n * // With retry configuration\n * const client = new HttpClient({\n * baseUrl: 'https://api.example.com',\n * retryOptions: {\n * maxRetries: 5,\n * retryDelay: 1000,\n * retryStatusCodes: [500, 502, 503]\n * }\n * });\n * ```\n */\n constructor(options: HttpClientOptions = {}) {\n this.baseUrl = validateAndNormalizeBaseUrl(options.baseUrl)\n this.defaultHeaders = options.headers || {}\n this.defaultTimeout = options.timeout || 30000 // 30 seconds default\n this.schemaValidator = options.schemaValidator || createSchemaValidator()\n this.requestInterceptors = options.requestInterceptors || []\n this.responseInterceptors = options.responseInterceptors || []\n this.defaultRetryOptions = options.retryOptions\n }\n\n /**\n * Add a request interceptor to modify requests before they're sent.\n *\n * Request interceptors are executed in the order they were added and can modify\n * the request context before it's sent to the server. This is useful for adding\n * authentication headers, logging, or transforming request data.\n *\n * @param interceptor - The interceptor function to add\n *\n * @example\n * ```ts\n * // Add authentication headers to all requests\n * client.addRequestInterceptor((context) => {\n * context.headers.set('Authorization', `Bearer ${getToken()}`);\n * return context;\n * });\n *\n * // Change the base URL for specific endpoints\n * client.addRequestInterceptor((context) => {\n * if (context.url.includes('/special/')) {\n * context.url = context.url.replace('api.example.com', 'special-api.example.com');\n * }\n * return context;\n * });\n *\n * // Log all outgoing requests\n * client.addRequestInterceptor((context) => {\n * console.log(`Making ${context.method} request to ${context.url}`);\n * return context;\n * });\n * ```\n */\n public addRequestInterceptor(interceptor: RequestInterceptor): void {\n this.requestInterceptors.push(interceptor)\n }\n\n /**\n * Add a response interceptor to process responses before they're returned.\n *\n * Response interceptors are executed in the order they were added and can modify\n * the response data before it's returned to the caller. This is useful for\n * transforming data, logging responses, or handling global error conditions.\n *\n * @param interceptor - The interceptor function to add\n *\n * @example\n * ```ts\n * // Log all responses\n * client.addResponseInterceptor((response) => {\n * console.log(`Response from ${response.raw.url}: ${response.status}`);\n * return response;\n * });\n *\n * // Transform response data\n * client.addResponseInterceptor((response) => {\n * if (Array.isArray(response.data)) {\n * response.data = response.data.map(item => transformItem(item));\n * }\n * return response;\n * });\n *\n * // Handle 401 responses by refreshing the token and retrying\n * client.addResponseInterceptor(async (response) => {\n * if (response.status === 401) {\n * await refreshToken();\n * // Make a new request (will use updated token)\n * return await client.request(response.raw.method, response.raw.url);\n * }\n * return response;\n * });\n * ```\n */\n public addResponseInterceptor(interceptor: ResponseInterceptor): void {\n this.responseInterceptors.push(interceptor)\n }\n\n /**\n * Determines if a request should be retried based on error type and retry configuration\n *\n * @param error - The error that occurred during the request\n * @param retryCount - Current retry attempt number\n * @param retryOptions - Retry configuration for this request\n * @returns Promise resolving to whether the request should be retried\n */\n private async shouldRetry(\n error: Error,\n retryCount: number,\n retryOptions: RetryOptions | boolean | undefined\n ): Promise<boolean> {\n if (retryOptions === false) return false\n\n const options = this.getRetryOptions(retryOptions)\n if (retryCount >= options.maxRetries) return false\n\n if (typeof options.shouldRetry === 'function') {\n try {\n return await options.shouldRetry(error, retryCount)\n } catch (retryError) {\n console.warn('Custom shouldRetry function failed:', retryError)\n }\n }\n\n if (error instanceof NetworkError && options.retryNetworkErrors) {\n return true\n }\n\n if (\n error instanceof HttpError &&\n options.retryStatusCodes.includes(error.status)\n ) {\n return true\n }\n\n if (error instanceof SchemaValidationError) {\n return false\n }\n\n if (error instanceof TimeoutError) {\n return true\n }\n\n return false\n }\n\n /**\n * Calculates the delay for the next retry attempt using exponential backoff with jitter\n *\n * @param retryCount - Current retry attempt number\n * @param options - Retry configuration options\n * @returns Delay in milliseconds before the next retry attempt\n */\n private getRetryDelay(\n retryCount: number,\n options: Required<RetryOptions>\n ): number {\n const baseDelay =\n options.retryDelay * Math.pow(options.backoffFactor, retryCount)\n const cappedDelay = Math.min(baseDelay, options.maxRetryDelay)\n\n // Add jitter (+-20%) to prevent thundering herd problem\n const jitterRange = cappedDelay * 0.2\n const jitter = jitterRange * (Math.random() * 2 - 1)\n const finalDelay = cappedDelay + jitter\n\n return Math.max(1, Math.floor(finalDelay))\n }\n\n /**\n * Merges provided retry options with default configuration\n *\n * @param retryOptions - Retry options to merge with defaults\n * @returns Complete retry configuration with all required properties\n */\n private getRetryOptions(\n retryOptions?: RetryOptions | boolean\n ): Required<RetryOptions> {\n if (retryOptions === false) {\n return {\n ...DEFAULT_RETRY_OPTIONS,\n maxRetries: 0,\n }\n }\n\n if (retryOptions === true) {\n return {\n ...DEFAULT_RETRY_OPTIONS,\n ...this.defaultRetryOptions,\n }\n }\n\n if (typeof retryOptions === 'object') {\n return {\n ...DEFAULT_RETRY_OPTIONS,\n ...this.defaultRetryOptions,\n ...retryOptions,\n }\n }\n\n return {\n ...DEFAULT_RETRY_OPTIONS,\n ...this.defaultRetryOptions,\n }\n }\n\n /**\n * Creates a promise that resolves after the specified delay\n *\n * @param ms - Delay duration in milliseconds\n * @returns Promise that resolves after the delay\n */\n private sleep(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms))\n }\n\n /**\n * Makes an HTTP request with automatic retry capability\n *\n * @param method - HTTP method to use for the request\n * @param url - URL path for the request (supports path parameters)\n * @param options - Request configuration options\n * @returns Promise resolving to the response data with data extraction method\n *\n * @example\n * ```ts\n * // Simple GET request\n * const response = await client.request('GET', '/users/1');\n *\n * // POST request with body and path parameters\n * const response = await client.request('POST', '/users/:id/posts', {\n * pathParams: { id: 1 },\n * body: { title: 'New Post', content: 'Hello World' },\n * schema: userPostSchema\n * });\n *\n * // Data extraction\n * const user = await client.request('GET', '/users/1', { schema: userSchema }).data();\n * ```\n */\n public request<\n Path extends string = string,\n TResponse = unknown,\n TBody = unknown,\n TParams extends RequestParamsType = RequestParamsType,\n >(\n method: HttpMethod,\n url: Path,\n options: TypedRequestOptions<TBody, TResponse, TParams, Path> = {}\n ): ResponsePromise<TResponse> {\n return wrapResponsePromise(\n this.requestWithRetry<Path, TResponse, TBody, TParams>(\n method,\n url,\n options\n )\n )\n }\n\n /**\n * Internal method that handles retry logic for requests\n */\n private async requestWithRetry<\n Path extends string = string,\n TResponse = unknown,\n TBody = unknown,\n TParams extends RequestParamsType = RequestParamsType,\n >(\n method: HttpMethod,\n url: Path,\n options: TypedRequestOptions<TBody, TResponse, TParams, Path>\n ): Promise<ResponseType<TResponse>> {\n let retryCount = 0\n\n while (true) {\n try {\n return await this.executeRequest<Path, TResponse, TBody, TParams>(\n method,\n url,\n options\n )\n } catch (error) {\n if (!(error instanceof Error)) {\n throw new NetworkError(String(error), undefined)\n }\n\n if (await this.shouldRetry(error, retryCount, options.retry)) {\n const retryOptions = this.getRetryOptions(options.retry)\n const delay = this.getRetryDelay(retryCount, retryOptions)\n await this.sleep(delay)\n\n retryCount++\n continue\n }\n\n throw error\n }\n }\n }\n\n /**\n * Executes a single HTTP request without retry logic\n *\n * @param method - HTTP method for the request\n * @param url - URL path with optional path parameters\n * @param options - Request configuration and validation options\n * @returns Promise resolving to the response data\n */\n private async executeRequest<\n Path extends string = string,\n TResponse = unknown,\n TBody = unknown,\n TParams extends RequestParamsType = RequestParamsType,\n >(\n method: HttpMethod,\n url: Path,\n options: TypedRequestOptions<TBody, TResponse, TParams, Path> = {}\n ): Promise<ResponseType<TResponse>> {\n let resolvedUrl = this.resolveUrl(url, options.pathParams)\n\n let requestContext: RequestContext<TBody> = {\n url: resolvedUrl,\n method,\n params: options.params,\n headers: this.prepareHeaders(options.headers),\n body: options.body,\n fetchOptions: {\n credentials: options.credentials,\n cache: options.cache,\n mode: options.mode,\n redirect: options.redirect,\n },\n }\n\n for (const interceptor of this.requestInterceptors) {\n try {\n requestContext = await interceptor(requestContext)\n } catch (error) {\n throw new InterceptorError(\n `Request interceptor failed: ${error instanceof Error ? error.message : String(error)}`,\n 'request',\n resolvedUrl,\n method,\n error instanceof Error ? error : undefined\n )\n }\n }\n\n resolvedUrl = requestContext.url\n\n if (\n requestContext.params &&\n Object.keys(requestContext.params).length > 0\n ) {\n const searchParams = new URLSearchParams()\n for (const [key, value] of Object.entries(requestContext.params)) {\n if (value !== undefined) {\n searchParams.append(key, String(value))\n }\n }\n const queryString = searchParams.toString()\n if (queryString) {\n resolvedUrl += (resolvedUrl.includes('?') ? '&' : '?') + queryString\n }\n }\n\n const requestInit: RequestInit = {\n method: requestContext.method,\n headers: requestContext.headers,\n ...requestContext.fetchOptions,\n }\n\n if (\n requestContext.body !== undefined &&\n (requestContext.method === 'POST' ||\n requestContext.method === 'PUT' ||\n requestContext.method === 'PATCH')\n ) {\n if (\n requestContext.body instanceof FormData ||\n requestContext.body instanceof Blob ||\n requestContext.body instanceof ArrayBuffer ||\n requestContext.body instanceof URLSearchParams ||\n typeof requestContext.body === 'string'\n ) {\n requestInit.body = requestContext.body as BodyInit\n } else {\n try {\n requestInit.body = JSON.stringify(requestContext.body)\n } catch (error) {\n throw new SerializationError(\n `Failed to serialize request body: ${error instanceof Error ? error.message : 'Invalid data structure'}`,\n error instanceof Error ? error : undefined\n )\n }\n }\n }\n\n const timeoutDuration = options.timeout || this.defaultTimeout\n const controller = new AbortController()\n const timeoutId = setTimeout(() => controller.abort(), timeoutDuration)\n\n const requestSignal = requestContext.signal || options.signal\n let cleanupSignals: VoidFunction | undefined\n const signal = requestSignal\n ? (() => {\n const result = this.mergeAbortSignals(\n requestSignal,\n controller.signal\n )\n cleanupSignals = result.cleanup\n return result.signal\n })()\n : controller.signal\n\n try {\n const response = await fetch(resolvedUrl, {\n ...requestInit,\n signal,\n })\n\n let responseData = await this.processResponse<TResponse>(\n response,\n options,\n method,\n resolvedUrl\n )\n\n if (options.schema) {\n responseData.data = this.validateWithSchema<TResponse>(\n options.schema,\n responseData.data\n )\n }\n\n return responseData\n } catch (error) {\n if (\n (error instanceof DOMException && error.name === 'AbortError') ||\n (error instanceof Error && error.name === 'AbortError') ||\n (error instanceof Error &&\n error.message.toLowerCase().includes('timeout'))\n ) {\n throw new TimeoutError(\n `Request timed out after ${timeoutDuration}ms`,\n error instanceof Error ? error : undefined\n )\n }\n\n if (\n error instanceof HttpError ||\n error instanceof SchemaValidationError ||\n error instanceof InterceptorError ||\n error instanceof PathParameterError ||\n error instanceof SerializationError\n ) {\n throw error\n }\n\n throw new NetworkError(\n error instanceof Error ? error.message : String(error),\n error instanceof Error ? error : undefined\n )\n } finally {\n clearTimeout(timeoutId)\n cleanupSignals?.()\n }\n }\n\n private validateWithSchema<T>(\n schema: Schema<T>,\n data: unknown,\n errorPrefix = 'Response schema validation failed'\n ): T {\n try {\n return this.schemaValidator.validate(schema, data)\n } catch (error) {\n throw new SchemaValidationError(\n `${errorPrefix}: ${error instanceof Error ? error.message : 'Unknown error'}`,\n schema,\n data,\n error instanceof Error ? error : undefined\n )\n }\n }\n\n /**\n * Prepares headers for HTTP requests by merging default and custom headers\n *\n * @param customHeaders - Additional headers to include in the request\n * @returns Headers object with all headers properly set\n */\n private prepareHeaders(customHeaders: Record<string, string> = {}): Headers {\n const headers = new Headers()\n\n for (const [key, value] of Object.entries(this.defaultHeaders)) {\n if (value != null) {\n headers.set(key, String(value))\n }\n }\n\n for (const [key, value] of Object.entries(customHeaders)) {\n if (value != null) {\n headers.set(key, String(value))\n }\n }\n\n return headers\n }\n\n /**\n * Extracts headers from Headers object into a plain record\n *\n * @param headers - Headers object to extract from\n * @returns Record containing header key-value pairs\n */\n private extractHeaders(headers: Headers): Record<string, string> {\n const result: Record<string, string> = {}\n headers.forEach((value, key) => {\n result[key] = value\n })\n return result\n }\n\n /**\n * Creates an HttpError instance with response details\n *\n * @param response - The HTTP response that caused the error\n * @param data - Response data (if any)\n * @param url - The URL that was requested\n * @param method - The HTTP method used\n * @param customStatusText - Optional custom status text\n * @param cause - Optional underlying error that caused this HTTP error\n * @returns HttpError instance with complete error information\n */\n private createHttpError(\n response: globalThis.Response,\n data: unknown,\n url: string,\n method: string,\n customStatusText?: string,\n cause?: Error\n ): HttpError {\n return new HttpError(\n `Request failed with status code ${response.status}`,\n response.status,\n customStatusText || response.statusText,\n data,\n response,\n url,\n method,\n cause\n )\n }\n\n private async parseResponseBody(\n response: globalThis.Response,\n options: RequestOptions\n ): Promise<unknown> {\n const contentType = response.headers.get('content-type') ?? ''\n\n try {\n if (options.responseType === 'text') {\n return await response.text()\n } else if (options.responseType === 'blob') {\n return await response.blob()\n } else if (options.responseType === 'arrayBuffer') {\n return await response.arrayBuffer()\n } else if (contentType.includes('application/json')) {\n const text = await response.text()\n if (!text) {\n return null\n }\n return JSON.parse(text)\n } else {\n return await response.text()\n }\n } catch (e) {\n if (response.status === 204) {\n return undefined\n }\n\n if (\n contentType.includes('application/json') &&\n e instanceof SyntaxError\n ) {\n throw new Error(`Failed to parse JSON response: ${e.message}`)\n }\n\n throw e\n }\n }\n\n private async processResponse<T, TBody = unknown>(\n response: globalThis.Response,\n options: TypedRequestOptions<TBody, T>,\n method: HttpMethod,\n url: string\n ): Promise<ResponseType<T>> {\n const headers = this.extractHeaders(response.headers)\n\n const validateStatus =\n options.validateStatus ||\n ((status: number) => status >= 200 && status < 300)\n\n const data = await this.parseResponseBody(response, options)\n\n if (!validateStatus(response.status)) {\n throw this.createHttpError(response, data, url, method)\n }\n\n const responseObj: ResponseType<unknown> = {\n data,\n status: response.status,\n statusText: response.statusText,\n headers,\n method,\n url,\n raw: response,\n }\n\n let processedResponse = responseObj\n const originalStatus = responseObj.status\n\n for (const interceptor of this.responseInterceptors) {\n try {\n processedResponse = await interceptor(processedResponse)\n } catch (error) {\n throw new InterceptorError(\n `Response interceptor failed: ${error instanceof Error ? error.message : String(error)}`,\n 'response',\n url,\n method,\n error instanceof Error ? error : undefined\n )\n }\n }\n\n // Only re-validate if interceptors changed the status\n if (\n processedResponse.status !== originalStatus &&\n !validateStatus(processedResponse.status)\n ) {\n throw this.createHttpError(\n response,\n processedResponse.data,\n url,\n method,\n processedResponse.statusText\n )\n }\n\n return processedResponse as ResponseType<T>\n }\n\n private mergeAbortSignals(\n signal1: AbortSignal,\n signal2: AbortSignal\n ): { signal: AbortSignal; cleanup?: VoidFunction } {\n if (signal1.aborted || signal2.aborted) {\n const controller = new AbortController()\n controller.abort()\n return { signal: controller.signal }\n }\n\n const controller = new AbortController()\n\n const abortHandler = () => {\n controller.abort()\n cleanup()\n }\n\n const cleanup = () => {\n signal1.removeEventListener('abort', abortHandler)\n signal2.removeEventListener('abort', abortHandler)\n }\n\n signal1.addEventListener('abort', abortHandler)\n signal2.addEventListener('abort', abortHandler)\n\n return { signal: controller.signal, cleanup }\n }\n\n /**\n * Send a GET request with schema validation (type inferred from schema).\n *\n * @example\n * // Get full response\n * const response = await client.get('/users/:id', {\n * pathParams: { id: '123' },\n * schema: z.object({ id: z.string(), name: z.string() })\n * })\n *\n * @example\n * // Extract data directly\n * const user = await client.get('/users/:id', {\n * pathParams: { id: '123' },\n * schema: userSchema\n * }).data()\n */\n public get<\n TResponse,\n Path extends string = string,\n TParams extends RequestParamsType = RequestParamsType,\n >(\n url: Path,\n options: EnforcedPathParamsOptions<void, TResponse, TParams, Path> & {\n schema: Schema<TResponse>\n }\n ): ResponsePromise<TResponse>\n\n /**\n * Send a GET request without schema (response.data is unknown).\n *\n * @example\n * const response = await client.get('/users')\n *\n * @example\n * const data = await client.get('/users').data()\n */\n public get<\n Path extends string,\n TParams extends RequestParamsType = RequestParamsType,\n >(\n url: Path,\n ...args: HasRequiredParams<Path> extends true\n ? [\n options: Omit<\n EnforcedPathParamsOptions<void, unknown, TParams, Path>,\n 'schema'\n >,\n ]\n : [\n options?: Omit<\n EnforcedPathParamsOptions<void, unknown, TParams, Path>,\n 'schema'\n >,\n ]\n ): ResponsePromise<unknown>\n\n public get<\n TResponse,\n Path extends string = string,\n TParams extends RequestParamsType = RequestParamsType,\n >(\n url: Path,\n options?: EnforcedPathParamsOptions<void, TResponse, TParams, Path>\n ): ResponsePromise<TResponse | unknown> {\n return this.request<Path, TResponse, void, TParams>(\n 'GET',\n url,\n options || {}\n )\n }\n\n /**\n * Send a POST request with schema validation (type inferred from schema).\n *\n * @example\n * const response = await client.post('/users', userData, {\n * schema: z.object({ id: z.string(), name: z.string() })\n * })\n *\n * @example\n * const user = await client.post('/users', userData, { schema: userSchema }).data()\n */\n public post<\n TResponse,\n Path extends string = string,\n TParams extends RequestParamsType = RequestParamsType,\n TBody = unknown,\n >(\n url: Path,\n body: TBody | undefined,\n options: Omit<\n EnforcedPathParamsOptions<TBody, TResponse, TParams, Path>,\n 'body'\n > & { schema: Schema<TResponse> }\n ): ResponsePromise<TResponse>\n\n /**\n * Send a POST request without schema (response.data is unknown).\n *\n * @example\n * const response = await client.post('/users', userData)\n *\n * @example\n * const data = await client.post('/users', userData).data()\n */\n public post<\n Path extends string,\n TParams extends RequestParamsType = RequestParamsType,\n TBody = unknown,\n >(\n url: Path,\n ...args: HasRequiredParams<Path> extends true\n ?\n | [\n body: TBody,\n options: Omit<\n EnforcedPathParamsOptions<TBody, unknown, TParams, Path>,\n 'body' | 'schema'\n >,\n ]\n | [\n body: undefined,\n options: Omit<\n EnforcedPathParamsOptions<TBody, unknown, TParams, Path>,\n 'body' | 'schema'\n >,\n ]\n : [\n body?: TBody,\n options?: Omit<\n EnforcedPathParamsOptions<TBody, unknown, TParams, Path>,\n 'body' | 'schema'\n >,\n ]\n ): ResponsePromise<unknown>\n\n public post<\n TResponse,\n Path extends string = string,\n TParams extends RequestParamsType = RequestParamsType,\n TBody = unknown,\n >(\n url: Path,\n body?: TBody,\n options?: Omit<\n EnforcedPathParamsOptions<TBody, TResponse, TParams, Path>,\n 'body'\n >\n ): ResponsePromise<TResponse | unknown> {\n return this.request<Path, TResponse, TBody, TParams>('POST', url, {\n ...(options || {}),\n body,\n })\n }\n\n /**\n * Send a PUT request with schema validation (type inferred from schema).\n *\n * @example\n * const response = await client.put('/users/:id', updatedData, {\n * pathParams: { id: '123' },\n * schema: z.object({ id: z.string(), name: z.string() })\n * })\n *\n * @example\n * const user = await client.put('/users/:id', updatedData, {\n * pathParams: { id: '123' },\n * schema: userSchema\n * }).data()\n */\n public put<\n TResponse,\n Path extends string = string,\n TParams extends RequestParamsType = RequestParamsType,\n TBody = unknown,\n >(\n url: Path,\n body: TBody | undefined,\n options: Omit<\n EnforcedPathParamsOptions<TBody, TResponse, TParams, Path>,\n 'body'\n > & { schema: Schema<TResponse> }\n ): ResponsePromise<TResponse>\n\n /**\n * Send a PUT request without schema (response.data is unknown).\n *\n * @example\n * const response = await client.put('/users/:id', updatedData, {\n * pathParams: { id: '123' }\n * })\n *\n * @example\n * const data = await client.put('/users/:id', updatedData, {\n * pathParams: { id: '123' }\n * }).data()\n */\n public put<\n Path extends string,\n TParams extends RequestParamsType = RequestParamsType,\n TBody = unknown,\n >(\n url: Path,\n ...args: HasRequiredParams<Path> extends true\n ?\n | [\n body: TBody,\n options: Omit<\n EnforcedPathParamsOptions<TBody, unknown, TParams, Path>,\n 'body' | 'schema'\n >,\n ]\n | [\n body: undefined,\n options: Omit<\n EnforcedPathParamsOptions<TBody, unknown, TParams, Path>,\n 'body' | 'schema'\n >,\n ]\n : [\n body?: TBody,\n options?: Omit<\n EnforcedPathParamsOptions<TBody, unknown, TParams, Path>,\n 'body' | 'schema'\n >,\n ]\n ): ResponsePromise<unknown>\n\n public put<\n TResponse,\n Path extends string = string,\n TParams extends RequestParamsType = RequestParamsType,\n TBody = unknown,\n >(\n url: Path,\n body?: TBody,\n options?: Omit<\n EnforcedPathParamsOptions<TBody, TResponse, TParams, Path>,\n 'body'\n >\n ): ResponsePromise<TResponse | unknown> {\n return this.request<Path, TResponse, TBody, TParams>('PUT', url, {\n ...(options || {}),\n body,\n })\n }\n\n /**\n * Send a PATCH request with schema validation (type inferred from schema).\n *\n * @example\n * const response = await client.patch('/users/:id', partialData, {\n * pathParams: { id: '123' },\n * schema: z.object({ id: z.string(), name: z.string() })\n * })\n *\n * @example\n * const user = await client.patch('/users/:id', partialData, {\n * pathParams: { id: '123' },\n * schema: userSchema\n * }).data()\n */\n public patch<\n TResponse,\n Path extends string = string,\n TParams extends RequestParamsType = RequestParamsType,\n TBody = unknown,\n >(\n url: Path,\n body: TBody | undefined,\n options: Omit<\n EnforcedPathParamsOptions<TBody, TResponse, TParams, Path>,\n 'body'\n > & { schema: Schema<TResponse> }\n ): ResponsePromise<TResponse>\n\n /**\n * Send a PATCH request without schema (response.data is unknown).\n *\n * @example\n * const response = await client.patch('/users/:id', partialData, {\n * pathParams: { id: '123' }\n * })\n *\n * @example\n * const data = await client.patch('/users/:id', partialData, {\n * pathParams: { id: '123' }\n * }).data()\n */\n public patch<\n Path extends string,\n TParams extends RequestParamsType = RequestParamsType,\n TBody = unknown,\n >(\n url: Path,\n ...args: HasRequiredParams<Path> extends true\n ?\n | [\n body: TBody,\n options: Omit<\n EnforcedPathParamsOptions<TBody, unknown, TParams, Path>,\n 'body' | 'schema'\n >,\n ]\n | [\n body: undefined,\n options: Omit<\n EnforcedPathParamsOptions<TBody, unknown, TParams, Path>,\n 'body' | 'schema'\n >,\n ]\n : [\n body?: TBody,\n options?: Omit<\n EnforcedPathParamsOptions<TBody, unknown, TParams, Path>,\n 'body' | 'schema'\n >,\n ]\n ): ResponsePromise<unknown>\n\n public patch<\n TResponse,\n Path extends string = string,\n TParams extends RequestParamsType = RequestParamsType,\n TBody = unknown,\n >(\n url: Path,\n body?: TBody,\n options?: Omit<\n EnforcedPathParamsOptions<TBody, TResponse, TParams, Path>,\n 'body'\n >\n ): ResponsePromise<TResponse | unknown> {\n return this.request<Path, TResponse, TBody, TParams>('PATCH', url, {\n ...(options || {}),\n body,\n })\n }\n\n /**\n * Send a DELETE request with schema validation (type inferred from schema).\n *\n * @example\n * const response = await client.delete('/users/:id', {\n * pathParams: { id: '123' },\n * schema: z.object({ success: z.boolean() })\n * })\n *\n * @example\n * const result = await client.delete('/users/:id', {\n * pathParams: { id: '123' },\n * schema: deleteResultSchema\n * }).data()\n */\n public delete<\n TResponse,\n Path extends string = string,\n TParams extends RequestParamsType = RequestParamsType,\n >(\n url: Path,\n options: EnforcedPathParamsOptions<void, TResponse, TParams, Path> & {\n schema: Schema<TResponse>\n }\n ): ResponsePromise<TResponse>\n\n /**\n * Send a DELETE request without schema (response.data is unknown).\n *\n * @example\n * const response = await client.delete('/users/:id', {\n * pathParams: { id: '123' }\n * })\n *\n * @example\n * const data = await client.delete('/users/:id', {\n * pathParams: { id: '123' }\n * }).data()\n */\n public delete<\n Path extends string,\n TParams extends RequestParamsType = RequestParamsType,\n >(\n url: Path,\n ...args: HasRequiredParams<Path> extends true\n ? [\n options: Omit<\n EnforcedPathParamsOptions<void, unknown, TParams, Path>,\n 'schema'\n >,\n ]\n : [\n options?: Omit<\n EnforcedPathParamsOptions<void, unknown, TParams, Path>,\n 'schema'\n >,\n ]\n ): ResponsePromise<unknown>\n\n public delete<\n TResponse,\n Path extends string = string,\n TParams extends RequestParamsType = RequestParamsType,\n >(\n url: Path,\n options?: EnforcedPathParamsOptions<void, TResponse, TParams, Path>\n ): ResponsePromise<TResponse | unknown> {\n return this.request<Path, TResponse, void, TParams>(\n 'DELETE',\n url,\n options || {}\n )\n }\n\n /**\n * Validates path parameters against the URL template\n *\n * @param url - URL template with path parameters (e.g., '/users/:id')\n * @param pathParams - Path parameters to validate\n * @throws Error if required path parameters are missing or invalid\n */\n private validatePathParams<Path extends string>(\n url: Path,\n pathParams?: PathParams<Path>\n ): void {\n if (!pathParams) {\n const requiredParams = this.extractRequiredPathParams(url)\n\n if (requiredParams.length > 0) {\n throw new PathParameterError(\n `Missing required path parameters for URL \"${url}\": ${requiredParams.join(', ')}. ` +\n `Please provide pathParams: { ${requiredParams.map(p => `${p}: value`).join(', ')} }`,\n url,\n requiredParams,\n []\n )\n }\n return\n }\n\n const requiredParams = this.extractRequiredPathParams(url)\n const providedParams = Object.keys(pathParams)\n\n const missingParams = requiredParams.filter(\n param => !providedParams.includes(param)\n )\n if (missingParams.length > 0) {\n throw new PathParameterError(\n `Missing required path parameters: ${missingParams.join(', ')}. ` +\n `Provided: ${providedParams.join(', ')}`,\n url,\n requiredParams,\n providedParams\n )\n }\n\n // const unusedParams = providedParams.filter(\n // param => !requiredParams.includes(param)\n // )\n // if (unusedParams.length > 0) {\n // console.warn(\n // `Unused path parameters provided: ${unusedParams.join(', ')}. ` +\n // `URL \"${url}\" does not contain these parameters.`\n // )\n // }\n }\n\n /**\n * Extracts required path parameters from a URL template\n *\n * @param url - URL template to extract parameters from\n * @returns Array of required parameter names\n */\n private extractRequiredPathParams(url: string): string[] {\n if (url.includes('?')) {\n throw new PathParameterError(\n 'Optional path parameters (e.g., :variable?) are not supported',\n url,\n [],\n []\n )\n }\n\n const matches = url.match(/:([a-zA-Z0-9_]+)/g)\n\n return matches ? matches.map(match => match.slice(1)) : []\n }\n\n /**\n * Resolves a URL template with path parameters and base URL\n *\n * @param url - URL template with optional path parameters\n * @param pathParams - Path parameters to interpolate into the URL\n * @returns Fully resolved URL with base URL and path parameters applied\n */\n private resolveUrl<Path extends string>(\n url: Path,\n pathParams?: PathParams<Path>\n ): string {\n this.validatePathParams(url, pathParams)\n\n const interpolatedUrl = pathParams ? generatePath(url, pathParams) : url\n\n if (/^https?:\\/\\//i.test(interpolatedUrl)) {\n return interpolatedUrl\n }\n\n const path = interpolatedUrl.startsWith('/')\n ? interpolatedUrl.slice(1)\n : interpolatedUrl\n\n return `${this.baseUrl}/${path}`\n }\n}\n","import {\n createStandardSchemaValidator as createStdSchemaValidator,\n isStandardSchema,\n} from './standard-schema'\n\nimport { Schema } from './types'\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\n * @throws {SchemaValidationError} If the data doesn't match the schema\n */\n validate<T>(schema: Schema<T>, data: unknown): T\n\n /**\n * Check if an object is a valid schema.\n *\n * @param obj - The object to check\n * @returns True if the object is a valid schema, false otherwise\n */\n isSchema(obj: unknown): boolean\n}\n\n/**\n * Create a default schema validator that supports Standard Schema.\n *\n * This validator only works with schemas that implement the Standard Schema\n * interface. For full support of Zod, Valibot, and Arktype, use the\n * appropriate validator from their respective packages.\n *\n * @returns A schema validator instance\n *\n * @example\n * ```ts\n * import { createSchemaValidator } from '1000fetches'\n *\n * const validator = createSchemaValidator();\n *\n * // Use with HttpClient\n * const client = new HttpClient({\n * schemaValidator: validator\n * });\n * ```\n */\nexport function createSchemaValidator(): SchemaValidator {\n return {\n validate<T>(schema: Schema<T>, data: unknown): T {\n if (!isStandardSchema(schema)) {\n throw new Error(\n 'Invalid schema: Schema must implement the Standard Schema interface'\n )\n }\n\n return createStdSchemaValidator().validate(schema, data)\n },\n\n isSchema(obj: unknown): boolean {\n return isStandardSchema(obj)\n },\n }\n}\n\nexport { createStdSchemaValidator as createStandardSchemaValidator }\n","import { PathParameterError } from '../errors'\n\n/**\n * Strips protocol from URL (e.g., https://, http://)\n */\ntype StripProtocol<T extends string> = T extends `${string}://${infer After}`\n ? After\n : T\n\n/**\n * Strips host and optional port from URL, keeping only the path\n * Handles cases like \"localhost:3000/users\" -> \"/users\"\n */\ntype StripHost<T extends string> = T extends `${infer _Host}/${infer Path}`\n ? `/${Path}`\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 `${string}=${string}` | `${string}=${string}&${string}`\n ? Path // Only strip if it looks like a query string (key=value)\n : T // Don't strip if it's part of a path parameter\n : T\n\n/**\n * Normalizes URL to path only, stripping protocol, host, port, and query\n */\ntype NormalizePath<T extends string> = StripQuery<StripHost<StripProtocol<T>>>\n\n/**\n * Removes optional suffix from param name (e.g., \"id?\" -> \"id\")\n * This makes optional params work seamlessly as required params\n */\ntype CleanParamName<S extends string> = S extends `${infer Name}?` ? Name : S\n\n/**\n * Extracts all path parameters from a route\n * Optional params like :id? are treated as required params (id)\n */\ntype ExtractRouteParams<T extends string> =\n NormalizePath<T> extends `${infer _Before}:${infer AfterColon}`\n ? AfterColon extends `${infer Param}/${infer Rest}`\n ? CleanParamName<Param> | ExtractRouteParams<`/${Rest}`>\n : CleanParamName<AfterColon>\n : never\n\nexport type HasRequiredParams<T extends string> = [\n ExtractRouteParams<T>,\n] extends [never]\n ? false\n : true\n\n/**\n * PathParams type - extracts parameter names and their types\n */\nexport type PathParams<Path extends string> = {\n [K in ExtractRouteParams<Path>]: string | number\n}\n\n/**\n * RequirePathParams enforces pathParams when needed\n * Optional params are seamlessly treated as required params\n */\nexport type RequirePathParams<Path extends string, T> =\n HasRequiredParams<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: Path,\n params: PathParams<Path> = {} as PathParams<Path>\n): string {\n return path.replace(/:([a-zA-Z0-9_]+)/g, (_match, paramName: string) => {\n if (params[paramName as keyof PathParams<Path>] === undefined) {\n throw new PathParameterError(\n `Missing required path parameter: ${paramName}`,\n path,\n [paramName],\n Object.keys(params)\n )\n }\n return String(params[paramName as keyof PathParams<Path>])\n })\n}\n"],"names":["HttpError","Error","name","status","statusText","data","response","url","method","cause","constructor","message","super","this","NetworkError","SchemaValidationError","schema","TimeoutError","PathParameterError","requiredParams","providedParams","InterceptorError","interceptorType","SerializationError","isStandardSchema","obj","validate","version","vendor","createStandardSchemaValidator","adapter","parse","result","Promise","issues","errorMessages","Array","from","map","issue","join","value","standardSchemaAdapter","isSchema","DEFAULT_RETRY_OPTIONS","maxRetries","retryDelay","backoffFactor","retryStatusCodes","retryNetworkErrors","maxRetryDelay","shouldRetry","baseUrl","defaultHeaders","defaultTimeout","schemaValidator","requestInterceptors","responseInterceptors","defaultRetryOptions","options","hasLocation","window","location","origin","startsWith","URL","href","replace","endsWith","slice","validateAndNormalizeBaseUrl","headers","timeout","createStdSchemaValidator","retryOptions","addRequestInterceptor","interceptor","push","addResponseInterceptor","error","retryCount","getRetryOptions","retryError","console","warn","includes","getRetryDelay","baseDelay","Math","pow","cappedDelay","min","finalDelay","random","max","floor","sleep","ms","resolve","setTimeout","request","promise","wrappedPromise","async","wrapResponsePromise","requestWithRetry","executeRequest","String","retry","delay","resolvedUrl","resolveUrl","pathParams","requestContext","params","prepareHeaders","body","fetchOptions","credentials","cache","mode","redirect","Object","keys","length","searchParams","URLSearchParams","key","entries","append","queryString","toString","requestInit","FormData","Blob","ArrayBuffer","JSON","stringify","timeoutDuration","controller","AbortController","timeoutId","abort","requestSignal","signal","cleanupSignals","mergeAbortSignals","cleanup","fetch","responseData","processResponse","validateWithSchema","DOMException","toLowerCase","clearTimeout","errorPrefix","customHeaders","Headers","set","extractHeaders","forEach","createHttpError","customStatusText","parseResponseBody","contentType","get","responseType","text","blob","arrayBuffer","e","SyntaxError","validateStatus","responseObj","raw","processedResponse","originalStatus","signal1","signal2","aborted","abortHandler","removeEventListener","addEventListener","post","put","patch","validatePathParams","extractRequiredPathParams","p","missingParams","filter","param","matches","match","interpolatedUrl","path","_match","paramName","generatePath","test"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs.js","sources":["../src/errors.ts","../src/standard-schema.ts","../src/client.ts","../src/schema.ts","../src/utils/path.ts"],"sourcesContent":["interface HttpClientError {\n name: string\n message: string\n cause?: Error\n stack?: string\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 enhancedMessage = `HTTP ${status} ${statusText}: ${message} (${method} ${url})`\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 }\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 }\n}\n\nexport class SchemaValidationError extends Error implements HttpClientError {\n public readonly name = 'SchemaValidationError'\n public readonly schema: unknown\n public readonly data: unknown\n public override readonly cause?: Error\n\n constructor(message: string, schema: unknown, data: unknown, cause?: Error) {\n super(message, { cause })\n this.schema = schema\n this.data = data\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 }\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 super(message, { cause })\n this.url = url\n this.requiredParams = requiredParams\n this.providedParams = providedParams\n }\n}\n\nexport class InterceptorError extends Error implements HttpClientError {\n public readonly name = 'InterceptorError'\n public readonly interceptorType: '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 interceptorType: 'request' | 'response',\n url?: string,\n method?: string,\n cause?: Error\n ) {\n super(message, { cause })\n this.interceptorType = interceptorType\n this.url = url\n this.method = method\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 }\n}\n","import { SchemaValidator } from './schema'\n\n/**\n * Standard Schema V1 interface implementation\n *\n * This interface defines the structure for schema validation libraries\n * that conform to the Standard Schema specification.\n *\n * @see https://github.com/standard-schema/standard-schema\n */\nexport interface StandardSchemaV1<Input = unknown, Output = Input> {\n /** The Standard Schema properties containing validation logic and metadata */\n readonly '~standard': StandardSchemaV1.Props<Input, Output>\n}\n\n/**\n * Namespace containing Standard Schema V1 type definitions\n */\nexport namespace StandardSchemaV1 {\n /**\n * Core properties interface for Standard Schema V1\n */\n export interface Props<Input = unknown, Output = Input> {\n /** The version number of the Standard Schema specification */\n readonly version: 1\n /** The name of the schema validation library (e.g., 'zod', 'valibot') */\n readonly vendor: string\n /**\n * Validates unknown input values against the schema\n *\n * @param value - The value to validate\n * @returns Promise or direct result containing validation outcome\n */\n readonly validate: (\n value: unknown\n ) => Result<Output> | Promise<Result<Output>>\n /** Type information for input and output types */\n readonly types?: Types<Input, Output> | undefined\n }\n\n /**\n * Union type representing the result of schema validation\n */\n export type Result<Output> = SuccessResult<Output> | FailureResult\n\n /**\n * Interface for successful validation results\n */\n export interface SuccessResult<Output> {\n readonly value: Output\n readonly issues?: undefined\n }\n\n /**\n * Interface for failed validation results\n */\n export interface FailureResult {\n readonly issues: ReadonlyArray<Issue>\n }\n\n /**\n * Interface for individual validation error details\n */\n export interface Issue {\n /** Human-readable error message describing the validation failure */\n readonly message: string\n /**\n * Path to the property that failed validation\n * Useful for nested object validation to pinpoint the exact location\n * of validation failures.\n */\n readonly path?: ReadonlyArray<PropertyKey | PathSegment> | undefined\n }\n\n /**\n * Interface for path segment information in validation errors\n */\n export interface PathSegment {\n readonly key: PropertyKey\n }\n\n /**\n * Interface for type information associated with a schema\n */\n export interface Types<Input = unknown, Output = Input> {\n readonly input: Input\n readonly output: Output\n }\n\n /**\n * Type utility to infer the input type from a Standard Schema\n */\n export type InferInput<Schema extends StandardSchemaV1> = NonNullable<\n Schema['~standard']['types']\n >['input']\n\n /**\n * Type utility to infer the output type from a Standard Schema\n */\n export type InferOutput<Schema extends StandardSchemaV1> = NonNullable<\n Schema['~standard']['types']\n >['output']\n}\n\n/**\n * Type guard to check if an object conforms to the Standard Schema V1 specification\n *\n * @param obj - The object to check\n * @returns True if the object is a valid Standard Schema V1 implementation\n *\n * @example\n * ```ts\n * if (isStandardSchema(schema)) {\n * // Use the schema with type safety\n * const result = schema['~standard'].validate(data);\n * }\n * ```\n */\nexport function 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 typeof obj['~standard'].version === 'number' &&\n 'vendor' in obj['~standard'] &&\n typeof obj['~standard'].vendor === 'string'\n )\n}\n\n/**\n * Creates an adapter for Standard Schema V1 implementations\n *\n * Converts Standard Schema validation results into a format compatible\n * with the HTTP client's schema validation system.\n *\n * @param schema - The Standard Schema V1 implementation to adapt\n * @returns Adapter object with parse method\n *\n * @example\n * ```ts\n * const zodAdapter = standardSchemaAdapter(zodUserSchema);\n * const validatedUser = zodAdapter.parse(userData);\n * ```\n */\nexport function standardSchemaAdapter<T>(schema: StandardSchemaV1<unknown, T>) {\n return {\n /**\n * Parses and validates data using the Standard Schema\n *\n * @param data - The data to validate\n * @returns The validated and typed data\n * @throws Error if validation fails\n */\n parse: (data: unknown): T => {\n const result = schema['~standard'].validate(data)\n\n if (result instanceof Promise) {\n throw new Error('Async Standard Schema validation is not supported')\n }\n\n if ('issues' in result && result.issues) {\n const errorMessages = Array.from(result.issues)\n .map(issue => issue.message)\n .join('; ')\n throw new Error(`Standard Schema validation failed: ${errorMessages}`)\n }\n\n return result.value as T\n },\n }\n}\n\n/**\n * Creates a schema validator that supports Standard Schema V1 implementations\n *\n * Provides a validator that can work with any schema library that implements\n * the Standard Schema V1 specification, enabling interoperability between\n * different validation libraries.\n *\n * @returns SchemaValidator that supports Standard Schema V1\n *\n * @example\n * ```ts\n * const validator = createStandardSchemaValidator();\n * const client = new HttpClient({ schemaValidator: validator });\n * ```\n */\nexport function createStandardSchemaValidator(): SchemaValidator {\n return {\n /**\n * Validates data against a Standard Schema V1 implementation\n *\n * @param schema - The Standard Schema V1 to validate against\n * @param data - The data to validate\n * @returns The validated and typed data\n * @throws Error if validation fails or schema is invalid\n */\n validate<T>(schema: StandardSchemaV1<unknown, T>, data: unknown): T {\n if (!isStandardSchema(schema)) {\n throw new Error(\n 'Invalid schema: Schema must implement the Standard Schema interface'\n )\n }\n\n const adapter = standardSchemaAdapter<T>(schema)\n return adapter.parse(data)\n },\n\n /**\n * Checks if an object is a valid Standard Schema V1 implementation\n *\n * @param obj - The object to check\n * @returns True if the object is a valid Standard Schema V1\n */\n isSchema(obj: unknown): boolean {\n return isStandardSchema(obj)\n },\n }\n}\n","import {\n HttpError,\n InterceptorError,\n NetworkError,\n PathParameterError,\n SchemaValidationError,\n SerializationError,\n TimeoutError,\n} from './errors'\nimport { createSchemaValidator, type SchemaValidator } from './schema'\nimport type {\n EnforcedPathParamsOptions,\n HttpClientOptions,\n HttpMethod,\n RequestContext,\n RequestInterceptor,\n RequestOptions,\n RequestParamsType,\n ResponseInterceptor,\n ResponsePromise,\n ResponseType,\n RetryOptions,\n Schema,\n TypedRequestOptions,\n} from './types'\nimport { generatePath, type HasRequiredParams, type PathParams } from './utils'\n\n/**\n * Default retry configuration for HTTP requests\n */\nconst DEFAULT_RETRY_OPTIONS: Required<RetryOptions> = {\n maxRetries: 3,\n retryDelay: 300,\n backoffFactor: 2,\n retryStatusCodes: [429, 500, 502, 503, 504],\n retryNetworkErrors: true,\n maxRetryDelay: 30000,\n shouldRetry: () => true,\n}\n\nfunction validateAndNormalizeBaseUrl(baseUrl?: string): string {\n const hasLocation =\n typeof window !== 'undefined' &&\n typeof window.location !== 'undefined' &&\n window.location.origin !== 'null'\n\n if (!baseUrl) {\n // In browser environment, default to location.origin for relative paths\n return hasLocation ? window.location.origin : ''\n }\n\n if (baseUrl.startsWith('/')) {\n // In Node.js or non-browser environments, relative paths are preserved as-is\n return hasLocation\n ? new URL(baseUrl, window.location.origin).href.replace(/\\/$/, '')\n : baseUrl.replace(/\\/$/, '')\n }\n\n try {\n new URL(baseUrl)\n } catch {\n throw new Error(\n `Invalid baseUrl: \"${baseUrl}\". Must be a valid absolute URL or relative path starting with \"/\".`\n )\n }\n\n return baseUrl.endsWith('/') ? baseUrl.slice(0, -1) : baseUrl\n}\n\n/**\n * Wraps a response promise with data extraction method\n */\nfunction wrapResponsePromise<T>(\n promise: Promise<ResponseType<T>>\n): ResponsePromise<T> {\n const wrappedPromise = promise as ResponsePromise<T>\n\n wrappedPromise.data = async () => {\n const response = await promise\n return response.data\n }\n\n return wrappedPromise\n}\n\n/**\n * A modern, type-safe HTTP client with built-in schema validation, interceptors, retry logic, and compile-time path parameter validation.\n *\n * The HttpClient provides a fluent API for making HTTP requests with full TypeScript support,\n * automatic retry logic, request/response interceptors, and schema validation using popular\n * validation libraries like Zod, Valibot, and Arktype.\n *\n * @example\n * ```ts\n * import { HttpClient } from '1000fetches'\n * import { z } from 'zod'\n *\n * // Create a client instance\n * const client = new HttpClient({\n * baseUrl: 'https://api.example.com',\n * timeout: 5000,\n * headers: { 'Authorization': 'Bearer token' }\n * });\n *\n * const userSchema = z.object({\n * id: z.string(),\n * name: z.string(),\n * email: z.string()\n * });\n *\n * const response = await client.get('/users/:id', {\n * pathParams: { id: '123' },\n * schema: userSchema\n * });\n */\nexport class HttpClient {\n private baseUrl: string\n private defaultHeaders: Record<string, string>\n private defaultTimeout: number\n private schemaValidator: SchemaValidator\n private requestInterceptors: RequestInterceptor[]\n private responseInterceptors: ResponseInterceptor[]\n private defaultRetryOptions?: RetryOptions\n\n /**\n * Create a new HttpClient instance.\n *\n * @param options - Configuration options for the HTTP client\n *\n * @example\n * ```ts\n * // Basic configuration\n * const client = new HttpClient({\n * baseUrl: 'https://api.example.com'\n * });\n *\n * // With custom headers and timeout\n * const client = new HttpClient({\n * baseUrl: 'https://api.example.com',\n * headers: { 'Authorization': 'Bearer token' },\n * timeout: 10000\n * });\n *\n * // With custom schema validator\n * const client = new HttpClient({\n * baseUrl: 'https://api.example.com',\n * schemaValidator: createCustomValidator()\n * });\n *\n * // With retry configuration\n * const client = new HttpClient({\n * baseUrl: 'https://api.example.com',\n * retryOptions: {\n * maxRetries: 5,\n * retryDelay: 1000,\n * retryStatusCodes: [500, 502, 503]\n * }\n * });\n * ```\n */\n constructor(options: HttpClientOptions = {}) {\n this.baseUrl = validateAndNormalizeBaseUrl(options.baseUrl)\n this.defaultHeaders = options.headers ?? {}\n this.defaultTimeout = options.timeout ?? 30_000\n this.schemaValidator = options.schemaValidator || createSchemaValidator()\n this.requestInterceptors = options.requestInterceptors ?? []\n this.responseInterceptors = options.responseInterceptors ?? []\n this.defaultRetryOptions = options.retryOptions\n }\n\n /**\n * Add a request interceptor to modify requests before they're sent.\n */\n public addRequestInterceptor(interceptor: RequestInterceptor): void {\n this.requestInterceptors.push(interceptor)\n }\n\n /**\n * Add a response interceptor to process responses before they're returned.\n */\n public addResponseInterceptor(interceptor: ResponseInterceptor): void {\n this.responseInterceptors.push(interceptor)\n }\n\n /**\n * Determines if a request should be retried based on error type and retry configuration\n *\n * @param error - The error that occurred during the request\n * @param retryCount - Current retry attempt number\n * @param retryOptions - Retry configuration for this request\n * @returns Promise resolving to whether the request should be retried\n */\n private async shouldRetry(\n error: Error,\n retryCount: number,\n retryOptions: RetryOptions | boolean | undefined\n ): Promise<boolean> {\n if (retryOptions === false) return false\n\n const options = this.getRetryOptions(retryOptions)\n if (retryCount >= options.maxRetries) return false\n\n if (typeof options.shouldRetry === 'function') {\n try {\n return await options.shouldRetry(error, retryCount)\n } catch (retryError) {\n console.warn('Custom shouldRetry function failed:', retryError)\n }\n }\n\n if (error instanceof NetworkError && options.retryNetworkErrors) {\n return true\n }\n\n if (\n error instanceof HttpError &&\n options.retryStatusCodes.includes(error.status)\n ) {\n return true\n }\n\n if (error instanceof SchemaValidationError) {\n return false\n }\n\n if (error instanceof TimeoutError) {\n return true\n }\n\n return false\n }\n\n /**\n * Calculates the delay for the next retry attempt using exponential backoff with jitter\n *\n * @param retryCount - Current retry attempt number\n * @param options - Retry configuration options\n * @returns Delay in milliseconds before the next retry attempt\n */\n private getRetryDelay(\n retryCount: number,\n options: Required<RetryOptions>\n ): number {\n const baseDelay =\n options.retryDelay * Math.pow(options.backoffFactor, retryCount)\n const cappedDelay = Math.min(baseDelay, options.maxRetryDelay)\n\n // Add jitter (+-20%) to prevent thundering herd problem\n const jitterRange = cappedDelay * 0.2\n const jitter = jitterRange * (Math.random() * 2 - 1)\n const finalDelay = cappedDelay + jitter\n\n return Math.max(1, Math.floor(finalDelay))\n }\n\n /**\n * Merges provided retry options with default configuration\n */\n private getRetryOptions(\n retryOptions?: RetryOptions | boolean\n ): Required<RetryOptions> {\n if (retryOptions === false) {\n return {\n ...DEFAULT_RETRY_OPTIONS,\n maxRetries: 0,\n }\n }\n\n if (retryOptions === true) {\n return {\n ...DEFAULT_RETRY_OPTIONS,\n ...this.defaultRetryOptions,\n }\n }\n\n if (typeof retryOptions === 'object') {\n return {\n ...DEFAULT_RETRY_OPTIONS,\n ...this.defaultRetryOptions,\n ...retryOptions,\n }\n }\n\n return {\n ...DEFAULT_RETRY_OPTIONS,\n ...this.defaultRetryOptions,\n }\n }\n\n /**\n * Creates a promise that resolves after the specified delay\n */\n private sleep(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms))\n }\n\n /**\n * Makes an HTTP request with automatic retry capability\n *\n * @param method - HTTP method to use for the request\n * @param url - URL path for the request (supports path parameters)\n * @param options - Request configuration options\n * @returns Promise resolving to the response data with data extraction method\n *\n * @example\n * ```ts\n * // GET\n * const response = await client.request('GET', '/users/1');\n *\n * // POST\n * const response = await client.request('POST', '/users/:id/posts', {\n * pathParams: { id: 1 },\n * body: { title: 'New Post', content: 'Hello World' },\n * schema: userPostSchema\n * });\n *\n * // Data extraction\n * const user = await client.request('GET', '/users/1', { schema: userSchema }).data();\n * ```\n */\n public request<\n Path extends string = string,\n TResponse = unknown,\n TBody = unknown,\n TParams extends RequestParamsType = RequestParamsType,\n >(\n method: HttpMethod,\n url: Path,\n options: TypedRequestOptions<TBody, TResponse, TParams, Path> = {}\n ): ResponsePromise<TResponse> {\n return wrapResponsePromise(\n this.requestWithRetry<Path, TResponse, TBody, TParams>(\n method,\n url,\n options\n )\n )\n }\n\n /**\n * Internal method that handles retry logic for requests\n */\n private async requestWithRetry<\n Path extends string = string,\n TResponse = unknown,\n TBody = unknown,\n TParams extends RequestParamsType = RequestParamsType,\n >(\n method: HttpMethod,\n url: Path,\n options: TypedRequestOptions<TBody, TResponse, TParams, Path>\n ): Promise<ResponseType<TResponse>> {\n let retryCount = 0\n\n while (true) {\n try {\n return await this.executeRequest<Path, TResponse, TBody, TParams>(\n method,\n url,\n options\n )\n } catch (error) {\n if (!(error instanceof Error)) {\n throw new NetworkError(String(error), undefined)\n }\n\n if (await this.shouldRetry(error, retryCount, options.retry)) {\n const retryOptions = this.getRetryOptions(options.retry)\n const delay = this.getRetryDelay(retryCount, retryOptions)\n await this.sleep(delay)\n\n retryCount++\n continue\n }\n\n throw error\n }\n }\n }\n\n /**\n * Executes a single HTTP request without retry logic\n *\n * @param method - HTTP method for the request\n * @param url - URL path with optional path parameters\n * @param options - Request configuration and validation options\n * @returns Promise resolving to the response data\n */\n private async executeRequest<\n Path extends string = string,\n TResponse = unknown,\n TBody = unknown,\n TParams extends RequestParamsType = RequestParamsType,\n >(\n method: HttpMethod,\n url: Path,\n options: TypedRequestOptions<TBody, TResponse, TParams, Path> = {}\n ): Promise<ResponseType<TResponse>> {\n let resolvedUrl = this.resolveUrl(url, options.pathParams)\n\n let requestContext: RequestContext<TBody> = {\n url: resolvedUrl,\n method,\n params: options.params,\n headers: this.prepareHeaders(options.headers),\n body: options.body,\n fetchOptions: {\n credentials: options.credentials,\n cache: options.cache,\n mode: options.mode,\n redirect: options.redirect,\n },\n }\n\n for (const interceptor of this.requestInterceptors) {\n try {\n requestContext = await interceptor(requestContext)\n } catch (error) {\n throw new InterceptorError(\n `Request interceptor failed: ${error instanceof Error ? error.message : String(error)}`,\n 'request',\n resolvedUrl,\n method,\n error instanceof Error ? error : undefined\n )\n }\n }\n\n resolvedUrl = requestContext.url\n\n if (\n requestContext.params &&\n Object.keys(requestContext.params).length > 0\n ) {\n const searchParams = new URLSearchParams()\n for (const [key, value] of Object.entries(requestContext.params)) {\n if (value !== undefined) {\n searchParams.append(key, String(value))\n }\n }\n const queryString = searchParams.toString()\n if (queryString) {\n resolvedUrl += (resolvedUrl.includes('?') ? '&' : '?') + queryString\n }\n }\n\n const requestInit: RequestInit = {\n method: requestContext.method,\n headers: requestContext.headers,\n ...requestContext.fetchOptions,\n }\n\n if (\n requestContext.body !== undefined &&\n (requestContext.method === 'POST' ||\n requestContext.method === 'PUT' ||\n requestContext.method === 'PATCH')\n ) {\n if (\n requestContext.body instanceof FormData ||\n requestContext.body instanceof Blob ||\n requestContext.body instanceof ArrayBuffer ||\n requestContext.body instanceof URLSearchParams ||\n typeof requestContext.body === 'string'\n ) {\n requestInit.body = requestContext.body as BodyInit\n } else {\n try {\n requestInit.body = JSON.stringify(requestContext.body)\n } catch (error) {\n throw new SerializationError(\n `Failed to serialize request body: ${error instanceof Error ? error.message : 'Invalid data structure'}`,\n error instanceof Error ? error : undefined\n )\n }\n }\n }\n\n const timeoutDuration = options.timeout || this.defaultTimeout\n const controller = new AbortController()\n const timeoutId = setTimeout(() => controller.abort(), timeoutDuration)\n\n const requestSignal = requestContext.signal || options.signal\n let cleanupSignals: VoidFunction | undefined\n const signal = requestSignal\n ? (() => {\n const result = this.mergeAbortSignals(\n requestSignal,\n controller.signal\n )\n cleanupSignals = result.cleanup\n return result.signal\n })()\n : controller.signal\n\n try {\n const response = await fetch(resolvedUrl, {\n ...requestInit,\n signal,\n })\n\n let responseData = await this.processResponse<TResponse>(\n response,\n options,\n method,\n resolvedUrl\n )\n\n if (options.schema) {\n responseData.data = this.validateWithSchema<TResponse>(\n options.schema,\n responseData.data\n )\n }\n\n return responseData\n } catch (error) {\n if (\n (error instanceof DOMException && error.name === 'AbortError') ||\n (error instanceof Error && error.name === 'AbortError') ||\n (error instanceof Error &&\n error.message.toLowerCase().includes('timeout'))\n ) {\n throw new TimeoutError(\n `Request timed out after ${timeoutDuration}ms`,\n error instanceof Error ? error : undefined\n )\n }\n\n if (\n error instanceof HttpError ||\n error instanceof SchemaValidationError ||\n error instanceof InterceptorError ||\n error instanceof PathParameterError ||\n error instanceof SerializationError\n ) {\n throw error\n }\n\n throw new NetworkError(\n error instanceof Error ? error.message : String(error),\n error instanceof Error ? error : undefined\n )\n } finally {\n clearTimeout(timeoutId)\n cleanupSignals?.()\n }\n }\n\n private validateWithSchema<T>(\n schema: Schema<T>,\n data: unknown,\n errorPrefix = 'Response schema validation failed'\n ): T {\n try {\n return this.schemaValidator.validate(schema, data)\n } catch (error) {\n throw new SchemaValidationError(\n `${errorPrefix}: ${error instanceof Error ? error.message : 'Unknown error'}`,\n schema,\n data,\n error instanceof Error ? error : undefined\n )\n }\n }\n\n /**\n * Prepares headers for HTTP requests by merging default and custom headers\n *\n * @param customHeaders - Additional headers to include in the request\n * @returns Headers object with all headers properly set\n */\n private prepareHeaders(customHeaders: Record<string, string> = {}): Headers {\n const headers = new Headers()\n\n for (const [key, value] of Object.entries(this.defaultHeaders)) {\n if (value != null) {\n headers.set(key, String(value))\n }\n }\n\n for (const [key, value] of Object.entries(customHeaders)) {\n if (value != null) {\n headers.set(key, String(value))\n }\n }\n\n return headers\n }\n\n /**\n * Extracts headers from Headers object into a plain record\n *\n * @param headers - Headers object to extract from\n * @returns Record containing header key-value pairs\n */\n private extractHeaders(headers: Headers): Record<string, string> {\n const result: Record<string, string> = {}\n headers.forEach((value, key) => {\n result[key] = value\n })\n return result\n }\n\n /**\n * Creates an HttpError instance with response details\n *\n * @param response - The HTTP response that caused the error\n * @param data - Response data (if any)\n * @param url - The URL that was requested\n * @param method - The HTTP method used\n * @param customStatusText - Optional custom status text\n * @param cause - Optional underlying error that caused this HTTP error\n * @returns HttpError instance with complete error information\n */\n private createHttpError(\n response: globalThis.Response,\n data: unknown,\n url: string,\n method: string,\n customStatusText?: string,\n cause?: Error\n ): HttpError {\n return new HttpError(\n `Request failed with status code ${response.status}`,\n response.status,\n customStatusText || response.statusText,\n data,\n response,\n url,\n method,\n cause\n )\n }\n\n private async parseResponseBody(\n response: globalThis.Response,\n options: RequestOptions\n ): Promise<unknown> {\n const contentType = response.headers.get('content-type') ?? ''\n\n try {\n if (options.responseType === 'text') {\n return await response.text()\n } else if (options.responseType === 'blob') {\n return await response.blob()\n } else if (options.responseType === 'arrayBuffer') {\n return await response.arrayBuffer()\n } else if (contentType.includes('application/json')) {\n const text = await response.text()\n if (!text) {\n return null\n }\n return JSON.parse(text)\n } else {\n return await response.text()\n }\n } catch (e) {\n if (response.status === 204) {\n return undefined\n }\n\n if (\n contentType.includes('application/json') &&\n e instanceof SyntaxError\n ) {\n throw new Error(`Failed to parse JSON response: ${e.message}`)\n }\n\n throw e\n }\n }\n\n private async processResponse<T, TBody = unknown>(\n response: globalThis.Response,\n options: TypedRequestOptions<TBody, T>,\n method: HttpMethod,\n url: string\n ): Promise<ResponseType<T>> {\n const headers = this.extractHeaders(response.headers)\n\n const validateStatus =\n options.validateStatus ||\n ((status: number) => status >= 200 && status < 300)\n\n const data = await this.parseResponseBody(response, options)\n\n if (!validateStatus(response.status)) {\n throw this.createHttpError(response, data, url, method)\n }\n\n const responseObj: ResponseType<unknown> = {\n data,\n status: response.status,\n statusText: response.statusText,\n headers,\n method,\n url,\n raw: response,\n }\n\n let processedResponse = responseObj\n const originalStatus = responseObj.status\n\n for (const interceptor of this.responseInterceptors) {\n try {\n processedResponse = await interceptor(processedResponse)\n } catch (error) {\n throw new InterceptorError(\n `Response interceptor failed: ${error instanceof Error ? error.message : String(error)}`,\n 'response',\n url,\n method,\n error instanceof Error ? error : undefined\n )\n }\n }\n\n // Only re-validate if interceptors changed the status\n if (\n processedResponse.status !== originalStatus &&\n !validateStatus(processedResponse.status)\n ) {\n throw this.createHttpError(\n response,\n processedResponse.data,\n url,\n method,\n processedResponse.statusText\n )\n }\n\n return processedResponse as ResponseType<T>\n }\n\n private mergeAbortSignals(\n signal1: AbortSignal,\n signal2: AbortSignal\n ): { signal: AbortSignal; cleanup?: VoidFunction } {\n if (signal1.aborted || signal2.aborted) {\n const controller = new AbortController()\n controller.abort()\n return { signal: controller.signal }\n }\n\n const controller = new AbortController()\n\n const abortHandler = () => {\n controller.abort()\n cleanup()\n }\n\n const cleanup = () => {\n signal1.removeEventListener('abort', abortHandler)\n signal2.removeEventListener('abort', abortHandler)\n }\n\n signal1.addEventListener('abort', abortHandler)\n signal2.addEventListener('abort', abortHandler)\n\n return { signal: controller.signal, cleanup }\n }\n\n /**\n * Send a GET request with schema validation (type inferred from schema).\n *\n * @example\n * // Get full response\n * const response = await client.get('/users/:id', {\n * pathParams: { id: '123' },\n * schema: z.object({ id: z.string(), name: z.string() })\n * })\n *\n * @example\n * // Extract data directly\n * const user = await client.get('/users/:id', {\n * pathParams: { id: '123' },\n * schema: userSchema\n * }).data()\n */\n public get<\n TResponse,\n Path extends string = string,\n TParams extends RequestParamsType = RequestParamsType,\n >(\n url: Path,\n options: EnforcedPathParamsOptions<void, TResponse, TParams, Path> & {\n schema: Schema<TResponse>\n }\n ): ResponsePromise<TResponse>\n\n /**\n * Send a GET request without schema (response.data is unknown).\n *\n * @example\n * const response = await client.get('/users')\n *\n * @example\n * const data = await client.get('/users').data()\n */\n public get<\n Path extends string,\n TParams extends RequestParamsType = RequestParamsType,\n >(\n url: Path,\n ...args: HasRequiredParams<Path> extends true\n ? [\n options: Omit<\n EnforcedPathParamsOptions<void, unknown, TParams, Path>,\n 'schema'\n >,\n ]\n : [\n options?: Omit<\n EnforcedPathParamsOptions<void, unknown, TParams, Path>,\n 'schema'\n >,\n ]\n ): ResponsePromise<unknown>\n\n public get<\n TResponse,\n Path extends string = string,\n TParams extends RequestParamsType = RequestParamsType,\n >(\n url: Path,\n options?: EnforcedPathParamsOptions<void, TResponse, TParams, Path>\n ): ResponsePromise<TResponse | unknown> {\n return this.request<Path, TResponse, void, TParams>(\n 'GET',\n url,\n options || {}\n )\n }\n\n /**\n * Send a POST request with schema validation (type inferred from schema).\n *\n * @example\n * const response = await client.post('/users', userData, {\n * schema: z.object({ id: z.string(), name: z.string() })\n * })\n *\n * @example\n * const user = await client.post('/users', userData, { schema: userSchema }).data()\n */\n public post<\n TResponse,\n Path extends string = string,\n TParams extends RequestParamsType = RequestParamsType,\n TBody = unknown,\n >(\n url: Path,\n body: TBody | undefined,\n options: Omit<\n EnforcedPathParamsOptions<TBody, TResponse, TParams, Path>,\n 'body'\n > & { schema: Schema<TResponse> }\n ): ResponsePromise<TResponse>\n\n /**\n * Send a POST request without schema (response.data is unknown).\n *\n * @example\n * const response = await client.post('/users', userData)\n *\n * @example\n * const data = await client.post('/users', userData).data()\n */\n public post<\n Path extends string,\n TParams extends RequestParamsType = RequestParamsType,\n TBody = unknown,\n >(\n url: Path,\n ...args: HasRequiredParams<Path> extends true\n ?\n | [\n body: TBody,\n options: Omit<\n EnforcedPathParamsOptions<TBody, unknown, TParams, Path>,\n 'body' | 'schema'\n >,\n ]\n | [\n body: undefined,\n options: Omit<\n EnforcedPathParamsOptions<TBody, unknown, TParams, Path>,\n 'body' | 'schema'\n >,\n ]\n : [\n body?: TBody,\n options?: Omit<\n EnforcedPathParamsOptions<TBody, unknown, TParams, Path>,\n 'body' | 'schema'\n >,\n ]\n ): ResponsePromise<unknown>\n\n public post<\n TResponse,\n Path extends string = string,\n TParams extends RequestParamsType = RequestParamsType,\n TBody = unknown,\n >(\n url: Path,\n body?: TBody,\n options?: Omit<\n EnforcedPathParamsOptions<TBody, TResponse, TParams, Path>,\n 'body'\n >\n ): ResponsePromise<TResponse | unknown> {\n return this.request<Path, TResponse, TBody, TParams>('POST', url, {\n ...(options || {}),\n body,\n })\n }\n\n /**\n * Send a PUT request with schema validation (type inferred from schema).\n *\n * @example\n * const response = await client.put('/users/:id', updatedData, {\n * pathParams: { id: '123' },\n * schema: z.object({ id: z.string(), name: z.string() })\n * })\n *\n * @example\n * const user = await client.put('/users/:id', updatedData, {\n * pathParams: { id: '123' },\n * schema: userSchema\n * }).data()\n */\n public put<\n TResponse,\n Path extends string = string,\n TParams extends RequestParamsType = RequestParamsType,\n TBody = unknown,\n >(\n url: Path,\n body: TBody | undefined,\n options: Omit<\n EnforcedPathParamsOptions<TBody, TResponse, TParams, Path>,\n 'body'\n > & { schema: Schema<TResponse> }\n ): ResponsePromise<TResponse>\n\n /**\n * Send a PUT request without schema (response.data is unknown).\n *\n * @example\n * const response = await client.put('/users/:id', updatedData, {\n * pathParams: { id: '123' }\n * })\n *\n * @example\n * const data = await client.put('/users/:id', updatedData, {\n * pathParams: { id: '123' }\n * }).data()\n */\n public put<\n Path extends string,\n TParams extends RequestParamsType = RequestParamsType,\n TBody = unknown,\n >(\n url: Path,\n ...args: HasRequiredParams<Path> extends true\n ?\n | [\n body: TBody,\n options: Omit<\n EnforcedPathParamsOptions<TBody, unknown, TParams, Path>,\n 'body' | 'schema'\n >,\n ]\n | [\n body: undefined,\n options: Omit<\n EnforcedPathParamsOptions<TBody, unknown, TParams, Path>,\n 'body' | 'schema'\n >,\n ]\n : [\n body?: TBody,\n options?: Omit<\n EnforcedPathParamsOptions<TBody, unknown, TParams, Path>,\n 'body' | 'schema'\n >,\n ]\n ): ResponsePromise<unknown>\n\n public put<\n TResponse,\n Path extends string = string,\n TParams extends RequestParamsType = RequestParamsType,\n TBody = unknown,\n >(\n url: Path,\n body?: TBody,\n options?: Omit<\n EnforcedPathParamsOptions<TBody, TResponse, TParams, Path>,\n 'body'\n >\n ): ResponsePromise<TResponse | unknown> {\n return this.request<Path, TResponse, TBody, TParams>('PUT', url, {\n ...(options || {}),\n body,\n })\n }\n\n /**\n * Send a PATCH request with schema validation (type inferred from schema).\n *\n * @example\n * const response = await client.patch('/users/:id', partialData, {\n * pathParams: { id: '123' },\n * schema: z.object({ id: z.string(), name: z.string() })\n * })\n *\n * @example\n * const user = await client.patch('/users/:id', partialData, {\n * pathParams: { id: '123' },\n * schema: userSchema\n * }).data()\n */\n public patch<\n TResponse,\n Path extends string = string,\n TParams extends RequestParamsType = RequestParamsType,\n TBody = unknown,\n >(\n url: Path,\n body: TBody | undefined,\n options: Omit<\n EnforcedPathParamsOptions<TBody, TResponse, TParams, Path>,\n 'body'\n > & { schema: Schema<TResponse> }\n ): ResponsePromise<TResponse>\n\n /**\n * Send a PATCH request without schema (response.data is unknown).\n *\n * @example\n * const response = await client.patch('/users/:id', partialData, {\n * pathParams: { id: '123' }\n * })\n *\n * @example\n * const data = await client.patch('/users/:id', partialData, {\n * pathParams: { id: '123' }\n * }).data()\n */\n public patch<\n Path extends string,\n TParams extends RequestParamsType = RequestParamsType,\n TBody = unknown,\n >(\n url: Path,\n ...args: HasRequiredParams<Path> extends true\n ?\n | [\n body: TBody,\n options: Omit<\n EnforcedPathParamsOptions<TBody, unknown, TParams, Path>,\n 'body' | 'schema'\n >,\n ]\n | [\n body: undefined,\n options: Omit<\n EnforcedPathParamsOptions<TBody, unknown, TParams, Path>,\n 'body' | 'schema'\n >,\n ]\n : [\n body?: TBody,\n options?: Omit<\n EnforcedPathParamsOptions<TBody, unknown, TParams, Path>,\n 'body' | 'schema'\n >,\n ]\n ): ResponsePromise<unknown>\n\n public patch<\n TResponse,\n Path extends string = string,\n TParams extends RequestParamsType = RequestParamsType,\n TBody = unknown,\n >(\n url: Path,\n body?: TBody,\n options?: Omit<\n EnforcedPathParamsOptions<TBody, TResponse, TParams, Path>,\n 'body'\n >\n ): ResponsePromise<TResponse | unknown> {\n return this.request<Path, TResponse, TBody, TParams>('PATCH', url, {\n ...(options || {}),\n body,\n })\n }\n\n /**\n * Send a DELETE request with schema validation (type inferred from schema).\n *\n * @example\n * const response = await client.delete('/users/:id', {\n * pathParams: { id: '123' },\n * schema: z.object({ success: z.boolean() })\n * })\n *\n * @example\n * const result = await client.delete('/users/:id', {\n * pathParams: { id: '123' },\n * schema: deleteResultSchema\n * }).data()\n */\n public delete<\n TResponse,\n Path extends string = string,\n TParams extends RequestParamsType = RequestParamsType,\n >(\n url: Path,\n options: EnforcedPathParamsOptions<void, TResponse, TParams, Path> & {\n schema: Schema<TResponse>\n }\n ): ResponsePromise<TResponse>\n\n /**\n * Send a DELETE request without schema (response.data is unknown).\n *\n * @example\n * const response = await client.delete('/users/:id', {\n * pathParams: { id: '123' }\n * })\n *\n * @example\n * const data = await client.delete('/users/:id', {\n * pathParams: { id: '123' }\n * }).data()\n */\n public delete<\n Path extends string,\n TParams extends RequestParamsType = RequestParamsType,\n >(\n url: Path,\n ...args: HasRequiredParams<Path> extends true\n ? [\n options: Omit<\n EnforcedPathParamsOptions<void, unknown, TParams, Path>,\n 'schema'\n >,\n ]\n : [\n options?: Omit<\n EnforcedPathParamsOptions<void, unknown, TParams, Path>,\n 'schema'\n >,\n ]\n ): ResponsePromise<unknown>\n\n public delete<\n TResponse,\n Path extends string = string,\n TParams extends RequestParamsType = RequestParamsType,\n >(\n url: Path,\n options?: EnforcedPathParamsOptions<void, TResponse, TParams, Path>\n ): ResponsePromise<TResponse | unknown> {\n return this.request<Path, TResponse, void, TParams>(\n 'DELETE',\n url,\n options || {}\n )\n }\n\n /**\n * Validates path parameters against the URL template\n *\n * @param url - URL template with path parameters (e.g., '/users/:id')\n * @param pathParams - Path parameters to validate\n * @throws Error if required path parameters are missing or invalid\n */\n private validatePathParams<Path extends string>(\n url: Path,\n pathParams?: PathParams<Path>\n ): void {\n if (!pathParams) {\n const requiredParams = this.extractRequiredPathParams(url)\n\n if (requiredParams.length > 0) {\n throw new PathParameterError(\n `Missing required path parameters for URL \"${url}\": ${requiredParams.join(', ')}. ` +\n `Please provide pathParams: { ${requiredParams.map(p => `${p}: value`).join(', ')} }`,\n url,\n requiredParams,\n []\n )\n }\n return\n }\n\n const requiredParams = this.extractRequiredPathParams(url)\n const providedParams = Object.keys(pathParams)\n\n const missingParams = requiredParams.filter(\n param => !providedParams.includes(param)\n )\n if (missingParams.length > 0) {\n throw new PathParameterError(\n `Missing required path parameters: ${missingParams.join(', ')}. ` +\n `Provided: ${providedParams.join(', ')}`,\n url,\n requiredParams,\n providedParams\n )\n }\n\n // const unusedParams = providedParams.filter(\n // param => !requiredParams.includes(param)\n // )\n // if (unusedParams.length > 0) {\n // console.warn(\n // `Unused path parameters provided: ${unusedParams.join(', ')}. ` +\n // `URL \"${url}\" does not contain these parameters.`\n // )\n // }\n }\n\n /**\n * Extracts required path parameters from a URL template\n *\n * @param url - URL template to extract parameters from\n * @returns Array of required parameter names\n */\n private extractRequiredPathParams(url: string): string[] {\n if (!url) {\n return []\n }\n\n const pathOnly = url.split('?').at(0)?.split('#').at(0)\n\n if (!pathOnly?.includes(':')) {\n return []\n }\n\n const matches = pathOnly.match(/:([a-zA-Z0-9_]+)/g)\n return matches ? matches.map(match => match.slice(1)) : []\n }\n\n /**\n * Resolves a URL template with path parameters and base URL\n *\n * @param url - URL template with optional path parameters\n * @param pathParams - Path parameters to interpolate into the URL\n * @returns Fully resolved URL with base URL and path parameters applied\n */\n private resolveUrl<Path extends string>(\n url: Path,\n pathParams?: PathParams<Path>\n ): string {\n this.validatePathParams(url, pathParams)\n\n const interpolatedUrl = pathParams ? generatePath(url, pathParams) : url\n\n if (/^https?:\\/\\//i.test(interpolatedUrl)) {\n return interpolatedUrl\n }\n\n const path = interpolatedUrl.startsWith('/')\n ? interpolatedUrl.slice(1)\n : interpolatedUrl\n\n return `${this.baseUrl}/${path}`\n }\n}\n","import {\n createStandardSchemaValidator as createStdSchemaValidator,\n isStandardSchema,\n} from './standard-schema'\n\nimport { Schema } from './types'\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\n * @throws {SchemaValidationError} If the data doesn't match the schema\n */\n validate<T>(schema: Schema<T>, data: unknown): T\n\n /**\n * Check if an object is a valid schema.\n *\n * @param obj - The object to check\n * @returns True if the object is a valid schema, false otherwise\n */\n isSchema(obj: unknown): boolean\n}\n\n/**\n * Create a default schema validator that supports Standard Schema.\n *\n * This validator only works with schemas that implement the Standard Schema\n * interface. For full support of Zod, Valibot, and Arktype, use the\n * appropriate validator from their respective packages.\n *\n * @returns A schema validator instance\n *\n * @example\n * ```ts\n * import { createSchemaValidator } from '1000fetches'\n *\n * const validator = createSchemaValidator();\n *\n * // Use with HttpClient\n * const client = new HttpClient({\n * schemaValidator: validator\n * });\n * ```\n */\nexport function createSchemaValidator(): SchemaValidator {\n return {\n validate<T>(schema: Schema<T>, data: unknown): T {\n if (!isStandardSchema(schema)) {\n throw new Error(\n 'Invalid schema: Schema must implement the Standard Schema interface'\n )\n }\n\n return createStdSchemaValidator().validate(schema, data)\n },\n\n isSchema(obj: unknown): boolean {\n return isStandardSchema(obj)\n },\n }\n}\n\nexport { createStdSchemaValidator as createStandardSchemaValidator }\n","import { PathParameterError } from '../errors'\n\n/**\n * Strips protocol from URL (e.g., https://, http://)\n */\ntype StripProtocol<T extends string> = T extends `${string}://${infer After}`\n ? After\n : T\n\n/**\n * Strips host and optional port from URL, keeping only the path\n * Handles cases like \"localhost:3000/users\" -> \"/users\"\n */\ntype StripHost<T extends string> = T extends `${infer _Host}/${infer Path}`\n ? `/${Path}`\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 `${string}=${string}` | `${string}=${string}&${string}` | `${string}&${string}`\n ? Path // contains = or &\n : Query extends `/${string}`\n ? T // it's another path segment\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<StripHost<StripProtocol<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 all path parameters from a route\n */\ntype ExtractRouteParams<T extends string> =\n NormalizePath<T> extends `${infer _Before}:${infer AfterColon}`\n ? AfterColon extends `${infer Param}/${infer Rest}`\n ? CleanParamName<`:${Param}`> | ExtractRouteParams<`/${Rest}`>\n : CleanParamName<`:${AfterColon}`>\n : never\n\nexport type HasRequiredParams<T extends string> = [ExtractRouteParams<T>] extends [never]\n ? false\n : true\n\n/**\n * PathParams type - extracts parameter names and their types\n */\nexport type PathParams<Path extends string> = {\n [K in ExtractRouteParams<Path>]: string | number\n}\n\n/**\n * RequirePathParams enforces pathParams when needed\n */\nexport type RequirePathParams<Path extends string, T> =\n HasRequiredParams<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: Path,\n params: PathParams<Path> = {} as PathParams<Path>\n): string {\n return path.replace(/:([a-zA-Z0-9_]+)/g, (_match, paramName: string) => {\n if (params[paramName as keyof PathParams<Path>] === undefined) {\n throw new PathParameterError(\n `Missing required path parameter: ${paramName}`,\n path,\n [paramName],\n Object.keys(params)\n )\n }\n return String(params[paramName as keyof PathParams<Path>])\n })\n}\n"],"names":["HttpError","Error","name","status","statusText","data","response","url","method","cause","constructor","message","super","this","NetworkError","SchemaValidationError","schema","TimeoutError","PathParameterError","requiredParams","providedParams","InterceptorError","interceptorType","SerializationError","isStandardSchema","obj","validate","version","vendor","createStandardSchemaValidator","adapter","parse","result","Promise","issues","errorMessages","Array","from","map","issue","join","value","standardSchemaAdapter","isSchema","DEFAULT_RETRY_OPTIONS","maxRetries","retryDelay","backoffFactor","retryStatusCodes","retryNetworkErrors","maxRetryDelay","shouldRetry","baseUrl","defaultHeaders","defaultTimeout","schemaValidator","requestInterceptors","responseInterceptors","defaultRetryOptions","options","hasLocation","window","location","origin","startsWith","URL","href","replace","endsWith","slice","validateAndNormalizeBaseUrl","headers","timeout","createStdSchemaValidator","retryOptions","addRequestInterceptor","interceptor","push","addResponseInterceptor","error","retryCount","getRetryOptions","retryError","console","warn","includes","getRetryDelay","baseDelay","Math","pow","cappedDelay","min","finalDelay","random","max","floor","sleep","ms","resolve","setTimeout","request","promise","wrappedPromise","async","wrapResponsePromise","requestWithRetry","executeRequest","String","retry","delay","resolvedUrl","resolveUrl","pathParams","requestContext","params","prepareHeaders","body","fetchOptions","credentials","cache","mode","redirect","Object","keys","length","searchParams","URLSearchParams","key","entries","append","queryString","toString","requestInit","FormData","Blob","ArrayBuffer","JSON","stringify","timeoutDuration","controller","AbortController","timeoutId","abort","requestSignal","signal","cleanupSignals","mergeAbortSignals","cleanup","fetch","responseData","processResponse","validateWithSchema","DOMException","toLowerCase","clearTimeout","errorPrefix","customHeaders","Headers","set","extractHeaders","forEach","createHttpError","customStatusText","parseResponseBody","contentType","get","responseType","text","blob","arrayBuffer","e","SyntaxError","validateStatus","responseObj","raw","processedResponse","originalStatus","signal1","signal2","aborted","abortHandler","removeEventListener","addEventListener","post","put","patch","validatePathParams","extractRequiredPathParams","p","missingParams","filter","param","pathOnly","split","at","matches","match","interpolatedUrl","path","_match","paramName","generatePath","test"],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1,8 +1,7 @@
1
1
  /**
2
- * Removes optional suffix from param name (e.g., "id?" -> "id")
3
- * This makes optional params work seamlessly as required params
2
+ * Removes optional suffix from param name (e.g., ":id?" -> "id", ":id" -> "id")
4
3
  */
5
- declare type CleanParamName<S extends string> = S extends `${infer Name}?` ? Name : S;
4
+ declare type CleanParamName<S extends string> = S extends `:${infer Name}?` ? Name : S extends `:${infer Name}` ? Name : S;
6
5
 
7
6
  /**
8
7
  * TypedRequestOptions with enforced pathParams when the URL contains path parameters.
@@ -12,13 +11,10 @@ declare type EnforcedPathParamsOptions<TBody = unknown, TResponse = unknown, TPa
12
11
 
13
12
  /**
14
13
  * Extracts all path parameters from a route
15
- * Optional params like :id? are treated as required params (id)
16
14
  */
17
- declare type ExtractRouteParams<T extends string> = NormalizePath<T> extends `${infer _Before}:${infer AfterColon}` ? AfterColon extends `${infer Param}/${infer Rest}` ? CleanParamName<Param> | ExtractRouteParams<`/${Rest}`> : CleanParamName<AfterColon> : never;
15
+ declare type ExtractRouteParams<T extends string> = NormalizePath<T> extends `${infer _Before}:${infer AfterColon}` ? AfterColon extends `${infer Param}/${infer Rest}` ? CleanParamName<`:${Param}`> | ExtractRouteParams<`/${Rest}`> : CleanParamName<`:${AfterColon}`> : never;
18
16
 
19
- declare type HasRequiredParams<T extends string> = [
20
- ExtractRouteParams<T>
21
- ] extends [never] ? false : true;
17
+ declare type HasRequiredParams<T extends string> = [ExtractRouteParams<T>] extends [never] ? false : true;
22
18
 
23
19
  /**
24
20
  * A modern, type-safe HTTP client with built-in schema validation, interceptors, retry logic, and compile-time path parameter validation.
@@ -97,72 +93,10 @@ export declare class HttpClient {
97
93
  constructor(options?: HttpClientOptions);
98
94
  /**
99
95
  * Add a request interceptor to modify requests before they're sent.
100
- *
101
- * Request interceptors are executed in the order they were added and can modify
102
- * the request context before it's sent to the server. This is useful for adding
103
- * authentication headers, logging, or transforming request data.
104
- *
105
- * @param interceptor - The interceptor function to add
106
- *
107
- * @example
108
- * ```ts
109
- * // Add authentication headers to all requests
110
- * client.addRequestInterceptor((context) => {
111
- * context.headers.set('Authorization', `Bearer ${getToken()}`);
112
- * return context;
113
- * });
114
- *
115
- * // Change the base URL for specific endpoints
116
- * client.addRequestInterceptor((context) => {
117
- * if (context.url.includes('/special/')) {
118
- * context.url = context.url.replace('api.example.com', 'special-api.example.com');
119
- * }
120
- * return context;
121
- * });
122
- *
123
- * // Log all outgoing requests
124
- * client.addRequestInterceptor((context) => {
125
- * console.log(`Making ${context.method} request to ${context.url}`);
126
- * return context;
127
- * });
128
- * ```
129
96
  */
130
97
  addRequestInterceptor(interceptor: RequestInterceptor): void;
131
98
  /**
132
99
  * Add a response interceptor to process responses before they're returned.
133
- *
134
- * Response interceptors are executed in the order they were added and can modify
135
- * the response data before it's returned to the caller. This is useful for
136
- * transforming data, logging responses, or handling global error conditions.
137
- *
138
- * @param interceptor - The interceptor function to add
139
- *
140
- * @example
141
- * ```ts
142
- * // Log all responses
143
- * client.addResponseInterceptor((response) => {
144
- * console.log(`Response from ${response.raw.url}: ${response.status}`);
145
- * return response;
146
- * });
147
- *
148
- * // Transform response data
149
- * client.addResponseInterceptor((response) => {
150
- * if (Array.isArray(response.data)) {
151
- * response.data = response.data.map(item => transformItem(item));
152
- * }
153
- * return response;
154
- * });
155
- *
156
- * // Handle 401 responses by refreshing the token and retrying
157
- * client.addResponseInterceptor(async (response) => {
158
- * if (response.status === 401) {
159
- * await refreshToken();
160
- * // Make a new request (will use updated token)
161
- * return await client.request(response.raw.method, response.raw.url);
162
- * }
163
- * return response;
164
- * });
165
- * ```
166
100
  */
167
101
  addResponseInterceptor(interceptor: ResponseInterceptor): void;
168
102
  /**
@@ -184,16 +118,10 @@ export declare class HttpClient {
184
118
  private getRetryDelay;
185
119
  /**
186
120
  * Merges provided retry options with default configuration
187
- *
188
- * @param retryOptions - Retry options to merge with defaults
189
- * @returns Complete retry configuration with all required properties
190
121
  */
191
122
  private getRetryOptions;
192
123
  /**
193
124
  * Creates a promise that resolves after the specified delay
194
- *
195
- * @param ms - Delay duration in milliseconds
196
- * @returns Promise that resolves after the delay
197
125
  */
198
126
  private sleep;
199
127
  /**
@@ -206,10 +134,10 @@ export declare class HttpClient {
206
134
  *
207
135
  * @example
208
136
  * ```ts
209
- * // Simple GET request
137
+ * // GET
210
138
  * const response = await client.request('GET', '/users/1');
211
139
  *
212
- * // POST request with body and path parameters
140
+ * // POST
213
141
  * const response = await client.request('POST', '/users/:id/posts', {
214
142
  * pathParams: { id: 1 },
215
143
  * body: { title: 'New Post', content: 'Hello World' },
@@ -586,7 +514,6 @@ declare type RequestParamsType = Record<string, string | number | boolean | unde
586
514
 
587
515
  /**
588
516
  * RequirePathParams enforces pathParams when needed
589
- * Optional params are seamlessly treated as required params
590
517
  */
591
518
  declare type RequirePathParams<Path extends string, T> = HasRequiredParams<Path> extends true ? T & {
592
519
  pathParams: PathParams<Path>;
@@ -697,16 +624,10 @@ declare interface StandardSchemaV1<Input = unknown, Output = Input> {
697
624
 
698
625
  /**
699
626
  * Namespace containing Standard Schema V1 type definitions
700
- *
701
- * Provides type-safe interfaces for schema validation results,
702
- * error handling, and type inference.
703
627
  */
704
628
  declare namespace StandardSchemaV1 {
705
629
  /**
706
630
  * Core properties interface for Standard Schema V1
707
- *
708
- * Contains the essential metadata and validation function
709
- * that every Standard Schema implementation must provide.
710
631
  */
711
632
  interface Props<Input = unknown, Output = Input> {
712
633
  /** The version number of the Standard Schema specification */
@@ -725,43 +646,29 @@ declare namespace StandardSchemaV1 {
725
646
  }
726
647
  /**
727
648
  * Union type representing the result of schema validation
728
- *
729
- * Can be either a successful validation with the validated value,
730
- * or a failed validation with error details.
731
649
  */
732
650
  type Result<Output> = SuccessResult<Output> | FailureResult;
733
651
  /**
734
652
  * Interface for successful validation results
735
- *
736
- * Contains the validated and typed output value.
737
653
  */
738
654
  interface SuccessResult<Output> {
739
- /** The validated and typed output value */
740
655
  readonly value: Output;
741
- /** Undefined since validation succeeded */
742
656
  readonly issues?: undefined;
743
657
  }
744
658
  /**
745
659
  * Interface for failed validation results
746
- *
747
- * Contains detailed error information about validation failures.
748
660
  */
749
661
  interface FailureResult {
750
- /** Array of validation error details */
751
662
  readonly issues: ReadonlyArray<Issue>;
752
663
  }
753
664
  /**
754
665
  * Interface for individual validation error details
755
- *
756
- * Provides error message and optional path information
757
- * to help identify where validation failed.
758
666
  */
759
667
  interface Issue {
760
668
  /** Human-readable error message describing the validation failure */
761
669
  readonly message: string;
762
670
  /**
763
671
  * Path to the property that failed validation
764
- *
765
672
  * Useful for nested object validation to pinpoint the exact location
766
673
  * of validation failures.
767
674
  */
@@ -769,46 +676,23 @@ declare namespace StandardSchemaV1 {
769
676
  }
770
677
  /**
771
678
  * Interface for path segment information in validation errors
772
- *
773
- * Used to provide detailed path information for validation failures
774
- * in complex nested structures.
775
679
  */
776
680
  interface PathSegment {
777
- /** The property key representing this path segment */
778
681
  readonly key: PropertyKey;
779
682
  }
780
683
  /**
781
684
  * Interface for type information associated with a schema
782
- *
783
- * Provides compile-time type information for input and output types
784
- * to enable better TypeScript integration and IntelliSense support.
785
685
  */
786
686
  interface Types<Input = unknown, Output = Input> {
787
- /** The input type that the schema expects */
788
687
  readonly input: Input;
789
- /** The output type that the schema produces after validation */
790
688
  readonly output: Output;
791
689
  }
792
690
  /**
793
691
  * Type utility to infer the input type from a Standard Schema
794
- *
795
- * Extracts the input type that a schema expects for validation.
796
- *
797
- * @example
798
- * ```ts
799
- * type UserInput = StandardSchemaV1.InferInput<typeof userSchema>
800
- * ```
801
692
  */
802
693
  type InferInput<Schema extends StandardSchemaV1> = NonNullable<Schema['~standard']['types']>['input'];
803
694
  /**
804
695
  * Type utility to infer the output type from a Standard Schema
805
- *
806
- * Extracts the output type that a schema produces after validation.
807
- *
808
- * @example
809
- * ```ts
810
- * type UserOutput = StandardSchemaV1.InferOutput<typeof userSchema>
811
- * ```
812
696
  */
813
697
  type InferOutput<Schema extends StandardSchemaV1> = NonNullable<Schema['~standard']['types']>['output'];
814
698
  }
@@ -828,7 +712,7 @@ declare type StripProtocol<T extends string> = T extends `${string}://${infer Af
828
712
  * Strips query string from path (e.g., "/users?x=1" -> "/users")
829
713
  * Only strips ? that comes after the path, not ? that's part of path parameters
830
714
  */
831
- declare type StripQuery<T extends string> = T extends `${infer Path}?${infer Query}` ? Query extends `${string}=${string}` | `${string}=${string}&${string}` ? Path : T : T;
715
+ declare type StripQuery<T extends string> = T extends `${infer Path}?${infer Query}` ? Query extends `${string}=${string}` | `${string}=${string}&${string}` | `${string}&${string}` ? Path : Query extends `/${string}` ? T : Query extends `` ? T : Path : T;
832
716
 
833
717
  export declare class TimeoutError extends Error implements HttpClientError {
834
718
  readonly name = "TimeoutError";
package/dist/index.es.js CHANGED
@@ -239,83 +239,21 @@ class HttpClient {
239
239
  */
240
240
  constructor(options = {}) {
241
241
  this.baseUrl = validateAndNormalizeBaseUrl(options.baseUrl);
242
- this.defaultHeaders = options.headers || {};
243
- this.defaultTimeout = options.timeout || 3e4;
242
+ this.defaultHeaders = options.headers ?? {};
243
+ this.defaultTimeout = options.timeout ?? 3e4;
244
244
  this.schemaValidator = options.schemaValidator || createSchemaValidator();
245
- this.requestInterceptors = options.requestInterceptors || [];
246
- this.responseInterceptors = options.responseInterceptors || [];
245
+ this.requestInterceptors = options.requestInterceptors ?? [];
246
+ this.responseInterceptors = options.responseInterceptors ?? [];
247
247
  this.defaultRetryOptions = options.retryOptions;
248
248
  }
249
249
  /**
250
250
  * Add a request interceptor to modify requests before they're sent.
251
- *
252
- * Request interceptors are executed in the order they were added and can modify
253
- * the request context before it's sent to the server. This is useful for adding
254
- * authentication headers, logging, or transforming request data.
255
- *
256
- * @param interceptor - The interceptor function to add
257
- *
258
- * @example
259
- * ```ts
260
- * // Add authentication headers to all requests
261
- * client.addRequestInterceptor((context) => {
262
- * context.headers.set('Authorization', `Bearer ${getToken()}`);
263
- * return context;
264
- * });
265
- *
266
- * // Change the base URL for specific endpoints
267
- * client.addRequestInterceptor((context) => {
268
- * if (context.url.includes('/special/')) {
269
- * context.url = context.url.replace('api.example.com', 'special-api.example.com');
270
- * }
271
- * return context;
272
- * });
273
- *
274
- * // Log all outgoing requests
275
- * client.addRequestInterceptor((context) => {
276
- * console.log(`Making ${context.method} request to ${context.url}`);
277
- * return context;
278
- * });
279
- * ```
280
251
  */
281
252
  addRequestInterceptor(interceptor) {
282
253
  this.requestInterceptors.push(interceptor);
283
254
  }
284
255
  /**
285
256
  * Add a response interceptor to process responses before they're returned.
286
- *
287
- * Response interceptors are executed in the order they were added and can modify
288
- * the response data before it's returned to the caller. This is useful for
289
- * transforming data, logging responses, or handling global error conditions.
290
- *
291
- * @param interceptor - The interceptor function to add
292
- *
293
- * @example
294
- * ```ts
295
- * // Log all responses
296
- * client.addResponseInterceptor((response) => {
297
- * console.log(`Response from ${response.raw.url}: ${response.status}`);
298
- * return response;
299
- * });
300
- *
301
- * // Transform response data
302
- * client.addResponseInterceptor((response) => {
303
- * if (Array.isArray(response.data)) {
304
- * response.data = response.data.map(item => transformItem(item));
305
- * }
306
- * return response;
307
- * });
308
- *
309
- * // Handle 401 responses by refreshing the token and retrying
310
- * client.addResponseInterceptor(async (response) => {
311
- * if (response.status === 401) {
312
- * await refreshToken();
313
- * // Make a new request (will use updated token)
314
- * return await client.request(response.raw.method, response.raw.url);
315
- * }
316
- * return response;
317
- * });
318
- * ```
319
257
  */
320
258
  addResponseInterceptor(interceptor) {
321
259
  this.responseInterceptors.push(interceptor);
@@ -370,9 +308,6 @@ class HttpClient {
370
308
  }
371
309
  /**
372
310
  * Merges provided retry options with default configuration
373
- *
374
- * @param retryOptions - Retry options to merge with defaults
375
- * @returns Complete retry configuration with all required properties
376
311
  */
377
312
  getRetryOptions(retryOptions) {
378
313
  if (retryOptions === false) {
@@ -401,9 +336,6 @@ class HttpClient {
401
336
  }
402
337
  /**
403
338
  * Creates a promise that resolves after the specified delay
404
- *
405
- * @param ms - Delay duration in milliseconds
406
- * @returns Promise that resolves after the delay
407
339
  */
408
340
  sleep(ms) {
409
341
  return new Promise((resolve) => setTimeout(resolve, ms));
@@ -418,10 +350,10 @@ class HttpClient {
418
350
  *
419
351
  * @example
420
352
  * ```ts
421
- * // Simple GET request
353
+ * // GET
422
354
  * const response = await client.request('GET', '/users/1');
423
355
  *
424
- * // POST request with body and path parameters
356
+ * // POST
425
357
  * const response = await client.request('POST', '/users/:id/posts', {
426
358
  * pathParams: { id: 1 },
427
359
  * body: { title: 'New Post', content: 'Hello World' },
@@ -816,15 +748,14 @@ class HttpClient {
816
748
  * @returns Array of required parameter names
817
749
  */
818
750
  extractRequiredPathParams(url) {
819
- if (url.includes("?")) {
820
- throw new PathParameterError(
821
- "Optional path parameters (e.g., :variable?) are not supported",
822
- url,
823
- [],
824
- []
825
- );
751
+ if (!url) {
752
+ return [];
753
+ }
754
+ const pathOnly = url.split("?").at(0)?.split("#").at(0);
755
+ if (!pathOnly?.includes(":")) {
756
+ return [];
826
757
  }
827
- const matches = url.match(/:([a-zA-Z0-9_]+)/g);
758
+ const matches = pathOnly.match(/:([a-zA-Z0-9_]+)/g);
828
759
  return matches ? matches.map((match) => match.slice(1)) : [];
829
760
  }
830
761
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"index.es.js","sources":["../src/errors.ts","../src/standard-schema.ts","../src/schema.ts","../src/utils/path.ts","../src/client.ts"],"sourcesContent":["interface HttpClientError {\n name: string\n message: string\n cause?: Error\n stack?: string\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 enhancedMessage = `HTTP ${status} ${statusText}: ${message} (${method} ${url})`\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 }\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 }\n}\n\nexport class SchemaValidationError extends Error implements HttpClientError {\n public readonly name = 'SchemaValidationError'\n public readonly schema: unknown\n public readonly data: unknown\n public override readonly cause?: Error\n\n constructor(message: string, schema: unknown, data: unknown, cause?: Error) {\n super(message, { cause })\n this.schema = schema\n this.data = data\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 }\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 super(message, { cause })\n this.url = url\n this.requiredParams = requiredParams\n this.providedParams = providedParams\n }\n}\n\nexport class InterceptorError extends Error implements HttpClientError {\n public readonly name = 'InterceptorError'\n public readonly interceptorType: '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 interceptorType: 'request' | 'response',\n url?: string,\n method?: string,\n cause?: Error\n ) {\n super(message, { cause })\n this.interceptorType = interceptorType\n this.url = url\n this.method = method\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 }\n}\n","import { SchemaValidator } from './schema'\n\n/**\n * Standard Schema V1 interface implementation\n *\n * This interface defines the structure for schema validation libraries\n * that conform to the Standard Schema specification.\n *\n * @see https://github.com/standard-schema/standard-schema\n */\nexport interface StandardSchemaV1<Input = unknown, Output = Input> {\n /** The Standard Schema properties containing validation logic and metadata */\n readonly '~standard': StandardSchemaV1.Props<Input, Output>\n}\n\n/**\n * Namespace containing Standard Schema V1 type definitions\n *\n * Provides type-safe interfaces for schema validation results,\n * error handling, and type inference.\n */\nexport namespace StandardSchemaV1 {\n /**\n * Core properties interface for Standard Schema V1\n *\n * Contains the essential metadata and validation function\n * that every Standard Schema implementation must provide.\n */\n export interface Props<Input = unknown, Output = Input> {\n /** The version number of the Standard Schema specification */\n readonly version: 1\n /** The name of the schema validation library (e.g., 'zod', 'valibot') */\n readonly vendor: string\n /**\n * Validates unknown input values against the schema\n *\n * @param value - The value to validate\n * @returns Promise or direct result containing validation outcome\n */\n readonly validate: (\n value: unknown\n ) => Result<Output> | Promise<Result<Output>>\n /** Type information for input and output types */\n readonly types?: Types<Input, Output> | undefined\n }\n\n /**\n * Union type representing the result of schema validation\n *\n * Can be either a successful validation with the validated value,\n * or a failed validation with error details.\n */\n export type Result<Output> = SuccessResult<Output> | FailureResult\n\n /**\n * Interface for successful validation results\n *\n * Contains the validated and typed output value.\n */\n export interface SuccessResult<Output> {\n /** The validated and typed output value */\n readonly value: Output\n /** Undefined since validation succeeded */\n readonly issues?: undefined\n }\n\n /**\n * Interface for failed validation results\n *\n * Contains detailed error information about validation failures.\n */\n export interface FailureResult {\n /** Array of validation error details */\n readonly issues: ReadonlyArray<Issue>\n }\n\n /**\n * Interface for individual validation error details\n *\n * Provides error message and optional path information\n * to help identify where validation failed.\n */\n export interface Issue {\n /** Human-readable error message describing the validation failure */\n readonly message: string\n /**\n * Path to the property that failed validation\n *\n * Useful for nested object validation to pinpoint the exact location\n * of validation failures.\n */\n readonly path?: ReadonlyArray<PropertyKey | PathSegment> | undefined\n }\n\n /**\n * Interface for path segment information in validation errors\n *\n * Used to provide detailed path information for validation failures\n * in complex nested structures.\n */\n export interface PathSegment {\n /** The property key representing this path segment */\n readonly key: PropertyKey\n }\n\n /**\n * Interface for type information associated with a schema\n *\n * Provides compile-time type information for input and output types\n * to enable better TypeScript integration and IntelliSense support.\n */\n export interface Types<Input = unknown, Output = Input> {\n /** The input type that the schema expects */\n readonly input: Input\n /** The output type that the schema produces after validation */\n readonly output: Output\n }\n\n /**\n * Type utility to infer the input type from a Standard Schema\n *\n * Extracts the input type that a schema expects for validation.\n *\n * @example\n * ```ts\n * type UserInput = StandardSchemaV1.InferInput<typeof userSchema>\n * ```\n */\n export type InferInput<Schema extends StandardSchemaV1> = NonNullable<\n Schema['~standard']['types']\n >['input']\n\n /**\n * Type utility to infer the output type from a Standard Schema\n *\n * Extracts the output type that a schema produces after validation.\n *\n * @example\n * ```ts\n * type UserOutput = StandardSchemaV1.InferOutput<typeof userSchema>\n * ```\n */\n export type InferOutput<Schema extends StandardSchemaV1> = NonNullable<\n Schema['~standard']['types']\n >['output']\n}\n\n/**\n * Type guard to check if an object conforms to the Standard Schema V1 specification\n *\n * Validates that an object has the required structure and properties\n * to be considered a valid Standard Schema implementation.\n *\n * @param obj - The object to check\n * @returns True if the object is a valid Standard Schema V1 implementation\n *\n * @example\n * ```ts\n * if (isStandardSchema(schema)) {\n * // Use the schema with type safety\n * const result = schema['~standard'].validate(data);\n * }\n * ```\n */\nexport function 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 typeof obj['~standard'].version === 'number' &&\n 'vendor' in obj['~standard'] &&\n typeof obj['~standard'].vendor === 'string'\n )\n}\n\n/**\n * Creates an adapter for Standard Schema V1 implementations\n *\n * Converts Standard Schema validation results into a format compatible\n * with the HTTP client's schema validation system.\n *\n * @param schema - The Standard Schema V1 implementation to adapt\n * @returns Adapter object with parse method\n *\n * @example\n * ```ts\n * const zodAdapter = standardSchemaAdapter(zodUserSchema);\n * const validatedUser = zodAdapter.parse(userData);\n * ```\n */\nexport function standardSchemaAdapter<T>(schema: StandardSchemaV1<unknown, T>) {\n return {\n /**\n * Parses and validates data using the Standard Schema\n *\n * @param data - The data to validate\n * @returns The validated and typed data\n * @throws Error if validation fails\n */\n parse: (data: unknown): T => {\n const result = schema['~standard'].validate(data)\n\n if (result instanceof Promise) {\n throw new Error('Async Standard Schema validation is not supported')\n }\n\n if ('issues' in result && result.issues) {\n const errorMessages = Array.from(result.issues)\n .map(issue => issue.message)\n .join('; ')\n throw new Error(`Standard Schema validation failed: ${errorMessages}`)\n }\n\n return result.value as T\n },\n }\n}\n\n/**\n * Creates a schema validator that supports Standard Schema V1 implementations\n *\n * Provides a validator that can work with any schema library that implements\n * the Standard Schema V1 specification, enabling interoperability between\n * different validation libraries.\n *\n * @returns SchemaValidator that supports Standard Schema V1\n *\n * @example\n * ```ts\n * const validator = createStandardSchemaValidator();\n * const client = new HttpClient({ schemaValidator: validator });\n * ```\n */\nexport function createStandardSchemaValidator(): SchemaValidator {\n return {\n /**\n * Validates data against a Standard Schema V1 implementation\n *\n * @param schema - The Standard Schema V1 to validate against\n * @param data - The data to validate\n * @returns The validated and typed data\n * @throws Error if validation fails or schema is invalid\n */\n validate<T>(schema: StandardSchemaV1<unknown, T>, data: unknown): T {\n if (!isStandardSchema(schema)) {\n throw new Error(\n 'Invalid schema: Schema must implement the Standard Schema interface'\n )\n }\n\n const adapter = standardSchemaAdapter<T>(schema)\n return adapter.parse(data)\n },\n\n /**\n * Checks if an object is a valid Standard Schema V1 implementation\n *\n * @param obj - The object to check\n * @returns True if the object is a valid Standard Schema V1\n */\n isSchema(obj: unknown): boolean {\n return isStandardSchema(obj)\n },\n }\n}\n","import {\n createStandardSchemaValidator as createStdSchemaValidator,\n isStandardSchema,\n} from './standard-schema'\n\nimport { Schema } from './types'\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\n * @throws {SchemaValidationError} If the data doesn't match the schema\n */\n validate<T>(schema: Schema<T>, data: unknown): T\n\n /**\n * Check if an object is a valid schema.\n *\n * @param obj - The object to check\n * @returns True if the object is a valid schema, false otherwise\n */\n isSchema(obj: unknown): boolean\n}\n\n/**\n * Create a default schema validator that supports Standard Schema.\n *\n * This validator only works with schemas that implement the Standard Schema\n * interface. For full support of Zod, Valibot, and Arktype, use the\n * appropriate validator from their respective packages.\n *\n * @returns A schema validator instance\n *\n * @example\n * ```ts\n * import { createSchemaValidator } from '1000fetches'\n *\n * const validator = createSchemaValidator();\n *\n * // Use with HttpClient\n * const client = new HttpClient({\n * schemaValidator: validator\n * });\n * ```\n */\nexport function createSchemaValidator(): SchemaValidator {\n return {\n validate<T>(schema: Schema<T>, data: unknown): T {\n if (!isStandardSchema(schema)) {\n throw new Error(\n 'Invalid schema: Schema must implement the Standard Schema interface'\n )\n }\n\n return createStdSchemaValidator().validate(schema, data)\n },\n\n isSchema(obj: unknown): boolean {\n return isStandardSchema(obj)\n },\n }\n}\n\nexport { createStdSchemaValidator as createStandardSchemaValidator }\n","import { PathParameterError } from '../errors'\n\n/**\n * Strips protocol from URL (e.g., https://, http://)\n */\ntype StripProtocol<T extends string> = T extends `${string}://${infer After}`\n ? After\n : T\n\n/**\n * Strips host and optional port from URL, keeping only the path\n * Handles cases like \"localhost:3000/users\" -> \"/users\"\n */\ntype StripHost<T extends string> = T extends `${infer _Host}/${infer Path}`\n ? `/${Path}`\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 `${string}=${string}` | `${string}=${string}&${string}`\n ? Path // Only strip if it looks like a query string (key=value)\n : T // Don't strip if it's part of a path parameter\n : T\n\n/**\n * Normalizes URL to path only, stripping protocol, host, port, and query\n */\ntype NormalizePath<T extends string> = StripQuery<StripHost<StripProtocol<T>>>\n\n/**\n * Removes optional suffix from param name (e.g., \"id?\" -> \"id\")\n * This makes optional params work seamlessly as required params\n */\ntype CleanParamName<S extends string> = S extends `${infer Name}?` ? Name : S\n\n/**\n * Extracts all path parameters from a route\n * Optional params like :id? are treated as required params (id)\n */\ntype ExtractRouteParams<T extends string> =\n NormalizePath<T> extends `${infer _Before}:${infer AfterColon}`\n ? AfterColon extends `${infer Param}/${infer Rest}`\n ? CleanParamName<Param> | ExtractRouteParams<`/${Rest}`>\n : CleanParamName<AfterColon>\n : never\n\nexport type HasRequiredParams<T extends string> = [\n ExtractRouteParams<T>,\n] extends [never]\n ? false\n : true\n\n/**\n * PathParams type - extracts parameter names and their types\n */\nexport type PathParams<Path extends string> = {\n [K in ExtractRouteParams<Path>]: string | number\n}\n\n/**\n * RequirePathParams enforces pathParams when needed\n * Optional params are seamlessly treated as required params\n */\nexport type RequirePathParams<Path extends string, T> =\n HasRequiredParams<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: Path,\n params: PathParams<Path> = {} as PathParams<Path>\n): string {\n return path.replace(/:([a-zA-Z0-9_]+)/g, (_match, paramName: string) => {\n if (params[paramName as keyof PathParams<Path>] === undefined) {\n throw new PathParameterError(\n `Missing required path parameter: ${paramName}`,\n path,\n [paramName],\n Object.keys(params)\n )\n }\n return String(params[paramName as keyof PathParams<Path>])\n })\n}\n","import {\n HttpError,\n InterceptorError,\n NetworkError,\n PathParameterError,\n SchemaValidationError,\n SerializationError,\n TimeoutError,\n} from './errors'\nimport { createSchemaValidator, type SchemaValidator } from './schema'\nimport type {\n EnforcedPathParamsOptions,\n HttpClientOptions,\n HttpMethod,\n RequestContext,\n RequestInterceptor,\n RequestOptions,\n RequestParamsType,\n ResponseInterceptor,\n ResponsePromise,\n ResponseType,\n RetryOptions,\n Schema,\n TypedRequestOptions,\n} from './types'\nimport { generatePath, type HasRequiredParams, type PathParams } from './utils'\n\n/**\n * Default retry configuration for HTTP requests\n */\nconst DEFAULT_RETRY_OPTIONS: Required<RetryOptions> = {\n maxRetries: 3,\n retryDelay: 300,\n backoffFactor: 2,\n retryStatusCodes: [429, 500, 502, 503, 504],\n retryNetworkErrors: true,\n maxRetryDelay: 30000,\n shouldRetry: () => true,\n}\n\nfunction validateAndNormalizeBaseUrl(baseUrl?: string): string {\n const hasLocation =\n typeof window !== 'undefined' &&\n typeof window.location !== 'undefined' &&\n window.location.origin !== 'null'\n\n if (!baseUrl) {\n // In browser environment, default to location.origin for relative paths\n return hasLocation ? window.location.origin : ''\n }\n\n // Allow relative paths like \"/api\" - they'll be resolved against location.origin or need absolute URLs in Node\n if (baseUrl.startsWith('/')) {\n // In Node.js or non-browser environments, relative paths are preserved as-is\n return hasLocation\n ? new URL(baseUrl, window.location.origin).href.replace(/\\/$/, '')\n : baseUrl.replace(/\\/$/, '')\n }\n\n try {\n new URL(baseUrl)\n } catch {\n throw new Error(\n `Invalid baseUrl: \"${baseUrl}\". Must be a valid absolute URL or relative path starting with \"/\".`\n )\n }\n\n return baseUrl.endsWith('/') ? baseUrl.slice(0, -1) : baseUrl\n}\n\n/**\n * Wraps a response promise with data extraction method\n * @param promise - The base response promise\n * @returns Promise with data method attached\n */\nfunction wrapResponsePromise<T>(\n promise: Promise<ResponseType<T>>\n): ResponsePromise<T> {\n const wrappedPromise = promise as ResponsePromise<T>\n\n wrappedPromise.data = async () => {\n const response = await promise\n return response.data\n }\n\n return wrappedPromise\n}\n\n/**\n * A modern, type-safe HTTP client with built-in schema validation, interceptors, retry logic, and compile-time path parameter validation.\n *\n * The HttpClient provides a fluent API for making HTTP requests with full TypeScript support,\n * automatic retry logic, request/response interceptors, and schema validation using popular\n * validation libraries like Zod, Valibot, and Arktype.\n *\n * @example\n * ```ts\n * import { HttpClient } from '1000fetches'\n * import { z } from 'zod'\n *\n * // Create a client instance\n * const client = new HttpClient({\n * baseUrl: 'https://api.example.com',\n * timeout: 5000,\n * headers: { 'Authorization': 'Bearer token' }\n * });\n *\n * const userSchema = z.object({\n * id: z.string(),\n * name: z.string(),\n * email: z.string()\n * });\n *\n * const response = await client.get('/users/:id', {\n * pathParams: { id: '123' },\n * schema: userSchema\n * });\n */\nexport class HttpClient {\n private baseUrl: string\n private defaultHeaders: Record<string, string>\n private defaultTimeout: number\n private schemaValidator: SchemaValidator\n private requestInterceptors: RequestInterceptor[]\n private responseInterceptors: ResponseInterceptor[]\n private defaultRetryOptions?: RetryOptions\n\n /**\n * Create a new HttpClient instance.\n *\n * @param options - Configuration options for the HTTP client\n *\n * @example\n * ```ts\n * // Basic configuration\n * const client = new HttpClient({\n * baseUrl: 'https://api.example.com'\n * });\n *\n * // With custom headers and timeout\n * const client = new HttpClient({\n * baseUrl: 'https://api.example.com',\n * headers: { 'Authorization': 'Bearer token' },\n * timeout: 10000\n * });\n *\n * // With custom schema validator\n * const client = new HttpClient({\n * baseUrl: 'https://api.example.com',\n * schemaValidator: createCustomValidator()\n * });\n *\n * // With retry configuration\n * const client = new HttpClient({\n * baseUrl: 'https://api.example.com',\n * retryOptions: {\n * maxRetries: 5,\n * retryDelay: 1000,\n * retryStatusCodes: [500, 502, 503]\n * }\n * });\n * ```\n */\n constructor(options: HttpClientOptions = {}) {\n this.baseUrl = validateAndNormalizeBaseUrl(options.baseUrl)\n this.defaultHeaders = options.headers || {}\n this.defaultTimeout = options.timeout || 30000 // 30 seconds default\n this.schemaValidator = options.schemaValidator || createSchemaValidator()\n this.requestInterceptors = options.requestInterceptors || []\n this.responseInterceptors = options.responseInterceptors || []\n this.defaultRetryOptions = options.retryOptions\n }\n\n /**\n * Add a request interceptor to modify requests before they're sent.\n *\n * Request interceptors are executed in the order they were added and can modify\n * the request context before it's sent to the server. This is useful for adding\n * authentication headers, logging, or transforming request data.\n *\n * @param interceptor - The interceptor function to add\n *\n * @example\n * ```ts\n * // Add authentication headers to all requests\n * client.addRequestInterceptor((context) => {\n * context.headers.set('Authorization', `Bearer ${getToken()}`);\n * return context;\n * });\n *\n * // Change the base URL for specific endpoints\n * client.addRequestInterceptor((context) => {\n * if (context.url.includes('/special/')) {\n * context.url = context.url.replace('api.example.com', 'special-api.example.com');\n * }\n * return context;\n * });\n *\n * // Log all outgoing requests\n * client.addRequestInterceptor((context) => {\n * console.log(`Making ${context.method} request to ${context.url}`);\n * return context;\n * });\n * ```\n */\n public addRequestInterceptor(interceptor: RequestInterceptor): void {\n this.requestInterceptors.push(interceptor)\n }\n\n /**\n * Add a response interceptor to process responses before they're returned.\n *\n * Response interceptors are executed in the order they were added and can modify\n * the response data before it's returned to the caller. This is useful for\n * transforming data, logging responses, or handling global error conditions.\n *\n * @param interceptor - The interceptor function to add\n *\n * @example\n * ```ts\n * // Log all responses\n * client.addResponseInterceptor((response) => {\n * console.log(`Response from ${response.raw.url}: ${response.status}`);\n * return response;\n * });\n *\n * // Transform response data\n * client.addResponseInterceptor((response) => {\n * if (Array.isArray(response.data)) {\n * response.data = response.data.map(item => transformItem(item));\n * }\n * return response;\n * });\n *\n * // Handle 401 responses by refreshing the token and retrying\n * client.addResponseInterceptor(async (response) => {\n * if (response.status === 401) {\n * await refreshToken();\n * // Make a new request (will use updated token)\n * return await client.request(response.raw.method, response.raw.url);\n * }\n * return response;\n * });\n * ```\n */\n public addResponseInterceptor(interceptor: ResponseInterceptor): void {\n this.responseInterceptors.push(interceptor)\n }\n\n /**\n * Determines if a request should be retried based on error type and retry configuration\n *\n * @param error - The error that occurred during the request\n * @param retryCount - Current retry attempt number\n * @param retryOptions - Retry configuration for this request\n * @returns Promise resolving to whether the request should be retried\n */\n private async shouldRetry(\n error: Error,\n retryCount: number,\n retryOptions: RetryOptions | boolean | undefined\n ): Promise<boolean> {\n if (retryOptions === false) return false\n\n const options = this.getRetryOptions(retryOptions)\n if (retryCount >= options.maxRetries) return false\n\n if (typeof options.shouldRetry === 'function') {\n try {\n return await options.shouldRetry(error, retryCount)\n } catch (retryError) {\n console.warn('Custom shouldRetry function failed:', retryError)\n }\n }\n\n if (error instanceof NetworkError && options.retryNetworkErrors) {\n return true\n }\n\n if (\n error instanceof HttpError &&\n options.retryStatusCodes.includes(error.status)\n ) {\n return true\n }\n\n if (error instanceof SchemaValidationError) {\n return false\n }\n\n if (error instanceof TimeoutError) {\n return true\n }\n\n return false\n }\n\n /**\n * Calculates the delay for the next retry attempt using exponential backoff with jitter\n *\n * @param retryCount - Current retry attempt number\n * @param options - Retry configuration options\n * @returns Delay in milliseconds before the next retry attempt\n */\n private getRetryDelay(\n retryCount: number,\n options: Required<RetryOptions>\n ): number {\n const baseDelay =\n options.retryDelay * Math.pow(options.backoffFactor, retryCount)\n const cappedDelay = Math.min(baseDelay, options.maxRetryDelay)\n\n // Add jitter (+-20%) to prevent thundering herd problem\n const jitterRange = cappedDelay * 0.2\n const jitter = jitterRange * (Math.random() * 2 - 1)\n const finalDelay = cappedDelay + jitter\n\n return Math.max(1, Math.floor(finalDelay))\n }\n\n /**\n * Merges provided retry options with default configuration\n *\n * @param retryOptions - Retry options to merge with defaults\n * @returns Complete retry configuration with all required properties\n */\n private getRetryOptions(\n retryOptions?: RetryOptions | boolean\n ): Required<RetryOptions> {\n if (retryOptions === false) {\n return {\n ...DEFAULT_RETRY_OPTIONS,\n maxRetries: 0,\n }\n }\n\n if (retryOptions === true) {\n return {\n ...DEFAULT_RETRY_OPTIONS,\n ...this.defaultRetryOptions,\n }\n }\n\n if (typeof retryOptions === 'object') {\n return {\n ...DEFAULT_RETRY_OPTIONS,\n ...this.defaultRetryOptions,\n ...retryOptions,\n }\n }\n\n return {\n ...DEFAULT_RETRY_OPTIONS,\n ...this.defaultRetryOptions,\n }\n }\n\n /**\n * Creates a promise that resolves after the specified delay\n *\n * @param ms - Delay duration in milliseconds\n * @returns Promise that resolves after the delay\n */\n private sleep(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms))\n }\n\n /**\n * Makes an HTTP request with automatic retry capability\n *\n * @param method - HTTP method to use for the request\n * @param url - URL path for the request (supports path parameters)\n * @param options - Request configuration options\n * @returns Promise resolving to the response data with data extraction method\n *\n * @example\n * ```ts\n * // Simple GET request\n * const response = await client.request('GET', '/users/1');\n *\n * // POST request with body and path parameters\n * const response = await client.request('POST', '/users/:id/posts', {\n * pathParams: { id: 1 },\n * body: { title: 'New Post', content: 'Hello World' },\n * schema: userPostSchema\n * });\n *\n * // Data extraction\n * const user = await client.request('GET', '/users/1', { schema: userSchema }).data();\n * ```\n */\n public request<\n Path extends string = string,\n TResponse = unknown,\n TBody = unknown,\n TParams extends RequestParamsType = RequestParamsType,\n >(\n method: HttpMethod,\n url: Path,\n options: TypedRequestOptions<TBody, TResponse, TParams, Path> = {}\n ): ResponsePromise<TResponse> {\n return wrapResponsePromise(\n this.requestWithRetry<Path, TResponse, TBody, TParams>(\n method,\n url,\n options\n )\n )\n }\n\n /**\n * Internal method that handles retry logic for requests\n */\n private async requestWithRetry<\n Path extends string = string,\n TResponse = unknown,\n TBody = unknown,\n TParams extends RequestParamsType = RequestParamsType,\n >(\n method: HttpMethod,\n url: Path,\n options: TypedRequestOptions<TBody, TResponse, TParams, Path>\n ): Promise<ResponseType<TResponse>> {\n let retryCount = 0\n\n while (true) {\n try {\n return await this.executeRequest<Path, TResponse, TBody, TParams>(\n method,\n url,\n options\n )\n } catch (error) {\n if (!(error instanceof Error)) {\n throw new NetworkError(String(error), undefined)\n }\n\n if (await this.shouldRetry(error, retryCount, options.retry)) {\n const retryOptions = this.getRetryOptions(options.retry)\n const delay = this.getRetryDelay(retryCount, retryOptions)\n await this.sleep(delay)\n\n retryCount++\n continue\n }\n\n throw error\n }\n }\n }\n\n /**\n * Executes a single HTTP request without retry logic\n *\n * @param method - HTTP method for the request\n * @param url - URL path with optional path parameters\n * @param options - Request configuration and validation options\n * @returns Promise resolving to the response data\n */\n private async executeRequest<\n Path extends string = string,\n TResponse = unknown,\n TBody = unknown,\n TParams extends RequestParamsType = RequestParamsType,\n >(\n method: HttpMethod,\n url: Path,\n options: TypedRequestOptions<TBody, TResponse, TParams, Path> = {}\n ): Promise<ResponseType<TResponse>> {\n let resolvedUrl = this.resolveUrl(url, options.pathParams)\n\n let requestContext: RequestContext<TBody> = {\n url: resolvedUrl,\n method,\n params: options.params,\n headers: this.prepareHeaders(options.headers),\n body: options.body,\n fetchOptions: {\n credentials: options.credentials,\n cache: options.cache,\n mode: options.mode,\n redirect: options.redirect,\n },\n }\n\n for (const interceptor of this.requestInterceptors) {\n try {\n requestContext = await interceptor(requestContext)\n } catch (error) {\n throw new InterceptorError(\n `Request interceptor failed: ${error instanceof Error ? error.message : String(error)}`,\n 'request',\n resolvedUrl,\n method,\n error instanceof Error ? error : undefined\n )\n }\n }\n\n resolvedUrl = requestContext.url\n\n if (\n requestContext.params &&\n Object.keys(requestContext.params).length > 0\n ) {\n const searchParams = new URLSearchParams()\n for (const [key, value] of Object.entries(requestContext.params)) {\n if (value !== undefined) {\n searchParams.append(key, String(value))\n }\n }\n const queryString = searchParams.toString()\n if (queryString) {\n resolvedUrl += (resolvedUrl.includes('?') ? '&' : '?') + queryString\n }\n }\n\n const requestInit: RequestInit = {\n method: requestContext.method,\n headers: requestContext.headers,\n ...requestContext.fetchOptions,\n }\n\n if (\n requestContext.body !== undefined &&\n (requestContext.method === 'POST' ||\n requestContext.method === 'PUT' ||\n requestContext.method === 'PATCH')\n ) {\n if (\n requestContext.body instanceof FormData ||\n requestContext.body instanceof Blob ||\n requestContext.body instanceof ArrayBuffer ||\n requestContext.body instanceof URLSearchParams ||\n typeof requestContext.body === 'string'\n ) {\n requestInit.body = requestContext.body as BodyInit\n } else {\n try {\n requestInit.body = JSON.stringify(requestContext.body)\n } catch (error) {\n throw new SerializationError(\n `Failed to serialize request body: ${error instanceof Error ? error.message : 'Invalid data structure'}`,\n error instanceof Error ? error : undefined\n )\n }\n }\n }\n\n const timeoutDuration = options.timeout || this.defaultTimeout\n const controller = new AbortController()\n const timeoutId = setTimeout(() => controller.abort(), timeoutDuration)\n\n const requestSignal = requestContext.signal || options.signal\n let cleanupSignals: VoidFunction | undefined\n const signal = requestSignal\n ? (() => {\n const result = this.mergeAbortSignals(\n requestSignal,\n controller.signal\n )\n cleanupSignals = result.cleanup\n return result.signal\n })()\n : controller.signal\n\n try {\n const response = await fetch(resolvedUrl, {\n ...requestInit,\n signal,\n })\n\n let responseData = await this.processResponse<TResponse>(\n response,\n options,\n method,\n resolvedUrl\n )\n\n if (options.schema) {\n responseData.data = this.validateWithSchema<TResponse>(\n options.schema,\n responseData.data\n )\n }\n\n return responseData\n } catch (error) {\n if (\n (error instanceof DOMException && error.name === 'AbortError') ||\n (error instanceof Error && error.name === 'AbortError') ||\n (error instanceof Error &&\n error.message.toLowerCase().includes('timeout'))\n ) {\n throw new TimeoutError(\n `Request timed out after ${timeoutDuration}ms`,\n error instanceof Error ? error : undefined\n )\n }\n\n if (\n error instanceof HttpError ||\n error instanceof SchemaValidationError ||\n error instanceof InterceptorError ||\n error instanceof PathParameterError ||\n error instanceof SerializationError\n ) {\n throw error\n }\n\n throw new NetworkError(\n error instanceof Error ? error.message : String(error),\n error instanceof Error ? error : undefined\n )\n } finally {\n clearTimeout(timeoutId)\n cleanupSignals?.()\n }\n }\n\n private validateWithSchema<T>(\n schema: Schema<T>,\n data: unknown,\n errorPrefix = 'Response schema validation failed'\n ): T {\n try {\n return this.schemaValidator.validate(schema, data)\n } catch (error) {\n throw new SchemaValidationError(\n `${errorPrefix}: ${error instanceof Error ? error.message : 'Unknown error'}`,\n schema,\n data,\n error instanceof Error ? error : undefined\n )\n }\n }\n\n /**\n * Prepares headers for HTTP requests by merging default and custom headers\n *\n * @param customHeaders - Additional headers to include in the request\n * @returns Headers object with all headers properly set\n */\n private prepareHeaders(customHeaders: Record<string, string> = {}): Headers {\n const headers = new Headers()\n\n for (const [key, value] of Object.entries(this.defaultHeaders)) {\n if (value != null) {\n headers.set(key, String(value))\n }\n }\n\n for (const [key, value] of Object.entries(customHeaders)) {\n if (value != null) {\n headers.set(key, String(value))\n }\n }\n\n return headers\n }\n\n /**\n * Extracts headers from Headers object into a plain record\n *\n * @param headers - Headers object to extract from\n * @returns Record containing header key-value pairs\n */\n private extractHeaders(headers: Headers): Record<string, string> {\n const result: Record<string, string> = {}\n headers.forEach((value, key) => {\n result[key] = value\n })\n return result\n }\n\n /**\n * Creates an HttpError instance with response details\n *\n * @param response - The HTTP response that caused the error\n * @param data - Response data (if any)\n * @param url - The URL that was requested\n * @param method - The HTTP method used\n * @param customStatusText - Optional custom status text\n * @param cause - Optional underlying error that caused this HTTP error\n * @returns HttpError instance with complete error information\n */\n private createHttpError(\n response: globalThis.Response,\n data: unknown,\n url: string,\n method: string,\n customStatusText?: string,\n cause?: Error\n ): HttpError {\n return new HttpError(\n `Request failed with status code ${response.status}`,\n response.status,\n customStatusText || response.statusText,\n data,\n response,\n url,\n method,\n cause\n )\n }\n\n private async parseResponseBody(\n response: globalThis.Response,\n options: RequestOptions\n ): Promise<unknown> {\n const contentType = response.headers.get('content-type') ?? ''\n\n try {\n if (options.responseType === 'text') {\n return await response.text()\n } else if (options.responseType === 'blob') {\n return await response.blob()\n } else if (options.responseType === 'arrayBuffer') {\n return await response.arrayBuffer()\n } else if (contentType.includes('application/json')) {\n const text = await response.text()\n if (!text) {\n return null\n }\n return JSON.parse(text)\n } else {\n return await response.text()\n }\n } catch (e) {\n if (response.status === 204) {\n return undefined\n }\n\n if (\n contentType.includes('application/json') &&\n e instanceof SyntaxError\n ) {\n throw new Error(`Failed to parse JSON response: ${e.message}`)\n }\n\n throw e\n }\n }\n\n private async processResponse<T, TBody = unknown>(\n response: globalThis.Response,\n options: TypedRequestOptions<TBody, T>,\n method: HttpMethod,\n url: string\n ): Promise<ResponseType<T>> {\n const headers = this.extractHeaders(response.headers)\n\n const validateStatus =\n options.validateStatus ||\n ((status: number) => status >= 200 && status < 300)\n\n const data = await this.parseResponseBody(response, options)\n\n if (!validateStatus(response.status)) {\n throw this.createHttpError(response, data, url, method)\n }\n\n const responseObj: ResponseType<unknown> = {\n data,\n status: response.status,\n statusText: response.statusText,\n headers,\n method,\n url,\n raw: response,\n }\n\n let processedResponse = responseObj\n const originalStatus = responseObj.status\n\n for (const interceptor of this.responseInterceptors) {\n try {\n processedResponse = await interceptor(processedResponse)\n } catch (error) {\n throw new InterceptorError(\n `Response interceptor failed: ${error instanceof Error ? error.message : String(error)}`,\n 'response',\n url,\n method,\n error instanceof Error ? error : undefined\n )\n }\n }\n\n // Only re-validate if interceptors changed the status\n if (\n processedResponse.status !== originalStatus &&\n !validateStatus(processedResponse.status)\n ) {\n throw this.createHttpError(\n response,\n processedResponse.data,\n url,\n method,\n processedResponse.statusText\n )\n }\n\n return processedResponse as ResponseType<T>\n }\n\n private mergeAbortSignals(\n signal1: AbortSignal,\n signal2: AbortSignal\n ): { signal: AbortSignal; cleanup?: VoidFunction } {\n if (signal1.aborted || signal2.aborted) {\n const controller = new AbortController()\n controller.abort()\n return { signal: controller.signal }\n }\n\n const controller = new AbortController()\n\n const abortHandler = () => {\n controller.abort()\n cleanup()\n }\n\n const cleanup = () => {\n signal1.removeEventListener('abort', abortHandler)\n signal2.removeEventListener('abort', abortHandler)\n }\n\n signal1.addEventListener('abort', abortHandler)\n signal2.addEventListener('abort', abortHandler)\n\n return { signal: controller.signal, cleanup }\n }\n\n /**\n * Send a GET request with schema validation (type inferred from schema).\n *\n * @example\n * // Get full response\n * const response = await client.get('/users/:id', {\n * pathParams: { id: '123' },\n * schema: z.object({ id: z.string(), name: z.string() })\n * })\n *\n * @example\n * // Extract data directly\n * const user = await client.get('/users/:id', {\n * pathParams: { id: '123' },\n * schema: userSchema\n * }).data()\n */\n public get<\n TResponse,\n Path extends string = string,\n TParams extends RequestParamsType = RequestParamsType,\n >(\n url: Path,\n options: EnforcedPathParamsOptions<void, TResponse, TParams, Path> & {\n schema: Schema<TResponse>\n }\n ): ResponsePromise<TResponse>\n\n /**\n * Send a GET request without schema (response.data is unknown).\n *\n * @example\n * const response = await client.get('/users')\n *\n * @example\n * const data = await client.get('/users').data()\n */\n public get<\n Path extends string,\n TParams extends RequestParamsType = RequestParamsType,\n >(\n url: Path,\n ...args: HasRequiredParams<Path> extends true\n ? [\n options: Omit<\n EnforcedPathParamsOptions<void, unknown, TParams, Path>,\n 'schema'\n >,\n ]\n : [\n options?: Omit<\n EnforcedPathParamsOptions<void, unknown, TParams, Path>,\n 'schema'\n >,\n ]\n ): ResponsePromise<unknown>\n\n public get<\n TResponse,\n Path extends string = string,\n TParams extends RequestParamsType = RequestParamsType,\n >(\n url: Path,\n options?: EnforcedPathParamsOptions<void, TResponse, TParams, Path>\n ): ResponsePromise<TResponse | unknown> {\n return this.request<Path, TResponse, void, TParams>(\n 'GET',\n url,\n options || {}\n )\n }\n\n /**\n * Send a POST request with schema validation (type inferred from schema).\n *\n * @example\n * const response = await client.post('/users', userData, {\n * schema: z.object({ id: z.string(), name: z.string() })\n * })\n *\n * @example\n * const user = await client.post('/users', userData, { schema: userSchema }).data()\n */\n public post<\n TResponse,\n Path extends string = string,\n TParams extends RequestParamsType = RequestParamsType,\n TBody = unknown,\n >(\n url: Path,\n body: TBody | undefined,\n options: Omit<\n EnforcedPathParamsOptions<TBody, TResponse, TParams, Path>,\n 'body'\n > & { schema: Schema<TResponse> }\n ): ResponsePromise<TResponse>\n\n /**\n * Send a POST request without schema (response.data is unknown).\n *\n * @example\n * const response = await client.post('/users', userData)\n *\n * @example\n * const data = await client.post('/users', userData).data()\n */\n public post<\n Path extends string,\n TParams extends RequestParamsType = RequestParamsType,\n TBody = unknown,\n >(\n url: Path,\n ...args: HasRequiredParams<Path> extends true\n ?\n | [\n body: TBody,\n options: Omit<\n EnforcedPathParamsOptions<TBody, unknown, TParams, Path>,\n 'body' | 'schema'\n >,\n ]\n | [\n body: undefined,\n options: Omit<\n EnforcedPathParamsOptions<TBody, unknown, TParams, Path>,\n 'body' | 'schema'\n >,\n ]\n : [\n body?: TBody,\n options?: Omit<\n EnforcedPathParamsOptions<TBody, unknown, TParams, Path>,\n 'body' | 'schema'\n >,\n ]\n ): ResponsePromise<unknown>\n\n public post<\n TResponse,\n Path extends string = string,\n TParams extends RequestParamsType = RequestParamsType,\n TBody = unknown,\n >(\n url: Path,\n body?: TBody,\n options?: Omit<\n EnforcedPathParamsOptions<TBody, TResponse, TParams, Path>,\n 'body'\n >\n ): ResponsePromise<TResponse | unknown> {\n return this.request<Path, TResponse, TBody, TParams>('POST', url, {\n ...(options || {}),\n body,\n })\n }\n\n /**\n * Send a PUT request with schema validation (type inferred from schema).\n *\n * @example\n * const response = await client.put('/users/:id', updatedData, {\n * pathParams: { id: '123' },\n * schema: z.object({ id: z.string(), name: z.string() })\n * })\n *\n * @example\n * const user = await client.put('/users/:id', updatedData, {\n * pathParams: { id: '123' },\n * schema: userSchema\n * }).data()\n */\n public put<\n TResponse,\n Path extends string = string,\n TParams extends RequestParamsType = RequestParamsType,\n TBody = unknown,\n >(\n url: Path,\n body: TBody | undefined,\n options: Omit<\n EnforcedPathParamsOptions<TBody, TResponse, TParams, Path>,\n 'body'\n > & { schema: Schema<TResponse> }\n ): ResponsePromise<TResponse>\n\n /**\n * Send a PUT request without schema (response.data is unknown).\n *\n * @example\n * const response = await client.put('/users/:id', updatedData, {\n * pathParams: { id: '123' }\n * })\n *\n * @example\n * const data = await client.put('/users/:id', updatedData, {\n * pathParams: { id: '123' }\n * }).data()\n */\n public put<\n Path extends string,\n TParams extends RequestParamsType = RequestParamsType,\n TBody = unknown,\n >(\n url: Path,\n ...args: HasRequiredParams<Path> extends true\n ?\n | [\n body: TBody,\n options: Omit<\n EnforcedPathParamsOptions<TBody, unknown, TParams, Path>,\n 'body' | 'schema'\n >,\n ]\n | [\n body: undefined,\n options: Omit<\n EnforcedPathParamsOptions<TBody, unknown, TParams, Path>,\n 'body' | 'schema'\n >,\n ]\n : [\n body?: TBody,\n options?: Omit<\n EnforcedPathParamsOptions<TBody, unknown, TParams, Path>,\n 'body' | 'schema'\n >,\n ]\n ): ResponsePromise<unknown>\n\n public put<\n TResponse,\n Path extends string = string,\n TParams extends RequestParamsType = RequestParamsType,\n TBody = unknown,\n >(\n url: Path,\n body?: TBody,\n options?: Omit<\n EnforcedPathParamsOptions<TBody, TResponse, TParams, Path>,\n 'body'\n >\n ): ResponsePromise<TResponse | unknown> {\n return this.request<Path, TResponse, TBody, TParams>('PUT', url, {\n ...(options || {}),\n body,\n })\n }\n\n /**\n * Send a PATCH request with schema validation (type inferred from schema).\n *\n * @example\n * const response = await client.patch('/users/:id', partialData, {\n * pathParams: { id: '123' },\n * schema: z.object({ id: z.string(), name: z.string() })\n * })\n *\n * @example\n * const user = await client.patch('/users/:id', partialData, {\n * pathParams: { id: '123' },\n * schema: userSchema\n * }).data()\n */\n public patch<\n TResponse,\n Path extends string = string,\n TParams extends RequestParamsType = RequestParamsType,\n TBody = unknown,\n >(\n url: Path,\n body: TBody | undefined,\n options: Omit<\n EnforcedPathParamsOptions<TBody, TResponse, TParams, Path>,\n 'body'\n > & { schema: Schema<TResponse> }\n ): ResponsePromise<TResponse>\n\n /**\n * Send a PATCH request without schema (response.data is unknown).\n *\n * @example\n * const response = await client.patch('/users/:id', partialData, {\n * pathParams: { id: '123' }\n * })\n *\n * @example\n * const data = await client.patch('/users/:id', partialData, {\n * pathParams: { id: '123' }\n * }).data()\n */\n public patch<\n Path extends string,\n TParams extends RequestParamsType = RequestParamsType,\n TBody = unknown,\n >(\n url: Path,\n ...args: HasRequiredParams<Path> extends true\n ?\n | [\n body: TBody,\n options: Omit<\n EnforcedPathParamsOptions<TBody, unknown, TParams, Path>,\n 'body' | 'schema'\n >,\n ]\n | [\n body: undefined,\n options: Omit<\n EnforcedPathParamsOptions<TBody, unknown, TParams, Path>,\n 'body' | 'schema'\n >,\n ]\n : [\n body?: TBody,\n options?: Omit<\n EnforcedPathParamsOptions<TBody, unknown, TParams, Path>,\n 'body' | 'schema'\n >,\n ]\n ): ResponsePromise<unknown>\n\n public patch<\n TResponse,\n Path extends string = string,\n TParams extends RequestParamsType = RequestParamsType,\n TBody = unknown,\n >(\n url: Path,\n body?: TBody,\n options?: Omit<\n EnforcedPathParamsOptions<TBody, TResponse, TParams, Path>,\n 'body'\n >\n ): ResponsePromise<TResponse | unknown> {\n return this.request<Path, TResponse, TBody, TParams>('PATCH', url, {\n ...(options || {}),\n body,\n })\n }\n\n /**\n * Send a DELETE request with schema validation (type inferred from schema).\n *\n * @example\n * const response = await client.delete('/users/:id', {\n * pathParams: { id: '123' },\n * schema: z.object({ success: z.boolean() })\n * })\n *\n * @example\n * const result = await client.delete('/users/:id', {\n * pathParams: { id: '123' },\n * schema: deleteResultSchema\n * }).data()\n */\n public delete<\n TResponse,\n Path extends string = string,\n TParams extends RequestParamsType = RequestParamsType,\n >(\n url: Path,\n options: EnforcedPathParamsOptions<void, TResponse, TParams, Path> & {\n schema: Schema<TResponse>\n }\n ): ResponsePromise<TResponse>\n\n /**\n * Send a DELETE request without schema (response.data is unknown).\n *\n * @example\n * const response = await client.delete('/users/:id', {\n * pathParams: { id: '123' }\n * })\n *\n * @example\n * const data = await client.delete('/users/:id', {\n * pathParams: { id: '123' }\n * }).data()\n */\n public delete<\n Path extends string,\n TParams extends RequestParamsType = RequestParamsType,\n >(\n url: Path,\n ...args: HasRequiredParams<Path> extends true\n ? [\n options: Omit<\n EnforcedPathParamsOptions<void, unknown, TParams, Path>,\n 'schema'\n >,\n ]\n : [\n options?: Omit<\n EnforcedPathParamsOptions<void, unknown, TParams, Path>,\n 'schema'\n >,\n ]\n ): ResponsePromise<unknown>\n\n public delete<\n TResponse,\n Path extends string = string,\n TParams extends RequestParamsType = RequestParamsType,\n >(\n url: Path,\n options?: EnforcedPathParamsOptions<void, TResponse, TParams, Path>\n ): ResponsePromise<TResponse | unknown> {\n return this.request<Path, TResponse, void, TParams>(\n 'DELETE',\n url,\n options || {}\n )\n }\n\n /**\n * Validates path parameters against the URL template\n *\n * @param url - URL template with path parameters (e.g., '/users/:id')\n * @param pathParams - Path parameters to validate\n * @throws Error if required path parameters are missing or invalid\n */\n private validatePathParams<Path extends string>(\n url: Path,\n pathParams?: PathParams<Path>\n ): void {\n if (!pathParams) {\n const requiredParams = this.extractRequiredPathParams(url)\n\n if (requiredParams.length > 0) {\n throw new PathParameterError(\n `Missing required path parameters for URL \"${url}\": ${requiredParams.join(', ')}. ` +\n `Please provide pathParams: { ${requiredParams.map(p => `${p}: value`).join(', ')} }`,\n url,\n requiredParams,\n []\n )\n }\n return\n }\n\n const requiredParams = this.extractRequiredPathParams(url)\n const providedParams = Object.keys(pathParams)\n\n const missingParams = requiredParams.filter(\n param => !providedParams.includes(param)\n )\n if (missingParams.length > 0) {\n throw new PathParameterError(\n `Missing required path parameters: ${missingParams.join(', ')}. ` +\n `Provided: ${providedParams.join(', ')}`,\n url,\n requiredParams,\n providedParams\n )\n }\n\n // const unusedParams = providedParams.filter(\n // param => !requiredParams.includes(param)\n // )\n // if (unusedParams.length > 0) {\n // console.warn(\n // `Unused path parameters provided: ${unusedParams.join(', ')}. ` +\n // `URL \"${url}\" does not contain these parameters.`\n // )\n // }\n }\n\n /**\n * Extracts required path parameters from a URL template\n *\n * @param url - URL template to extract parameters from\n * @returns Array of required parameter names\n */\n private extractRequiredPathParams(url: string): string[] {\n if (url.includes('?')) {\n throw new PathParameterError(\n 'Optional path parameters (e.g., :variable?) are not supported',\n url,\n [],\n []\n )\n }\n\n const matches = url.match(/:([a-zA-Z0-9_]+)/g)\n\n return matches ? matches.map(match => match.slice(1)) : []\n }\n\n /**\n * Resolves a URL template with path parameters and base URL\n *\n * @param url - URL template with optional path parameters\n * @param pathParams - Path parameters to interpolate into the URL\n * @returns Fully resolved URL with base URL and path parameters applied\n */\n private resolveUrl<Path extends string>(\n url: Path,\n pathParams?: PathParams<Path>\n ): string {\n this.validatePathParams(url, pathParams)\n\n const interpolatedUrl = pathParams ? generatePath(url, pathParams) : url\n\n if (/^https?:\\/\\//i.test(interpolatedUrl)) {\n return interpolatedUrl\n }\n\n const path = interpolatedUrl.startsWith('/')\n ? interpolatedUrl.slice(1)\n : interpolatedUrl\n\n return `${this.baseUrl}/${path}`\n }\n}\n"],"names":["createStdSchemaValidator","controller","requiredParams"],"mappings":"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"}
1
+ {"version":3,"file":"index.es.js","sources":["../src/errors.ts","../src/standard-schema.ts","../src/schema.ts","../src/utils/path.ts","../src/client.ts"],"sourcesContent":["interface HttpClientError {\n name: string\n message: string\n cause?: Error\n stack?: string\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 enhancedMessage = `HTTP ${status} ${statusText}: ${message} (${method} ${url})`\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 }\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 }\n}\n\nexport class SchemaValidationError extends Error implements HttpClientError {\n public readonly name = 'SchemaValidationError'\n public readonly schema: unknown\n public readonly data: unknown\n public override readonly cause?: Error\n\n constructor(message: string, schema: unknown, data: unknown, cause?: Error) {\n super(message, { cause })\n this.schema = schema\n this.data = data\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 }\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 super(message, { cause })\n this.url = url\n this.requiredParams = requiredParams\n this.providedParams = providedParams\n }\n}\n\nexport class InterceptorError extends Error implements HttpClientError {\n public readonly name = 'InterceptorError'\n public readonly interceptorType: '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 interceptorType: 'request' | 'response',\n url?: string,\n method?: string,\n cause?: Error\n ) {\n super(message, { cause })\n this.interceptorType = interceptorType\n this.url = url\n this.method = method\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 }\n}\n","import { SchemaValidator } from './schema'\n\n/**\n * Standard Schema V1 interface implementation\n *\n * This interface defines the structure for schema validation libraries\n * that conform to the Standard Schema specification.\n *\n * @see https://github.com/standard-schema/standard-schema\n */\nexport interface StandardSchemaV1<Input = unknown, Output = Input> {\n /** The Standard Schema properties containing validation logic and metadata */\n readonly '~standard': StandardSchemaV1.Props<Input, Output>\n}\n\n/**\n * Namespace containing Standard Schema V1 type definitions\n */\nexport namespace StandardSchemaV1 {\n /**\n * Core properties interface for Standard Schema V1\n */\n export interface Props<Input = unknown, Output = Input> {\n /** The version number of the Standard Schema specification */\n readonly version: 1\n /** The name of the schema validation library (e.g., 'zod', 'valibot') */\n readonly vendor: string\n /**\n * Validates unknown input values against the schema\n *\n * @param value - The value to validate\n * @returns Promise or direct result containing validation outcome\n */\n readonly validate: (\n value: unknown\n ) => Result<Output> | Promise<Result<Output>>\n /** Type information for input and output types */\n readonly types?: Types<Input, Output> | undefined\n }\n\n /**\n * Union type representing the result of schema validation\n */\n export type Result<Output> = SuccessResult<Output> | FailureResult\n\n /**\n * Interface for successful validation results\n */\n export interface SuccessResult<Output> {\n readonly value: Output\n readonly issues?: undefined\n }\n\n /**\n * Interface for failed validation results\n */\n export interface FailureResult {\n readonly issues: ReadonlyArray<Issue>\n }\n\n /**\n * Interface for individual validation error details\n */\n export interface Issue {\n /** Human-readable error message describing the validation failure */\n readonly message: string\n /**\n * Path to the property that failed validation\n * Useful for nested object validation to pinpoint the exact location\n * of validation failures.\n */\n readonly path?: ReadonlyArray<PropertyKey | PathSegment> | undefined\n }\n\n /**\n * Interface for path segment information in validation errors\n */\n export interface PathSegment {\n readonly key: PropertyKey\n }\n\n /**\n * Interface for type information associated with a schema\n */\n export interface Types<Input = unknown, Output = Input> {\n readonly input: Input\n readonly output: Output\n }\n\n /**\n * Type utility to infer the input type from a Standard Schema\n */\n export type InferInput<Schema extends StandardSchemaV1> = NonNullable<\n Schema['~standard']['types']\n >['input']\n\n /**\n * Type utility to infer the output type from a Standard Schema\n */\n export type InferOutput<Schema extends StandardSchemaV1> = NonNullable<\n Schema['~standard']['types']\n >['output']\n}\n\n/**\n * Type guard to check if an object conforms to the Standard Schema V1 specification\n *\n * @param obj - The object to check\n * @returns True if the object is a valid Standard Schema V1 implementation\n *\n * @example\n * ```ts\n * if (isStandardSchema(schema)) {\n * // Use the schema with type safety\n * const result = schema['~standard'].validate(data);\n * }\n * ```\n */\nexport function 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 typeof obj['~standard'].version === 'number' &&\n 'vendor' in obj['~standard'] &&\n typeof obj['~standard'].vendor === 'string'\n )\n}\n\n/**\n * Creates an adapter for Standard Schema V1 implementations\n *\n * Converts Standard Schema validation results into a format compatible\n * with the HTTP client's schema validation system.\n *\n * @param schema - The Standard Schema V1 implementation to adapt\n * @returns Adapter object with parse method\n *\n * @example\n * ```ts\n * const zodAdapter = standardSchemaAdapter(zodUserSchema);\n * const validatedUser = zodAdapter.parse(userData);\n * ```\n */\nexport function standardSchemaAdapter<T>(schema: StandardSchemaV1<unknown, T>) {\n return {\n /**\n * Parses and validates data using the Standard Schema\n *\n * @param data - The data to validate\n * @returns The validated and typed data\n * @throws Error if validation fails\n */\n parse: (data: unknown): T => {\n const result = schema['~standard'].validate(data)\n\n if (result instanceof Promise) {\n throw new Error('Async Standard Schema validation is not supported')\n }\n\n if ('issues' in result && result.issues) {\n const errorMessages = Array.from(result.issues)\n .map(issue => issue.message)\n .join('; ')\n throw new Error(`Standard Schema validation failed: ${errorMessages}`)\n }\n\n return result.value as T\n },\n }\n}\n\n/**\n * Creates a schema validator that supports Standard Schema V1 implementations\n *\n * Provides a validator that can work with any schema library that implements\n * the Standard Schema V1 specification, enabling interoperability between\n * different validation libraries.\n *\n * @returns SchemaValidator that supports Standard Schema V1\n *\n * @example\n * ```ts\n * const validator = createStandardSchemaValidator();\n * const client = new HttpClient({ schemaValidator: validator });\n * ```\n */\nexport function createStandardSchemaValidator(): SchemaValidator {\n return {\n /**\n * Validates data against a Standard Schema V1 implementation\n *\n * @param schema - The Standard Schema V1 to validate against\n * @param data - The data to validate\n * @returns The validated and typed data\n * @throws Error if validation fails or schema is invalid\n */\n validate<T>(schema: StandardSchemaV1<unknown, T>, data: unknown): T {\n if (!isStandardSchema(schema)) {\n throw new Error(\n 'Invalid schema: Schema must implement the Standard Schema interface'\n )\n }\n\n const adapter = standardSchemaAdapter<T>(schema)\n return adapter.parse(data)\n },\n\n /**\n * Checks if an object is a valid Standard Schema V1 implementation\n *\n * @param obj - The object to check\n * @returns True if the object is a valid Standard Schema V1\n */\n isSchema(obj: unknown): boolean {\n return isStandardSchema(obj)\n },\n }\n}\n","import {\n createStandardSchemaValidator as createStdSchemaValidator,\n isStandardSchema,\n} from './standard-schema'\n\nimport { Schema } from './types'\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\n * @throws {SchemaValidationError} If the data doesn't match the schema\n */\n validate<T>(schema: Schema<T>, data: unknown): T\n\n /**\n * Check if an object is a valid schema.\n *\n * @param obj - The object to check\n * @returns True if the object is a valid schema, false otherwise\n */\n isSchema(obj: unknown): boolean\n}\n\n/**\n * Create a default schema validator that supports Standard Schema.\n *\n * This validator only works with schemas that implement the Standard Schema\n * interface. For full support of Zod, Valibot, and Arktype, use the\n * appropriate validator from their respective packages.\n *\n * @returns A schema validator instance\n *\n * @example\n * ```ts\n * import { createSchemaValidator } from '1000fetches'\n *\n * const validator = createSchemaValidator();\n *\n * // Use with HttpClient\n * const client = new HttpClient({\n * schemaValidator: validator\n * });\n * ```\n */\nexport function createSchemaValidator(): SchemaValidator {\n return {\n validate<T>(schema: Schema<T>, data: unknown): T {\n if (!isStandardSchema(schema)) {\n throw new Error(\n 'Invalid schema: Schema must implement the Standard Schema interface'\n )\n }\n\n return createStdSchemaValidator().validate(schema, data)\n },\n\n isSchema(obj: unknown): boolean {\n return isStandardSchema(obj)\n },\n }\n}\n\nexport { createStdSchemaValidator as createStandardSchemaValidator }\n","import { PathParameterError } from '../errors'\n\n/**\n * Strips protocol from URL (e.g., https://, http://)\n */\ntype StripProtocol<T extends string> = T extends `${string}://${infer After}`\n ? After\n : T\n\n/**\n * Strips host and optional port from URL, keeping only the path\n * Handles cases like \"localhost:3000/users\" -> \"/users\"\n */\ntype StripHost<T extends string> = T extends `${infer _Host}/${infer Path}`\n ? `/${Path}`\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 `${string}=${string}` | `${string}=${string}&${string}` | `${string}&${string}`\n ? Path // contains = or &\n : Query extends `/${string}`\n ? T // it's another path segment\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<StripHost<StripProtocol<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 all path parameters from a route\n */\ntype ExtractRouteParams<T extends string> =\n NormalizePath<T> extends `${infer _Before}:${infer AfterColon}`\n ? AfterColon extends `${infer Param}/${infer Rest}`\n ? CleanParamName<`:${Param}`> | ExtractRouteParams<`/${Rest}`>\n : CleanParamName<`:${AfterColon}`>\n : never\n\nexport type HasRequiredParams<T extends string> = [ExtractRouteParams<T>] extends [never]\n ? false\n : true\n\n/**\n * PathParams type - extracts parameter names and their types\n */\nexport type PathParams<Path extends string> = {\n [K in ExtractRouteParams<Path>]: string | number\n}\n\n/**\n * RequirePathParams enforces pathParams when needed\n */\nexport type RequirePathParams<Path extends string, T> =\n HasRequiredParams<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: Path,\n params: PathParams<Path> = {} as PathParams<Path>\n): string {\n return path.replace(/:([a-zA-Z0-9_]+)/g, (_match, paramName: string) => {\n if (params[paramName as keyof PathParams<Path>] === undefined) {\n throw new PathParameterError(\n `Missing required path parameter: ${paramName}`,\n path,\n [paramName],\n Object.keys(params)\n )\n }\n return String(params[paramName as keyof PathParams<Path>])\n })\n}\n","import {\n HttpError,\n InterceptorError,\n NetworkError,\n PathParameterError,\n SchemaValidationError,\n SerializationError,\n TimeoutError,\n} from './errors'\nimport { createSchemaValidator, type SchemaValidator } from './schema'\nimport type {\n EnforcedPathParamsOptions,\n HttpClientOptions,\n HttpMethod,\n RequestContext,\n RequestInterceptor,\n RequestOptions,\n RequestParamsType,\n ResponseInterceptor,\n ResponsePromise,\n ResponseType,\n RetryOptions,\n Schema,\n TypedRequestOptions,\n} from './types'\nimport { generatePath, type HasRequiredParams, type PathParams } from './utils'\n\n/**\n * Default retry configuration for HTTP requests\n */\nconst DEFAULT_RETRY_OPTIONS: Required<RetryOptions> = {\n maxRetries: 3,\n retryDelay: 300,\n backoffFactor: 2,\n retryStatusCodes: [429, 500, 502, 503, 504],\n retryNetworkErrors: true,\n maxRetryDelay: 30000,\n shouldRetry: () => true,\n}\n\nfunction validateAndNormalizeBaseUrl(baseUrl?: string): string {\n const hasLocation =\n typeof window !== 'undefined' &&\n typeof window.location !== 'undefined' &&\n window.location.origin !== 'null'\n\n if (!baseUrl) {\n // In browser environment, default to location.origin for relative paths\n return hasLocation ? window.location.origin : ''\n }\n\n if (baseUrl.startsWith('/')) {\n // In Node.js or non-browser environments, relative paths are preserved as-is\n return hasLocation\n ? new URL(baseUrl, window.location.origin).href.replace(/\\/$/, '')\n : baseUrl.replace(/\\/$/, '')\n }\n\n try {\n new URL(baseUrl)\n } catch {\n throw new Error(\n `Invalid baseUrl: \"${baseUrl}\". Must be a valid absolute URL or relative path starting with \"/\".`\n )\n }\n\n return baseUrl.endsWith('/') ? baseUrl.slice(0, -1) : baseUrl\n}\n\n/**\n * Wraps a response promise with data extraction method\n */\nfunction wrapResponsePromise<T>(\n promise: Promise<ResponseType<T>>\n): ResponsePromise<T> {\n const wrappedPromise = promise as ResponsePromise<T>\n\n wrappedPromise.data = async () => {\n const response = await promise\n return response.data\n }\n\n return wrappedPromise\n}\n\n/**\n * A modern, type-safe HTTP client with built-in schema validation, interceptors, retry logic, and compile-time path parameter validation.\n *\n * The HttpClient provides a fluent API for making HTTP requests with full TypeScript support,\n * automatic retry logic, request/response interceptors, and schema validation using popular\n * validation libraries like Zod, Valibot, and Arktype.\n *\n * @example\n * ```ts\n * import { HttpClient } from '1000fetches'\n * import { z } from 'zod'\n *\n * // Create a client instance\n * const client = new HttpClient({\n * baseUrl: 'https://api.example.com',\n * timeout: 5000,\n * headers: { 'Authorization': 'Bearer token' }\n * });\n *\n * const userSchema = z.object({\n * id: z.string(),\n * name: z.string(),\n * email: z.string()\n * });\n *\n * const response = await client.get('/users/:id', {\n * pathParams: { id: '123' },\n * schema: userSchema\n * });\n */\nexport class HttpClient {\n private baseUrl: string\n private defaultHeaders: Record<string, string>\n private defaultTimeout: number\n private schemaValidator: SchemaValidator\n private requestInterceptors: RequestInterceptor[]\n private responseInterceptors: ResponseInterceptor[]\n private defaultRetryOptions?: RetryOptions\n\n /**\n * Create a new HttpClient instance.\n *\n * @param options - Configuration options for the HTTP client\n *\n * @example\n * ```ts\n * // Basic configuration\n * const client = new HttpClient({\n * baseUrl: 'https://api.example.com'\n * });\n *\n * // With custom headers and timeout\n * const client = new HttpClient({\n * baseUrl: 'https://api.example.com',\n * headers: { 'Authorization': 'Bearer token' },\n * timeout: 10000\n * });\n *\n * // With custom schema validator\n * const client = new HttpClient({\n * baseUrl: 'https://api.example.com',\n * schemaValidator: createCustomValidator()\n * });\n *\n * // With retry configuration\n * const client = new HttpClient({\n * baseUrl: 'https://api.example.com',\n * retryOptions: {\n * maxRetries: 5,\n * retryDelay: 1000,\n * retryStatusCodes: [500, 502, 503]\n * }\n * });\n * ```\n */\n constructor(options: HttpClientOptions = {}) {\n this.baseUrl = validateAndNormalizeBaseUrl(options.baseUrl)\n this.defaultHeaders = options.headers ?? {}\n this.defaultTimeout = options.timeout ?? 30_000\n this.schemaValidator = options.schemaValidator || createSchemaValidator()\n this.requestInterceptors = options.requestInterceptors ?? []\n this.responseInterceptors = options.responseInterceptors ?? []\n this.defaultRetryOptions = options.retryOptions\n }\n\n /**\n * Add a request interceptor to modify requests before they're sent.\n */\n public addRequestInterceptor(interceptor: RequestInterceptor): void {\n this.requestInterceptors.push(interceptor)\n }\n\n /**\n * Add a response interceptor to process responses before they're returned.\n */\n public addResponseInterceptor(interceptor: ResponseInterceptor): void {\n this.responseInterceptors.push(interceptor)\n }\n\n /**\n * Determines if a request should be retried based on error type and retry configuration\n *\n * @param error - The error that occurred during the request\n * @param retryCount - Current retry attempt number\n * @param retryOptions - Retry configuration for this request\n * @returns Promise resolving to whether the request should be retried\n */\n private async shouldRetry(\n error: Error,\n retryCount: number,\n retryOptions: RetryOptions | boolean | undefined\n ): Promise<boolean> {\n if (retryOptions === false) return false\n\n const options = this.getRetryOptions(retryOptions)\n if (retryCount >= options.maxRetries) return false\n\n if (typeof options.shouldRetry === 'function') {\n try {\n return await options.shouldRetry(error, retryCount)\n } catch (retryError) {\n console.warn('Custom shouldRetry function failed:', retryError)\n }\n }\n\n if (error instanceof NetworkError && options.retryNetworkErrors) {\n return true\n }\n\n if (\n error instanceof HttpError &&\n options.retryStatusCodes.includes(error.status)\n ) {\n return true\n }\n\n if (error instanceof SchemaValidationError) {\n return false\n }\n\n if (error instanceof TimeoutError) {\n return true\n }\n\n return false\n }\n\n /**\n * Calculates the delay for the next retry attempt using exponential backoff with jitter\n *\n * @param retryCount - Current retry attempt number\n * @param options - Retry configuration options\n * @returns Delay in milliseconds before the next retry attempt\n */\n private getRetryDelay(\n retryCount: number,\n options: Required<RetryOptions>\n ): number {\n const baseDelay =\n options.retryDelay * Math.pow(options.backoffFactor, retryCount)\n const cappedDelay = Math.min(baseDelay, options.maxRetryDelay)\n\n // Add jitter (+-20%) to prevent thundering herd problem\n const jitterRange = cappedDelay * 0.2\n const jitter = jitterRange * (Math.random() * 2 - 1)\n const finalDelay = cappedDelay + jitter\n\n return Math.max(1, Math.floor(finalDelay))\n }\n\n /**\n * Merges provided retry options with default configuration\n */\n private getRetryOptions(\n retryOptions?: RetryOptions | boolean\n ): Required<RetryOptions> {\n if (retryOptions === false) {\n return {\n ...DEFAULT_RETRY_OPTIONS,\n maxRetries: 0,\n }\n }\n\n if (retryOptions === true) {\n return {\n ...DEFAULT_RETRY_OPTIONS,\n ...this.defaultRetryOptions,\n }\n }\n\n if (typeof retryOptions === 'object') {\n return {\n ...DEFAULT_RETRY_OPTIONS,\n ...this.defaultRetryOptions,\n ...retryOptions,\n }\n }\n\n return {\n ...DEFAULT_RETRY_OPTIONS,\n ...this.defaultRetryOptions,\n }\n }\n\n /**\n * Creates a promise that resolves after the specified delay\n */\n private sleep(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms))\n }\n\n /**\n * Makes an HTTP request with automatic retry capability\n *\n * @param method - HTTP method to use for the request\n * @param url - URL path for the request (supports path parameters)\n * @param options - Request configuration options\n * @returns Promise resolving to the response data with data extraction method\n *\n * @example\n * ```ts\n * // GET\n * const response = await client.request('GET', '/users/1');\n *\n * // POST\n * const response = await client.request('POST', '/users/:id/posts', {\n * pathParams: { id: 1 },\n * body: { title: 'New Post', content: 'Hello World' },\n * schema: userPostSchema\n * });\n *\n * // Data extraction\n * const user = await client.request('GET', '/users/1', { schema: userSchema }).data();\n * ```\n */\n public request<\n Path extends string = string,\n TResponse = unknown,\n TBody = unknown,\n TParams extends RequestParamsType = RequestParamsType,\n >(\n method: HttpMethod,\n url: Path,\n options: TypedRequestOptions<TBody, TResponse, TParams, Path> = {}\n ): ResponsePromise<TResponse> {\n return wrapResponsePromise(\n this.requestWithRetry<Path, TResponse, TBody, TParams>(\n method,\n url,\n options\n )\n )\n }\n\n /**\n * Internal method that handles retry logic for requests\n */\n private async requestWithRetry<\n Path extends string = string,\n TResponse = unknown,\n TBody = unknown,\n TParams extends RequestParamsType = RequestParamsType,\n >(\n method: HttpMethod,\n url: Path,\n options: TypedRequestOptions<TBody, TResponse, TParams, Path>\n ): Promise<ResponseType<TResponse>> {\n let retryCount = 0\n\n while (true) {\n try {\n return await this.executeRequest<Path, TResponse, TBody, TParams>(\n method,\n url,\n options\n )\n } catch (error) {\n if (!(error instanceof Error)) {\n throw new NetworkError(String(error), undefined)\n }\n\n if (await this.shouldRetry(error, retryCount, options.retry)) {\n const retryOptions = this.getRetryOptions(options.retry)\n const delay = this.getRetryDelay(retryCount, retryOptions)\n await this.sleep(delay)\n\n retryCount++\n continue\n }\n\n throw error\n }\n }\n }\n\n /**\n * Executes a single HTTP request without retry logic\n *\n * @param method - HTTP method for the request\n * @param url - URL path with optional path parameters\n * @param options - Request configuration and validation options\n * @returns Promise resolving to the response data\n */\n private async executeRequest<\n Path extends string = string,\n TResponse = unknown,\n TBody = unknown,\n TParams extends RequestParamsType = RequestParamsType,\n >(\n method: HttpMethod,\n url: Path,\n options: TypedRequestOptions<TBody, TResponse, TParams, Path> = {}\n ): Promise<ResponseType<TResponse>> {\n let resolvedUrl = this.resolveUrl(url, options.pathParams)\n\n let requestContext: RequestContext<TBody> = {\n url: resolvedUrl,\n method,\n params: options.params,\n headers: this.prepareHeaders(options.headers),\n body: options.body,\n fetchOptions: {\n credentials: options.credentials,\n cache: options.cache,\n mode: options.mode,\n redirect: options.redirect,\n },\n }\n\n for (const interceptor of this.requestInterceptors) {\n try {\n requestContext = await interceptor(requestContext)\n } catch (error) {\n throw new InterceptorError(\n `Request interceptor failed: ${error instanceof Error ? error.message : String(error)}`,\n 'request',\n resolvedUrl,\n method,\n error instanceof Error ? error : undefined\n )\n }\n }\n\n resolvedUrl = requestContext.url\n\n if (\n requestContext.params &&\n Object.keys(requestContext.params).length > 0\n ) {\n const searchParams = new URLSearchParams()\n for (const [key, value] of Object.entries(requestContext.params)) {\n if (value !== undefined) {\n searchParams.append(key, String(value))\n }\n }\n const queryString = searchParams.toString()\n if (queryString) {\n resolvedUrl += (resolvedUrl.includes('?') ? '&' : '?') + queryString\n }\n }\n\n const requestInit: RequestInit = {\n method: requestContext.method,\n headers: requestContext.headers,\n ...requestContext.fetchOptions,\n }\n\n if (\n requestContext.body !== undefined &&\n (requestContext.method === 'POST' ||\n requestContext.method === 'PUT' ||\n requestContext.method === 'PATCH')\n ) {\n if (\n requestContext.body instanceof FormData ||\n requestContext.body instanceof Blob ||\n requestContext.body instanceof ArrayBuffer ||\n requestContext.body instanceof URLSearchParams ||\n typeof requestContext.body === 'string'\n ) {\n requestInit.body = requestContext.body as BodyInit\n } else {\n try {\n requestInit.body = JSON.stringify(requestContext.body)\n } catch (error) {\n throw new SerializationError(\n `Failed to serialize request body: ${error instanceof Error ? error.message : 'Invalid data structure'}`,\n error instanceof Error ? error : undefined\n )\n }\n }\n }\n\n const timeoutDuration = options.timeout || this.defaultTimeout\n const controller = new AbortController()\n const timeoutId = setTimeout(() => controller.abort(), timeoutDuration)\n\n const requestSignal = requestContext.signal || options.signal\n let cleanupSignals: VoidFunction | undefined\n const signal = requestSignal\n ? (() => {\n const result = this.mergeAbortSignals(\n requestSignal,\n controller.signal\n )\n cleanupSignals = result.cleanup\n return result.signal\n })()\n : controller.signal\n\n try {\n const response = await fetch(resolvedUrl, {\n ...requestInit,\n signal,\n })\n\n let responseData = await this.processResponse<TResponse>(\n response,\n options,\n method,\n resolvedUrl\n )\n\n if (options.schema) {\n responseData.data = this.validateWithSchema<TResponse>(\n options.schema,\n responseData.data\n )\n }\n\n return responseData\n } catch (error) {\n if (\n (error instanceof DOMException && error.name === 'AbortError') ||\n (error instanceof Error && error.name === 'AbortError') ||\n (error instanceof Error &&\n error.message.toLowerCase().includes('timeout'))\n ) {\n throw new TimeoutError(\n `Request timed out after ${timeoutDuration}ms`,\n error instanceof Error ? error : undefined\n )\n }\n\n if (\n error instanceof HttpError ||\n error instanceof SchemaValidationError ||\n error instanceof InterceptorError ||\n error instanceof PathParameterError ||\n error instanceof SerializationError\n ) {\n throw error\n }\n\n throw new NetworkError(\n error instanceof Error ? error.message : String(error),\n error instanceof Error ? error : undefined\n )\n } finally {\n clearTimeout(timeoutId)\n cleanupSignals?.()\n }\n }\n\n private validateWithSchema<T>(\n schema: Schema<T>,\n data: unknown,\n errorPrefix = 'Response schema validation failed'\n ): T {\n try {\n return this.schemaValidator.validate(schema, data)\n } catch (error) {\n throw new SchemaValidationError(\n `${errorPrefix}: ${error instanceof Error ? error.message : 'Unknown error'}`,\n schema,\n data,\n error instanceof Error ? error : undefined\n )\n }\n }\n\n /**\n * Prepares headers for HTTP requests by merging default and custom headers\n *\n * @param customHeaders - Additional headers to include in the request\n * @returns Headers object with all headers properly set\n */\n private prepareHeaders(customHeaders: Record<string, string> = {}): Headers {\n const headers = new Headers()\n\n for (const [key, value] of Object.entries(this.defaultHeaders)) {\n if (value != null) {\n headers.set(key, String(value))\n }\n }\n\n for (const [key, value] of Object.entries(customHeaders)) {\n if (value != null) {\n headers.set(key, String(value))\n }\n }\n\n return headers\n }\n\n /**\n * Extracts headers from Headers object into a plain record\n *\n * @param headers - Headers object to extract from\n * @returns Record containing header key-value pairs\n */\n private extractHeaders(headers: Headers): Record<string, string> {\n const result: Record<string, string> = {}\n headers.forEach((value, key) => {\n result[key] = value\n })\n return result\n }\n\n /**\n * Creates an HttpError instance with response details\n *\n * @param response - The HTTP response that caused the error\n * @param data - Response data (if any)\n * @param url - The URL that was requested\n * @param method - The HTTP method used\n * @param customStatusText - Optional custom status text\n * @param cause - Optional underlying error that caused this HTTP error\n * @returns HttpError instance with complete error information\n */\n private createHttpError(\n response: globalThis.Response,\n data: unknown,\n url: string,\n method: string,\n customStatusText?: string,\n cause?: Error\n ): HttpError {\n return new HttpError(\n `Request failed with status code ${response.status}`,\n response.status,\n customStatusText || response.statusText,\n data,\n response,\n url,\n method,\n cause\n )\n }\n\n private async parseResponseBody(\n response: globalThis.Response,\n options: RequestOptions\n ): Promise<unknown> {\n const contentType = response.headers.get('content-type') ?? ''\n\n try {\n if (options.responseType === 'text') {\n return await response.text()\n } else if (options.responseType === 'blob') {\n return await response.blob()\n } else if (options.responseType === 'arrayBuffer') {\n return await response.arrayBuffer()\n } else if (contentType.includes('application/json')) {\n const text = await response.text()\n if (!text) {\n return null\n }\n return JSON.parse(text)\n } else {\n return await response.text()\n }\n } catch (e) {\n if (response.status === 204) {\n return undefined\n }\n\n if (\n contentType.includes('application/json') &&\n e instanceof SyntaxError\n ) {\n throw new Error(`Failed to parse JSON response: ${e.message}`)\n }\n\n throw e\n }\n }\n\n private async processResponse<T, TBody = unknown>(\n response: globalThis.Response,\n options: TypedRequestOptions<TBody, T>,\n method: HttpMethod,\n url: string\n ): Promise<ResponseType<T>> {\n const headers = this.extractHeaders(response.headers)\n\n const validateStatus =\n options.validateStatus ||\n ((status: number) => status >= 200 && status < 300)\n\n const data = await this.parseResponseBody(response, options)\n\n if (!validateStatus(response.status)) {\n throw this.createHttpError(response, data, url, method)\n }\n\n const responseObj: ResponseType<unknown> = {\n data,\n status: response.status,\n statusText: response.statusText,\n headers,\n method,\n url,\n raw: response,\n }\n\n let processedResponse = responseObj\n const originalStatus = responseObj.status\n\n for (const interceptor of this.responseInterceptors) {\n try {\n processedResponse = await interceptor(processedResponse)\n } catch (error) {\n throw new InterceptorError(\n `Response interceptor failed: ${error instanceof Error ? error.message : String(error)}`,\n 'response',\n url,\n method,\n error instanceof Error ? error : undefined\n )\n }\n }\n\n // Only re-validate if interceptors changed the status\n if (\n processedResponse.status !== originalStatus &&\n !validateStatus(processedResponse.status)\n ) {\n throw this.createHttpError(\n response,\n processedResponse.data,\n url,\n method,\n processedResponse.statusText\n )\n }\n\n return processedResponse as ResponseType<T>\n }\n\n private mergeAbortSignals(\n signal1: AbortSignal,\n signal2: AbortSignal\n ): { signal: AbortSignal; cleanup?: VoidFunction } {\n if (signal1.aborted || signal2.aborted) {\n const controller = new AbortController()\n controller.abort()\n return { signal: controller.signal }\n }\n\n const controller = new AbortController()\n\n const abortHandler = () => {\n controller.abort()\n cleanup()\n }\n\n const cleanup = () => {\n signal1.removeEventListener('abort', abortHandler)\n signal2.removeEventListener('abort', abortHandler)\n }\n\n signal1.addEventListener('abort', abortHandler)\n signal2.addEventListener('abort', abortHandler)\n\n return { signal: controller.signal, cleanup }\n }\n\n /**\n * Send a GET request with schema validation (type inferred from schema).\n *\n * @example\n * // Get full response\n * const response = await client.get('/users/:id', {\n * pathParams: { id: '123' },\n * schema: z.object({ id: z.string(), name: z.string() })\n * })\n *\n * @example\n * // Extract data directly\n * const user = await client.get('/users/:id', {\n * pathParams: { id: '123' },\n * schema: userSchema\n * }).data()\n */\n public get<\n TResponse,\n Path extends string = string,\n TParams extends RequestParamsType = RequestParamsType,\n >(\n url: Path,\n options: EnforcedPathParamsOptions<void, TResponse, TParams, Path> & {\n schema: Schema<TResponse>\n }\n ): ResponsePromise<TResponse>\n\n /**\n * Send a GET request without schema (response.data is unknown).\n *\n * @example\n * const response = await client.get('/users')\n *\n * @example\n * const data = await client.get('/users').data()\n */\n public get<\n Path extends string,\n TParams extends RequestParamsType = RequestParamsType,\n >(\n url: Path,\n ...args: HasRequiredParams<Path> extends true\n ? [\n options: Omit<\n EnforcedPathParamsOptions<void, unknown, TParams, Path>,\n 'schema'\n >,\n ]\n : [\n options?: Omit<\n EnforcedPathParamsOptions<void, unknown, TParams, Path>,\n 'schema'\n >,\n ]\n ): ResponsePromise<unknown>\n\n public get<\n TResponse,\n Path extends string = string,\n TParams extends RequestParamsType = RequestParamsType,\n >(\n url: Path,\n options?: EnforcedPathParamsOptions<void, TResponse, TParams, Path>\n ): ResponsePromise<TResponse | unknown> {\n return this.request<Path, TResponse, void, TParams>(\n 'GET',\n url,\n options || {}\n )\n }\n\n /**\n * Send a POST request with schema validation (type inferred from schema).\n *\n * @example\n * const response = await client.post('/users', userData, {\n * schema: z.object({ id: z.string(), name: z.string() })\n * })\n *\n * @example\n * const user = await client.post('/users', userData, { schema: userSchema }).data()\n */\n public post<\n TResponse,\n Path extends string = string,\n TParams extends RequestParamsType = RequestParamsType,\n TBody = unknown,\n >(\n url: Path,\n body: TBody | undefined,\n options: Omit<\n EnforcedPathParamsOptions<TBody, TResponse, TParams, Path>,\n 'body'\n > & { schema: Schema<TResponse> }\n ): ResponsePromise<TResponse>\n\n /**\n * Send a POST request without schema (response.data is unknown).\n *\n * @example\n * const response = await client.post('/users', userData)\n *\n * @example\n * const data = await client.post('/users', userData).data()\n */\n public post<\n Path extends string,\n TParams extends RequestParamsType = RequestParamsType,\n TBody = unknown,\n >(\n url: Path,\n ...args: HasRequiredParams<Path> extends true\n ?\n | [\n body: TBody,\n options: Omit<\n EnforcedPathParamsOptions<TBody, unknown, TParams, Path>,\n 'body' | 'schema'\n >,\n ]\n | [\n body: undefined,\n options: Omit<\n EnforcedPathParamsOptions<TBody, unknown, TParams, Path>,\n 'body' | 'schema'\n >,\n ]\n : [\n body?: TBody,\n options?: Omit<\n EnforcedPathParamsOptions<TBody, unknown, TParams, Path>,\n 'body' | 'schema'\n >,\n ]\n ): ResponsePromise<unknown>\n\n public post<\n TResponse,\n Path extends string = string,\n TParams extends RequestParamsType = RequestParamsType,\n TBody = unknown,\n >(\n url: Path,\n body?: TBody,\n options?: Omit<\n EnforcedPathParamsOptions<TBody, TResponse, TParams, Path>,\n 'body'\n >\n ): ResponsePromise<TResponse | unknown> {\n return this.request<Path, TResponse, TBody, TParams>('POST', url, {\n ...(options || {}),\n body,\n })\n }\n\n /**\n * Send a PUT request with schema validation (type inferred from schema).\n *\n * @example\n * const response = await client.put('/users/:id', updatedData, {\n * pathParams: { id: '123' },\n * schema: z.object({ id: z.string(), name: z.string() })\n * })\n *\n * @example\n * const user = await client.put('/users/:id', updatedData, {\n * pathParams: { id: '123' },\n * schema: userSchema\n * }).data()\n */\n public put<\n TResponse,\n Path extends string = string,\n TParams extends RequestParamsType = RequestParamsType,\n TBody = unknown,\n >(\n url: Path,\n body: TBody | undefined,\n options: Omit<\n EnforcedPathParamsOptions<TBody, TResponse, TParams, Path>,\n 'body'\n > & { schema: Schema<TResponse> }\n ): ResponsePromise<TResponse>\n\n /**\n * Send a PUT request without schema (response.data is unknown).\n *\n * @example\n * const response = await client.put('/users/:id', updatedData, {\n * pathParams: { id: '123' }\n * })\n *\n * @example\n * const data = await client.put('/users/:id', updatedData, {\n * pathParams: { id: '123' }\n * }).data()\n */\n public put<\n Path extends string,\n TParams extends RequestParamsType = RequestParamsType,\n TBody = unknown,\n >(\n url: Path,\n ...args: HasRequiredParams<Path> extends true\n ?\n | [\n body: TBody,\n options: Omit<\n EnforcedPathParamsOptions<TBody, unknown, TParams, Path>,\n 'body' | 'schema'\n >,\n ]\n | [\n body: undefined,\n options: Omit<\n EnforcedPathParamsOptions<TBody, unknown, TParams, Path>,\n 'body' | 'schema'\n >,\n ]\n : [\n body?: TBody,\n options?: Omit<\n EnforcedPathParamsOptions<TBody, unknown, TParams, Path>,\n 'body' | 'schema'\n >,\n ]\n ): ResponsePromise<unknown>\n\n public put<\n TResponse,\n Path extends string = string,\n TParams extends RequestParamsType = RequestParamsType,\n TBody = unknown,\n >(\n url: Path,\n body?: TBody,\n options?: Omit<\n EnforcedPathParamsOptions<TBody, TResponse, TParams, Path>,\n 'body'\n >\n ): ResponsePromise<TResponse | unknown> {\n return this.request<Path, TResponse, TBody, TParams>('PUT', url, {\n ...(options || {}),\n body,\n })\n }\n\n /**\n * Send a PATCH request with schema validation (type inferred from schema).\n *\n * @example\n * const response = await client.patch('/users/:id', partialData, {\n * pathParams: { id: '123' },\n * schema: z.object({ id: z.string(), name: z.string() })\n * })\n *\n * @example\n * const user = await client.patch('/users/:id', partialData, {\n * pathParams: { id: '123' },\n * schema: userSchema\n * }).data()\n */\n public patch<\n TResponse,\n Path extends string = string,\n TParams extends RequestParamsType = RequestParamsType,\n TBody = unknown,\n >(\n url: Path,\n body: TBody | undefined,\n options: Omit<\n EnforcedPathParamsOptions<TBody, TResponse, TParams, Path>,\n 'body'\n > & { schema: Schema<TResponse> }\n ): ResponsePromise<TResponse>\n\n /**\n * Send a PATCH request without schema (response.data is unknown).\n *\n * @example\n * const response = await client.patch('/users/:id', partialData, {\n * pathParams: { id: '123' }\n * })\n *\n * @example\n * const data = await client.patch('/users/:id', partialData, {\n * pathParams: { id: '123' }\n * }).data()\n */\n public patch<\n Path extends string,\n TParams extends RequestParamsType = RequestParamsType,\n TBody = unknown,\n >(\n url: Path,\n ...args: HasRequiredParams<Path> extends true\n ?\n | [\n body: TBody,\n options: Omit<\n EnforcedPathParamsOptions<TBody, unknown, TParams, Path>,\n 'body' | 'schema'\n >,\n ]\n | [\n body: undefined,\n options: Omit<\n EnforcedPathParamsOptions<TBody, unknown, TParams, Path>,\n 'body' | 'schema'\n >,\n ]\n : [\n body?: TBody,\n options?: Omit<\n EnforcedPathParamsOptions<TBody, unknown, TParams, Path>,\n 'body' | 'schema'\n >,\n ]\n ): ResponsePromise<unknown>\n\n public patch<\n TResponse,\n Path extends string = string,\n TParams extends RequestParamsType = RequestParamsType,\n TBody = unknown,\n >(\n url: Path,\n body?: TBody,\n options?: Omit<\n EnforcedPathParamsOptions<TBody, TResponse, TParams, Path>,\n 'body'\n >\n ): ResponsePromise<TResponse | unknown> {\n return this.request<Path, TResponse, TBody, TParams>('PATCH', url, {\n ...(options || {}),\n body,\n })\n }\n\n /**\n * Send a DELETE request with schema validation (type inferred from schema).\n *\n * @example\n * const response = await client.delete('/users/:id', {\n * pathParams: { id: '123' },\n * schema: z.object({ success: z.boolean() })\n * })\n *\n * @example\n * const result = await client.delete('/users/:id', {\n * pathParams: { id: '123' },\n * schema: deleteResultSchema\n * }).data()\n */\n public delete<\n TResponse,\n Path extends string = string,\n TParams extends RequestParamsType = RequestParamsType,\n >(\n url: Path,\n options: EnforcedPathParamsOptions<void, TResponse, TParams, Path> & {\n schema: Schema<TResponse>\n }\n ): ResponsePromise<TResponse>\n\n /**\n * Send a DELETE request without schema (response.data is unknown).\n *\n * @example\n * const response = await client.delete('/users/:id', {\n * pathParams: { id: '123' }\n * })\n *\n * @example\n * const data = await client.delete('/users/:id', {\n * pathParams: { id: '123' }\n * }).data()\n */\n public delete<\n Path extends string,\n TParams extends RequestParamsType = RequestParamsType,\n >(\n url: Path,\n ...args: HasRequiredParams<Path> extends true\n ? [\n options: Omit<\n EnforcedPathParamsOptions<void, unknown, TParams, Path>,\n 'schema'\n >,\n ]\n : [\n options?: Omit<\n EnforcedPathParamsOptions<void, unknown, TParams, Path>,\n 'schema'\n >,\n ]\n ): ResponsePromise<unknown>\n\n public delete<\n TResponse,\n Path extends string = string,\n TParams extends RequestParamsType = RequestParamsType,\n >(\n url: Path,\n options?: EnforcedPathParamsOptions<void, TResponse, TParams, Path>\n ): ResponsePromise<TResponse | unknown> {\n return this.request<Path, TResponse, void, TParams>(\n 'DELETE',\n url,\n options || {}\n )\n }\n\n /**\n * Validates path parameters against the URL template\n *\n * @param url - URL template with path parameters (e.g., '/users/:id')\n * @param pathParams - Path parameters to validate\n * @throws Error if required path parameters are missing or invalid\n */\n private validatePathParams<Path extends string>(\n url: Path,\n pathParams?: PathParams<Path>\n ): void {\n if (!pathParams) {\n const requiredParams = this.extractRequiredPathParams(url)\n\n if (requiredParams.length > 0) {\n throw new PathParameterError(\n `Missing required path parameters for URL \"${url}\": ${requiredParams.join(', ')}. ` +\n `Please provide pathParams: { ${requiredParams.map(p => `${p}: value`).join(', ')} }`,\n url,\n requiredParams,\n []\n )\n }\n return\n }\n\n const requiredParams = this.extractRequiredPathParams(url)\n const providedParams = Object.keys(pathParams)\n\n const missingParams = requiredParams.filter(\n param => !providedParams.includes(param)\n )\n if (missingParams.length > 0) {\n throw new PathParameterError(\n `Missing required path parameters: ${missingParams.join(', ')}. ` +\n `Provided: ${providedParams.join(', ')}`,\n url,\n requiredParams,\n providedParams\n )\n }\n\n // const unusedParams = providedParams.filter(\n // param => !requiredParams.includes(param)\n // )\n // if (unusedParams.length > 0) {\n // console.warn(\n // `Unused path parameters provided: ${unusedParams.join(', ')}. ` +\n // `URL \"${url}\" does not contain these parameters.`\n // )\n // }\n }\n\n /**\n * Extracts required path parameters from a URL template\n *\n * @param url - URL template to extract parameters from\n * @returns Array of required parameter names\n */\n private extractRequiredPathParams(url: string): string[] {\n if (!url) {\n return []\n }\n\n const pathOnly = url.split('?').at(0)?.split('#').at(0)\n\n if (!pathOnly?.includes(':')) {\n return []\n }\n\n const matches = pathOnly.match(/:([a-zA-Z0-9_]+)/g)\n return matches ? matches.map(match => match.slice(1)) : []\n }\n\n /**\n * Resolves a URL template with path parameters and base URL\n *\n * @param url - URL template with optional path parameters\n * @param pathParams - Path parameters to interpolate into the URL\n * @returns Fully resolved URL with base URL and path parameters applied\n */\n private resolveUrl<Path extends string>(\n url: Path,\n pathParams?: PathParams<Path>\n ): string {\n this.validatePathParams(url, pathParams)\n\n const interpolatedUrl = pathParams ? generatePath(url, pathParams) : url\n\n if (/^https?:\\/\\//i.test(interpolatedUrl)) {\n return interpolatedUrl\n }\n\n const path = interpolatedUrl.startsWith('/')\n ? interpolatedUrl.slice(1)\n : interpolatedUrl\n\n return `${this.baseUrl}/${path}`\n }\n}\n"],"names":["createStdSchemaValidator","controller","requiredParams"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "1000fetches",
3
- "version": "0.1.3",
3
+ "version": "0.1.4",
4
4
  "description": "A type-first HTTP client with compile-time path validation, runtime schema verification, smart retry logic, and interceptors — powered by native fetch. Supports Zod, Valibot, ArkType, and any Standard Schema-compatible library.",
5
5
  "main": "dist/index.cjs.js",
6
6
  "module": "dist/index.es.js",
@@ -54,11 +54,11 @@
54
54
  },
55
55
  "homepage": "https://github.com/your-username/1000fetches#readme",
56
56
  "devDependencies": {
57
- "@types/node": "22.18.8",
57
+ "@types/node": "22.18.9",
58
58
  "@vitest/coverage-v8": "3.2.4",
59
59
  "arktype": "2.1.22",
60
60
  "expect-type": "1.2.2",
61
- "msw": "2.11.3",
61
+ "msw": "2.11.5",
62
62
  "rollup-plugin-visualizer": "6.0.4",
63
63
  "terser": "5.44.0",
64
64
  "typescript": "5.9.3",