1000fetches 0.1.1 → 0.1.2

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 e extends Error{name="HttpError";status;statusText;data;response;url;method;cause;constructor(e,t,r,s,a,o,n,i){super(`HTTP ${t} ${r}: ${e} (${n} ${o})`,{cause:i}),this.status=t,this.statusText=r,this.data=s,this.response=a,this.url=o,this.method=n}}class t extends Error{name="NetworkError";cause;constructor(e,t){super(e,{cause:t})}}class r extends Error{name="SchemaValidationError";schema;data;cause;constructor(e,t,r,s){super(e,{cause:s}),this.schema=t,this.data=r}}class s extends Error{name="TimeoutError";cause;constructor(e,t){super(e,{cause:t})}}class a extends Error{name="PathParameterError";url;requiredParams;providedParams;cause;constructor(e,t,r,s,a){super(e,{cause:a}),this.url=t,this.requiredParams=r,this.providedParams=s}}class o extends Error{name="InterceptorError";interceptorType;url;method;cause;constructor(e,t,r,s,a){super(e,{cause:a}),this.interceptorType=t,this.url=r,this.method=s}}class n extends Error{name="SerializationError";cause;constructor(e,t){super(e,{cause:t})}}function i(e){return null!==e&&("object"==typeof e||"function"==typeof e)&&"~standard"in e&&"object"==typeof e["~standard"]&&null!==e["~standard"]&&"validate"in e["~standard"]&&"function"==typeof e["~standard"].validate&&"version"in e["~standard"]&&"number"==typeof e["~standard"].version&&"vendor"in e["~standard"]&&"string"==typeof e["~standard"].vendor}function c(e){return{parse:t=>{const r=e["~standard"].validate(t);if(r instanceof Promise)throw new Error("Async Standard Schema validation is not supported");if("issues"in r&&r.issues){const e=Array.from(r.issues).map(e=>e.message).join("; ");throw new Error(`Standard Schema validation failed: ${e}`)}return r.value}}}function d(){return{validate(e,t){if(!i(e))throw new Error("Invalid schema: Schema must implement the Standard Schema interface");return c(e).parse(t)},isSchema:e=>i(e)}}function u(){return{validate(e,t){if(!i(e))throw new Error("Invalid schema: Schema must implement the Standard Schema interface");return d().validate(e,t)},isSchema:e=>i(e)}}function h(e,t={}){return e.replace(/:([a-zA-Z0-9_]+)/g,(r,s)=>{if(void 0===t[s])throw new a(`Missing required path parameter: ${s}`,e,[s],Object.keys(t));return String(t[s])})}const l={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(e={}){this.baseUrl=function(e){if(!e)return"";try{new URL(e)}catch{throw new Error(`Invalid baseUrl: "${e}". Must be a valid URL.`)}return e.endsWith("/")?e.slice(0,-1):e}(e.baseUrl),this.defaultHeaders=e.headers||{},this.defaultTimeout=e.timeout||3e4,this.schemaValidator=e.schemaValidator||u(),this.requestInterceptors=e.requestInterceptors||[],this.responseInterceptors=e.responseInterceptors||[],this.defaultRetryOptions=e.retryOptions}addRequestInterceptor(e){this.requestInterceptors.push(e)}addResponseInterceptor(e){this.responseInterceptors.push(e)}setSchemaValidator(e){this.schemaValidator=e}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 t&&i.retryNetworkErrors)||(!!(a instanceof e&&i.retryStatusCodes.includes(a.status))||!(a instanceof r)&&a instanceof s)}getRetryDelay(e,t){const r=t.retryDelay*Math.pow(t.backoffFactor,e),s=Math.min(r,t.maxRetryDelay),a=s+.2*s*(2*Math.random()-1);return Math.max(1,Math.floor(a))}getRetryOptions(e){return!1===e?{...l,maxRetries:0}:!0===e?{...l,...this.defaultRetryOptions}:"object"==typeof e?{...l,...this.defaultRetryOptions,...e}:{...l,...this.defaultRetryOptions}}sleep(e){return new Promise(t=>setTimeout(t,e))}async request(e,r,s={}){let a=0;for(;;)try{return await this.executeRequest(e,r,s)}catch(o){if(!(o instanceof Error))throw new t(String(o),void 0);if(await this.shouldRetry(o,a,s.retry)){const e=this.getRetryOptions(s.retry),t=this.getRetryDelay(a,e);await this.sleep(t),a++;continue}throw o}}async executeRequest(i,c,d={}){let u=this.resolveUrl(c,d.pathParams),h={url:u,method:i,params:d.params,headers:this.prepareHeaders(d.headers),body:d.body,fetchOptions:{credentials:d.credentials,cache:d.cache,mode:d.mode,redirect:d.redirect}};for(const e of this.requestInterceptors)try{h=await e(h)}catch(b){throw new o(`Request interceptor failed: ${b instanceof Error?b.message:String(b)}`,"request",u,i,b instanceof Error?b:void 0)}if(u=h.url,h.params&&Object.keys(h.params).length>0){const e=new URLSearchParams;for(const[r,s]of Object.entries(h.params))void 0!==s&&e.append(r,String(s));const t=e.toString();t&&(u+=(u.includes("?")?"&":"?")+t)}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=d.timeout||this.defaultTimeout,f=new AbortController,m=setTimeout(()=>f.abort(),p),y=h.signal||d.signal;let w;const E=y?(()=>{const e=this.mergeAbortSignals(y,f.signal);return w=e.cleanup,e.signal})():f.signal;try{const e=await fetch(u,{...l,signal:E});let t=await this.processResponse(e,d,i,u);return d.schema&&(t.data=this.validateResponseData(d.schema,t.data)),t}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 e||b instanceof r||b instanceof o||b instanceof a||b instanceof n)throw b;throw new t(b instanceof Error?b.message:String(b),b instanceof Error?b:void 0)}finally{clearTimeout(m),w?.()}}validateWithSchema(e,t,s){try{return this.schemaValidator.validate(e,t)}catch(a){throw new r(`${s}: ${a instanceof Error?a.message:"Unknown error"}`,e,t,a instanceof Error?a:void 0)}}validateResponseData(e,t){return this.validateWithSchema(e,t,"Response schema validation failed")}validateSchema(e,t){return this.validateWithSchema(e,t,"Schema validation failed")}prepareHeaders(e={}){const t=new Headers;for(const[r,s]of Object.entries(this.defaultHeaders))null!=s&&t.set(r,String(s));for(const[r,s]of Object.entries(e))null!=s&&t.set(r,String(s));return t}extractHeaders(e){const t={};return e.forEach((e,r)=>{t[r]=e}),t}createHttpError(t,r,s,a,o,n){return new e(`Request failed with status code ${t.status}`,t.status,o||t.statusText,r,t,s,a,n)}async parseResponseBody(e,t){const r=e.headers.get("content-type")??"";try{if("text"===t.responseType)return await e.text();if("blob"===t.responseType)return await e.blob();if("arrayBuffer"===t.responseType)return await e.arrayBuffer();if(r.includes("application/json")){const t=await e.text();return t?JSON.parse(t):null}return await e.text()}catch(s){if(204===e.status)return;if(r.includes("application/json")&&s instanceof SyntaxError)throw new Error(`Failed to parse JSON response: ${s.message}`);throw s}}async processResponse(e,t,r,s){const a=this.extractHeaders(e.headers),n=t.validateStatus||(e=>e>=200&&e<300),i=await this.parseResponseBody(e,t);if(!n(e.status))throw this.createHttpError(e,i,s,r);const c={data:i,status:e.status,statusText:e.statusText,headers:a,method:r,url:s,raw:e};let d=c;const u=c.status;for(const l of this.responseInterceptors)try{d=await l(d)}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(d.status!==u&&!n(d.status))throw this.createHttpError(e,d.data,s,r,d.statusText);return d}mergeAbortSignals(e,t){if(e.aborted||t.aborted){const e=new AbortController;return e.abort(),{signal:e.signal}}const r=new AbortController,s=()=>{r.abort(),a()},a=()=>{e.removeEventListener("abort",s),t.removeEventListener("abort",s)};return e.addEventListener("abort",s),t.addEventListener("abort",s),{signal:r.signal,cleanup:a}}get(e,t){return this.request("GET",e,t||{})}post(e,t,r){return this.request("POST",e,{...r||{},body:t})}put(e,t,r){return this.request("PUT",e,{...r||{},body:t})}patch(e,t,r){return this.request("PATCH",e,{...r||{},body:t})}delete(e,t){return this.request("DELETE",e,t||{})}validatePathParams(e,t){if(!t){const t=this.extractRequiredPathParams(e);if(t.length>0)throw new a(`Missing required path parameters for URL "${e}": ${t.join(", ")}. Please provide pathParams: { ${t.map(e=>`${e}: value`).join(", ")} }`,e,t,[]);return}const r=this.extractRequiredPathParams(e),s=Object.keys(t),o=r.filter(e=>!s.includes(e));if(o.length>0)throw new a(`Missing required path parameters: ${o.join(", ")}. Provided: ${s.join(", ")}`,e,r,s)}extractRequiredPathParams(e){const t=e.match(/:([a-zA-Z0-9_]+)/g);return t?t.map(e=>e.slice(1)):[]}resolveUrl(e,t){this.validatePathParams(e,t);const r=t?h(e,t):e;if(/^https?:\/\//i.test(r))return r;const s=r.startsWith("/")?r.slice(1):r;return`${this.baseUrl}/${s}`}},exports.HttpError=e,exports.InterceptorError=o,exports.NetworkError=t,exports.PathParameterError=a,exports.SchemaValidationError=r,exports.SerializationError=n,exports.TimeoutError=s,exports.createSchemaValidator=u,exports.createStandardSchemaValidator=d,exports.generatePath=h,exports.isStandardSchema=i,exports.standardSchemaAdapter=c;
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){if(!t)return"";try{new URL(t)}catch{throw new Error(`Invalid baseUrl: "${t}". Must be a valid URL.`)}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))}async request(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){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;
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/schema.ts","../src/utils/path.ts","../src/client.ts"],"sourcesContent":["export 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 functions and types needed for Standard Schema support\nimport {\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\ntype ValidateNoOptionalParams<T extends string> =\n T extends `${string}:${string}?${string}`\n ? never // Optional parameters are not supported yet\n : T extends `${string}:${string}/${infer Rest}`\n ? ValidateNoOptionalParams<Rest>\n : T\n\ntype ExtractRouteParams<T extends string> =\n T extends `${string}:${infer Param}/${infer Rest}`\n ? Param | ExtractRouteParams<Rest>\n : T extends `${string}:${infer Param}`\n ? Param\n : never\n\nexport type HasRequiredParams<T extends string> =\n T extends `${string}:${string}` ? true : false\n\nexport type PathParams<Path extends string> =\n ValidateNoOptionalParams<Path> extends never\n ? never // Optional parameters are not supported yet\n : {\n [K in ExtractRouteParams<Path>]: string | number\n }\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 HttpClientOptions,\n HttpMethod,\n RequestContext,\n RequestInterceptor,\n RequestOptions,\n RequestParamsType,\n ResponseInterceptor,\n ResponseType,\n RetryOptions,\n Schema,\n TypedRequestOptions,\n} from './types'\nimport { generatePath, 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 if (!baseUrl) {\n return ''\n }\n\n try {\n new URL(baseUrl)\n } catch {\n throw new Error(`Invalid baseUrl: \"${baseUrl}\". Must be a valid URL.`)\n }\n\n return baseUrl.endsWith('/') ? baseUrl.slice(0, -1) : baseUrl\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 * Set a custom schema validator for request/response validation\n *\n * @param validator - The schema validator to use for validation\n *\n * @example\n * ```ts\n * // Set a custom validator\n * client.setSchemaValidator(customValidator);\n * ```\n */\n /**\n * Set a custom schema validator for the client.\n *\n * This allows you to use a different validation library or custom validation logic\n * for all requests made by this client instance.\n *\n * @param validator - The schema validator to use for all validation operations\n *\n * @example\n * ```ts\n * import { createCustomValidator } from './custom-validator'\n *\n * // Set a custom validator\n * client.setSchemaValidator(createCustomValidator());\n *\n * // Now all requests will use the custom validator\n * const response = await client.post('/users', userData, {\n * schema: customUserSchema\n * });\n * ```\n */\n public setSchemaValidator(validator: SchemaValidator): void {\n this.schemaValidator = validator\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 // Ensure we never return negative delays and have a minimum delay of 1ms\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\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 */\n public async 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 ): 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.validateResponseData<TResponse>(\n options.schema,\n responseData.data\n )\n }\n\n return responseData\n } catch (error) {\n // Check for timeout-related errors more comprehensively\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: string\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 private validateResponseData<T>(schema: Schema<T>, data: unknown): T {\n return this.validateWithSchema(\n schema,\n data,\n 'Response schema validation failed'\n )\n }\n\n /**\n * Public method to validate data against any schema\n *\n * @param schema - Schema to validate against\n * @param data - Data to validate\n * @returns Validated data\n *\n * @example\n * ```ts\n * const validatedUser = client.validateSchema(userSchema, userData);\n * ```\n */\n /**\n * Validate data against a schema using the configured schema validator.\n *\n * This method uses the same schema validator that's configured for the client,\n * ensuring consistent validation behavior across all requests.\n *\n * @template T - The expected type after validation\n * @param schema - The schema to validate against (Zod, Valibot, or Arktype)\n * @param data - The data to validate\n *\n * @returns The validated data with the correct type\n *\n * @throws {SchemaValidationError} If the data doesn't match the schema\n *\n * @example\n * ```ts\n * import { z } from 'zod'\n *\n * const userSchema = z.object({\n * id: z.string(),\n * name: z.string(),\n * email: z.email()\n * });\n *\n * // Validate data manually\n * try {\n * const validatedUser = client.validateSchema(userSchema, userData);\n * console.log('Valid user:', validatedUser);\n * } catch (error) {\n * console.error('Invalid user data:', error);\n * }\n *\n * // This is equivalent to the validation that happens automatically\n * // when you use schema in requests\n * ```\n */\n public validateSchema<T>(schema: Schema<T>, data: unknown): T {\n return this.validateWithSchema(schema, data, 'Schema validation failed')\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 // Check validateStatus first, before response.ok\n const validateStatus =\n options.validateStatus ||\n ((status: number) => status >= 200 && status < 300)\n\n // Parse response body once (for both success and error cases)\n const data = await this.parseResponseBody(response, options)\n\n // Check if this is an error response after parsing\n if (!validateStatus(response.status)) {\n throw this.createHttpError(response, data, url, method)\n }\n\n // Create response object with unknown data initially\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 // Apply response interceptors\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 * // JSON 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 * // Blob response\n * const response = await client.get('/avatar', {\n * responseType: 'blob',\n * schema: z.instanceof(Blob)\n * })\n *\n * @example\n * // Text response\n * const response = await client.get('/raw', {\n * responseType: 'text',\n * schema: z.string()\n * })\n */\n public get<\n TResponse,\n Path extends string = string,\n TParams extends RequestParamsType = RequestParamsType,\n >(\n url: Path,\n options: TypedRequestOptions<void, TResponse, TParams, Path> & {\n schema: Schema<TResponse>\n }\n ): Promise<ResponseType<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 public get<\n Path extends string = string,\n TParams extends RequestParamsType = RequestParamsType,\n >(\n url: Path,\n options?: Omit<TypedRequestOptions<void, unknown, TParams, Path>, 'schema'>\n ): Promise<ResponseType<unknown>>\n\n public get<\n TResponse,\n Path extends string = string,\n TParams extends RequestParamsType = RequestParamsType,\n >(\n url: Path,\n options?: TypedRequestOptions<void, TResponse, TParams, Path>\n ): Promise<ResponseType<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 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 TypedRequestOptions<TBody, TResponse, TParams, Path>,\n 'body'\n > & { schema: Schema<TResponse> }\n ): Promise<ResponseType<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 public post<\n Path extends string = string,\n TParams extends RequestParamsType = RequestParamsType,\n TBody = unknown,\n >(\n url: Path,\n body?: TBody,\n options?: Omit<\n TypedRequestOptions<TBody, unknown, TParams, Path>,\n 'body' | 'schema'\n >\n ): Promise<ResponseType<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<TypedRequestOptions<TBody, TResponse, TParams, Path>, 'body'>\n ): Promise<ResponseType<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 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 TypedRequestOptions<TBody, TResponse, TParams, Path>,\n 'body'\n > & { schema: Schema<TResponse> }\n ): Promise<ResponseType<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 public put<\n Path extends string = string,\n TParams extends RequestParamsType = RequestParamsType,\n TBody = unknown,\n >(\n url: Path,\n body?: TBody,\n options?: Omit<\n TypedRequestOptions<TBody, unknown, TParams, Path>,\n 'body' | 'schema'\n >\n ): Promise<ResponseType<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<TypedRequestOptions<TBody, TResponse, TParams, Path>, 'body'>\n ): Promise<ResponseType<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 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 TypedRequestOptions<TBody, TResponse, TParams, Path>,\n 'body'\n > & { schema: Schema<TResponse> }\n ): Promise<ResponseType<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 public patch<\n Path extends string = string,\n TParams extends RequestParamsType = RequestParamsType,\n TBody = unknown,\n >(\n url: Path,\n body?: TBody,\n options?: Omit<\n TypedRequestOptions<TBody, unknown, TParams, Path>,\n 'body' | 'schema'\n >\n ): Promise<ResponseType<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<TypedRequestOptions<TBody, TResponse, TParams, Path>, 'body'>\n ): Promise<ResponseType<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 public delete<\n TResponse,\n Path extends string = string,\n TParams extends RequestParamsType = RequestParamsType,\n >(\n url: Path,\n options: TypedRequestOptions<void, TResponse, TParams, Path> & {\n schema: Schema<TResponse>\n }\n ): Promise<ResponseType<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 public delete<\n Path extends string = string,\n TParams extends RequestParamsType = RequestParamsType,\n >(\n url: Path,\n options?: Omit<TypedRequestOptions<void, unknown, TParams, Path>, 'schema'>\n ): Promise<ResponseType<unknown>>\n\n public delete<\n TResponse,\n Path extends string = string,\n TParams extends RequestParamsType = RequestParamsType,\n >(\n url: Path,\n options?: TypedRequestOptions<void, TResponse, TParams, Path>\n ): Promise<ResponseType<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 // Check if URL contains required path parameters\n const requiredParams = this.extractRequiredPathParams(url)\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 // Validate that all required parameters are provided\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 const matches = url.match(/:([a-zA-Z0-9_]+)/g)\n if (!matches) return []\n\n return 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":["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","standardSchemaAdapter","parse","result","Promise","issues","errorMessages","Array","from","map","issue","join","value","createStandardSchemaValidator","isSchema","createSchemaValidator","createStdSchemaValidator","generatePath","path","params","replace","_match","paramName","Object","keys","String","DEFAULT_RETRY_OPTIONS","maxRetries","retryDelay","backoffFactor","retryStatusCodes","retryNetworkErrors","maxRetryDelay","shouldRetry","baseUrl","defaultHeaders","defaultTimeout","schemaValidator","requestInterceptors","responseInterceptors","defaultRetryOptions","options","URL","endsWith","slice","validateAndNormalizeBaseUrl","headers","timeout","retryOptions","addRequestInterceptor","interceptor","push","addResponseInterceptor","setSchemaValidator","validator","error","retryCount","getRetryOptions","retryError","console","warn","includes","getRetryDelay","baseDelay","Math","pow","cappedDelay","min","finalDelay","random","max","floor","sleep","ms","resolve","setTimeout","request","executeRequest","retry","delay","resolvedUrl","resolveUrl","pathParams","requestContext","prepareHeaders","body","fetchOptions","credentials","cache","mode","redirect","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","validateResponseData","DOMException","toLowerCase","clearTimeout","validateWithSchema","errorPrefix","validateSchema","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","test","startsWith"],"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 *\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 HttpClientOptions,\n HttpMethod,\n RequestContext,\n RequestInterceptor,\n RequestOptions,\n RequestParamsType,\n ResponseInterceptor,\n ResponseType,\n RetryOptions,\n Schema,\n TypedRequestOptions,\n} from './types'\nimport { generatePath, 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 if (!baseUrl) {\n return ''\n }\n\n try {\n new URL(baseUrl)\n } catch {\n throw new Error(`Invalid baseUrl: \"${baseUrl}\". Must be a valid URL.`)\n }\n\n return baseUrl.endsWith('/') ? baseUrl.slice(0, -1) : baseUrl\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\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 */\n public async 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 ): 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 * // JSON 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 * // Blob response\n * const response = await client.get('/avatar', {\n * responseType: 'blob',\n * schema: z.instanceof(Blob)\n * })\n *\n * @example\n * // Text response\n * const response = await client.get('/raw', {\n * responseType: 'text',\n * schema: z.string()\n * })\n */\n public get<\n TResponse,\n Path extends string = string,\n TParams extends RequestParamsType = RequestParamsType,\n >(\n url: Path,\n options: TypedRequestOptions<void, TResponse, TParams, Path> & {\n schema: Schema<TResponse>\n }\n ): Promise<ResponseType<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 public get<\n Path extends string = string,\n TParams extends RequestParamsType = RequestParamsType,\n >(\n url: Path,\n options?: Omit<TypedRequestOptions<void, unknown, TParams, Path>, 'schema'>\n ): Promise<ResponseType<unknown>>\n\n public get<\n TResponse,\n Path extends string = string,\n TParams extends RequestParamsType = RequestParamsType,\n >(\n url: Path,\n options?: TypedRequestOptions<void, TResponse, TParams, Path>\n ): Promise<ResponseType<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 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 TypedRequestOptions<TBody, TResponse, TParams, Path>,\n 'body'\n > & { schema: Schema<TResponse> }\n ): Promise<ResponseType<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 public post<\n Path extends string = string,\n TParams extends RequestParamsType = RequestParamsType,\n TBody = unknown,\n >(\n url: Path,\n body?: TBody,\n options?: Omit<\n TypedRequestOptions<TBody, unknown, TParams, Path>,\n 'body' | 'schema'\n >\n ): Promise<ResponseType<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<TypedRequestOptions<TBody, TResponse, TParams, Path>, 'body'>\n ): Promise<ResponseType<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 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 TypedRequestOptions<TBody, TResponse, TParams, Path>,\n 'body'\n > & { schema: Schema<TResponse> }\n ): Promise<ResponseType<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 public put<\n Path extends string = string,\n TParams extends RequestParamsType = RequestParamsType,\n TBody = unknown,\n >(\n url: Path,\n body?: TBody,\n options?: Omit<\n TypedRequestOptions<TBody, unknown, TParams, Path>,\n 'body' | 'schema'\n >\n ): Promise<ResponseType<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<TypedRequestOptions<TBody, TResponse, TParams, Path>, 'body'>\n ): Promise<ResponseType<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 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 TypedRequestOptions<TBody, TResponse, TParams, Path>,\n 'body'\n > & { schema: Schema<TResponse> }\n ): Promise<ResponseType<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 public patch<\n Path extends string = string,\n TParams extends RequestParamsType = RequestParamsType,\n TBody = unknown,\n >(\n url: Path,\n body?: TBody,\n options?: Omit<\n TypedRequestOptions<TBody, unknown, TParams, Path>,\n 'body' | 'schema'\n >\n ): Promise<ResponseType<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<TypedRequestOptions<TBody, TResponse, TParams, Path>, 'body'>\n ): Promise<ResponseType<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 public delete<\n TResponse,\n Path extends string = string,\n TParams extends RequestParamsType = RequestParamsType,\n >(\n url: Path,\n options: TypedRequestOptions<void, TResponse, TParams, Path> & {\n schema: Schema<TResponse>\n }\n ): Promise<ResponseType<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 public delete<\n Path extends string = string,\n TParams extends RequestParamsType = RequestParamsType,\n >(\n url: Path,\n options?: Omit<TypedRequestOptions<void, unknown, TParams, Path>, 'schema'>\n ): Promise<ResponseType<unknown>>\n\n public delete<\n TResponse,\n Path extends string = string,\n TParams extends RequestParamsType = RequestParamsType,\n >(\n url: Path,\n options?: TypedRequestOptions<void, TResponse, TParams, Path>\n ): Promise<ResponseType<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 const matches = url.match(/:([a-zA-Z0-9_]+)/g)\n if (!matches) return []\n\n return 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\ntype ValidateNoOptionalParams<T extends string> =\n T extends `${string}:${string}?${string}`\n ? never // Optional parameters are not supported yet\n : T extends `${string}:${string}/${infer Rest}`\n ? ValidateNoOptionalParams<Rest>\n : T\n\ntype ExtractRouteParams<T extends string> =\n T extends `${string}:${infer Param}/${infer Rest}`\n ? Param | ExtractRouteParams<Rest>\n : T extends `${string}:${infer Param}`\n ? Param\n : never\n\ntype HasRequiredParams<T extends string> = T extends `${string}:${string}`\n ? true\n : false\n\nexport type PathParams<Path extends string> =\n ValidateNoOptionalParams<Path> extends never\n ? never // Optional parameters are not supported yet\n : {\n [K in ExtractRouteParams<Path>]: string | number\n }\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","URL","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","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","replace","_match","paramName","generatePath","test","startsWith"],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1,59 +1,5 @@
1
- /**
2
- * Create a default schema validator that supports Standard Schema.
3
- *
4
- * This validator only works with schemas that implement the Standard Schema
5
- * interface. For full support of Zod, Valibot, and Arktype, use the
6
- * appropriate validator from their respective packages.
7
- *
8
- * @returns A schema validator instance
9
- *
10
- * @example
11
- * ```ts
12
- * import { createSchemaValidator } from '1000fetches'
13
- *
14
- * const validator = createSchemaValidator();
15
- *
16
- * // Use with HttpClient
17
- * const client = new HttpClient({
18
- * schemaValidator: validator
19
- * });
20
- * ```
21
- */
22
- export declare function createSchemaValidator(): SchemaValidator;
23
-
24
- /**
25
- * Creates a schema validator that supports Standard Schema V1 implementations
26
- *
27
- * Provides a validator that can work with any schema library that implements
28
- * the Standard Schema V1 specification, enabling interoperability between
29
- * different validation libraries.
30
- *
31
- * @returns SchemaValidator that supports Standard Schema V1
32
- *
33
- * @example
34
- * ```ts
35
- * const validator = createStandardSchemaValidator();
36
- * const client = new HttpClient({ schemaValidator: validator });
37
- * ```
38
- */
39
- export declare function createStandardSchemaValidator(): SchemaValidator;
40
-
41
1
  declare type ExtractRouteParams<T extends string> = T extends `${string}:${infer Param}/${infer Rest}` ? Param | ExtractRouteParams<Rest> : T extends `${string}:${infer Param}` ? Param : never;
42
2
 
43
- /**
44
- * Interpolates parameters into a URL template
45
- * Similar to React Router's generatePath function
46
- *
47
- * @example
48
- * ```ts
49
- * const path = generatePath('/users/:id/posts/:postId', { id: '123', postId: '456' });
50
- * // => '/users/123/posts/456'
51
- * ```
52
- */
53
- export declare function generatePath<Path extends string>(path: Path, params?: PathParams<Path>): string;
54
-
55
- declare type HasRequiredParams<T extends string> = T extends `${string}:${string}` ? true : false;
56
-
57
3
  /**
58
4
  * A modern, type-safe HTTP client with built-in schema validation, interceptors, retry logic, and compile-time path parameter validation.
59
5
  *
@@ -199,39 +145,6 @@ export declare class HttpClient {
199
145
  * ```
200
146
  */
201
147
  addResponseInterceptor(interceptor: ResponseInterceptor): void;
202
- /**
203
- * Set a custom schema validator for request/response validation
204
- *
205
- * @param validator - The schema validator to use for validation
206
- *
207
- * @example
208
- * ```ts
209
- * // Set a custom validator
210
- * client.setSchemaValidator(customValidator);
211
- * ```
212
- */
213
- /**
214
- * Set a custom schema validator for the client.
215
- *
216
- * This allows you to use a different validation library or custom validation logic
217
- * for all requests made by this client instance.
218
- *
219
- * @param validator - The schema validator to use for all validation operations
220
- *
221
- * @example
222
- * ```ts
223
- * import { createCustomValidator } from './custom-validator'
224
- *
225
- * // Set a custom validator
226
- * client.setSchemaValidator(createCustomValidator());
227
- *
228
- * // Now all requests will use the custom validator
229
- * const response = await client.post('/users', userData, {
230
- * schema: customUserSchema
231
- * });
232
- * ```
233
- */
234
- setSchemaValidator(validator: SchemaValidator): void;
235
148
  /**
236
149
  * Determines if a request should be retried based on error type and retry configuration
237
150
  *
@@ -295,56 +208,6 @@ export declare class HttpClient {
295
208
  */
296
209
  private executeRequest;
297
210
  private validateWithSchema;
298
- private validateResponseData;
299
- /**
300
- * Public method to validate data against any schema
301
- *
302
- * @param schema - Schema to validate against
303
- * @param data - Data to validate
304
- * @returns Validated data
305
- *
306
- * @example
307
- * ```ts
308
- * const validatedUser = client.validateSchema(userSchema, userData);
309
- * ```
310
- */
311
- /**
312
- * Validate data against a schema using the configured schema validator.
313
- *
314
- * This method uses the same schema validator that's configured for the client,
315
- * ensuring consistent validation behavior across all requests.
316
- *
317
- * @template T - The expected type after validation
318
- * @param schema - The schema to validate against (Zod, Valibot, or Arktype)
319
- * @param data - The data to validate
320
- *
321
- * @returns The validated data with the correct type
322
- *
323
- * @throws {SchemaValidationError} If the data doesn't match the schema
324
- *
325
- * @example
326
- * ```ts
327
- * import { z } from 'zod'
328
- *
329
- * const userSchema = z.object({
330
- * id: z.string(),
331
- * name: z.string(),
332
- * email: z.email()
333
- * });
334
- *
335
- * // Validate data manually
336
- * try {
337
- * const validatedUser = client.validateSchema(userSchema, userData);
338
- * console.log('Valid user:', validatedUser);
339
- * } catch (error) {
340
- * console.error('Invalid user data:', error);
341
- * }
342
- *
343
- * // This is equivalent to the validation that happens automatically
344
- * // when you use schema in requests
345
- * ```
346
- */
347
- validateSchema<T>(schema: Schema<T>, data: unknown): T;
348
211
  /**
349
212
  * Prepares headers for HTTP requests by merging default and custom headers
350
213
  *
@@ -554,25 +417,6 @@ export declare class InterceptorError extends Error implements HttpClientError {
554
417
  constructor(message: string, interceptorType: 'request' | 'response', url?: string, method?: string, cause?: Error);
555
418
  }
556
419
 
557
- /**
558
- * Type guard to check if an object conforms to the Standard Schema V1 specification
559
- *
560
- * Validates that an object has the required structure and properties
561
- * to be considered a valid Standard Schema implementation.
562
- *
563
- * @param obj - The object to check
564
- * @returns True if the object is a valid Standard Schema V1 implementation
565
- *
566
- * @example
567
- * ```ts
568
- * if (isStandardSchema(schema)) {
569
- * // Use the schema with type safety
570
- * const result = schema['~standard'].validate(data);
571
- * }
572
- * ```
573
- */
574
- export declare function isStandardSchema(obj: unknown): obj is StandardSchemaV1;
575
-
576
420
  export declare class NetworkError extends Error implements HttpClientError {
577
421
  readonly name = "NetworkError";
578
422
  readonly cause?: Error;
@@ -635,10 +479,6 @@ export declare interface RequestOptions<TBody = unknown> {
635
479
 
636
480
  declare type RequestParamsType = Record<string, string | number | boolean | undefined>;
637
481
 
638
- declare type RequirePathParams<Path extends string, T> = HasRequiredParams<Path> extends true ? T & {
639
- pathParams: PathParams<Path>;
640
- } : T;
641
-
642
482
  /**
643
483
  * Response interceptor function
644
484
  * Can modify response data after the request returns
@@ -689,7 +529,7 @@ export declare class SchemaValidationError extends Error implements HttpClientEr
689
529
  * This interface allows you to create custom schema validators that work
690
530
  * with different validation libraries (Zod, Valibot, Arktype, etc.).
691
531
  */
692
- export declare interface SchemaValidator {
532
+ declare interface SchemaValidator {
693
533
  /**
694
534
  * Validate data against a schema.
695
535
  *
@@ -715,32 +555,6 @@ export declare class SerializationError extends Error implements HttpClientError
715
555
  constructor(message: string, cause?: Error);
716
556
  }
717
557
 
718
- /**
719
- * Creates an adapter for Standard Schema V1 implementations
720
- *
721
- * Converts Standard Schema validation results into a format compatible
722
- * with the HTTP client's schema validation system.
723
- *
724
- * @param schema - The Standard Schema V1 implementation to adapt
725
- * @returns Adapter object with parse method
726
- *
727
- * @example
728
- * ```ts
729
- * const zodAdapter = standardSchemaAdapter(zodUserSchema);
730
- * const validatedUser = zodAdapter.parse(userData);
731
- * ```
732
- */
733
- export declare function standardSchemaAdapter<T>(schema: StandardSchemaV1<unknown, T>): {
734
- /**
735
- * Parses and validates data using the Standard Schema
736
- *
737
- * @param data - The data to validate
738
- * @returns The validated and typed data
739
- * @throws Error if validation fails
740
- */
741
- parse: (data: unknown) => T;
742
- };
743
-
744
558
  /**
745
559
  * Standard Schema V1 interface implementation
746
560
  *
@@ -749,7 +563,7 @@ export declare function standardSchemaAdapter<T>(schema: StandardSchemaV1<unknow
749
563
  *
750
564
  * @see https://github.com/standard-schema/standard-schema
751
565
  */
752
- export declare interface StandardSchemaV1<Input = unknown, Output = Input> {
566
+ declare interface StandardSchemaV1<Input = unknown, Output = Input> {
753
567
  /** The Standard Schema properties containing validation logic and metadata */
754
568
  readonly '~standard': StandardSchemaV1.Props<Input, Output>;
755
569
  }
@@ -760,14 +574,14 @@ export declare interface StandardSchemaV1<Input = unknown, Output = Input> {
760
574
  * Provides type-safe interfaces for schema validation results,
761
575
  * error handling, and type inference.
762
576
  */
763
- export declare namespace StandardSchemaV1 {
577
+ declare namespace StandardSchemaV1 {
764
578
  /**
765
579
  * Core properties interface for Standard Schema V1
766
580
  *
767
581
  * Contains the essential metadata and validation function
768
582
  * that every Standard Schema implementation must provide.
769
583
  */
770
- export interface Props<Input = unknown, Output = Input> {
584
+ interface Props<Input = unknown, Output = Input> {
771
585
  /** The version number of the Standard Schema specification */
772
586
  readonly version: 1;
773
587
  /** The name of the schema validation library (e.g., 'zod', 'valibot') */
@@ -788,13 +602,13 @@ export declare namespace StandardSchemaV1 {
788
602
  * Can be either a successful validation with the validated value,
789
603
  * or a failed validation with error details.
790
604
  */
791
- export type Result<Output> = SuccessResult<Output> | FailureResult;
605
+ type Result<Output> = SuccessResult<Output> | FailureResult;
792
606
  /**
793
607
  * Interface for successful validation results
794
608
  *
795
609
  * Contains the validated and typed output value.
796
610
  */
797
- export interface SuccessResult<Output> {
611
+ interface SuccessResult<Output> {
798
612
  /** The validated and typed output value */
799
613
  readonly value: Output;
800
614
  /** Undefined since validation succeeded */
@@ -805,7 +619,7 @@ export declare namespace StandardSchemaV1 {
805
619
  *
806
620
  * Contains detailed error information about validation failures.
807
621
  */
808
- export interface FailureResult {
622
+ interface FailureResult {
809
623
  /** Array of validation error details */
810
624
  readonly issues: ReadonlyArray<Issue>;
811
625
  }
@@ -815,7 +629,7 @@ export declare namespace StandardSchemaV1 {
815
629
  * Provides error message and optional path information
816
630
  * to help identify where validation failed.
817
631
  */
818
- export interface Issue {
632
+ interface Issue {
819
633
  /** Human-readable error message describing the validation failure */
820
634
  readonly message: string;
821
635
  /**
@@ -832,7 +646,7 @@ export declare namespace StandardSchemaV1 {
832
646
  * Used to provide detailed path information for validation failures
833
647
  * in complex nested structures.
834
648
  */
835
- export interface PathSegment {
649
+ interface PathSegment {
836
650
  /** The property key representing this path segment */
837
651
  readonly key: PropertyKey;
838
652
  }
@@ -842,7 +656,7 @@ export declare namespace StandardSchemaV1 {
842
656
  * Provides compile-time type information for input and output types
843
657
  * to enable better TypeScript integration and IntelliSense support.
844
658
  */
845
- export interface Types<Input = unknown, Output = Input> {
659
+ interface Types<Input = unknown, Output = Input> {
846
660
  /** The input type that the schema expects */
847
661
  readonly input: Input;
848
662
  /** The output type that the schema produces after validation */
@@ -858,7 +672,7 @@ export declare namespace StandardSchemaV1 {
858
672
  * type UserInput = StandardSchemaV1.InferInput<typeof userSchema>
859
673
  * ```
860
674
  */
861
- export type InferInput<Schema extends StandardSchemaV1> = NonNullable<Schema['~standard']['types']>['input'];
675
+ type InferInput<Schema extends StandardSchemaV1> = NonNullable<Schema['~standard']['types']>['input'];
862
676
  /**
863
677
  * Type utility to infer the output type from a Standard Schema
864
678
  *
@@ -869,18 +683,16 @@ export declare namespace StandardSchemaV1 {
869
683
  * type UserOutput = StandardSchemaV1.InferOutput<typeof userSchema>
870
684
  * ```
871
685
  */
872
- export type InferOutput<Schema extends StandardSchemaV1> = NonNullable<Schema['~standard']['types']>['output'];
686
+ type InferOutput<Schema extends StandardSchemaV1> = NonNullable<Schema['~standard']['types']>['output'];
873
687
  }
874
688
 
875
- export declare type StrictTypedRequestOptions<TBody = unknown, TResponse = unknown, TParams extends RequestParamsType = RequestParamsType, Path extends string = string> = RequirePathParams<Path, TypedRequestOptions<TBody, TResponse, TParams, Path>>;
876
-
877
689
  export declare class TimeoutError extends Error implements HttpClientError {
878
690
  readonly name = "TimeoutError";
879
691
  readonly cause?: Error;
880
692
  constructor(message: string, cause?: Error);
881
693
  }
882
694
 
883
- export declare interface TypedRequestOptions<TBody = unknown, TResponse = unknown, TParams extends RequestParamsType = RequestParamsType, Path extends string = string> extends Omit<RequestOptions<TBody>, 'params'> {
695
+ declare interface TypedRequestOptions<TBody = unknown, TResponse = unknown, TParams extends RequestParamsType = RequestParamsType, Path extends string = string> extends Omit<RequestOptions<TBody>, 'params'> {
884
696
  params?: TParams;
885
697
  schema?: Schema<TResponse>;
886
698
  pathParams?: PathParams<Path>;
package/dist/index.es.js CHANGED
@@ -306,41 +306,6 @@ class HttpClient {
306
306
  addResponseInterceptor(interceptor) {
307
307
  this.responseInterceptors.push(interceptor);
308
308
  }
309
- /**
310
- * Set a custom schema validator for request/response validation
311
- *
312
- * @param validator - The schema validator to use for validation
313
- *
314
- * @example
315
- * ```ts
316
- * // Set a custom validator
317
- * client.setSchemaValidator(customValidator);
318
- * ```
319
- */
320
- /**
321
- * Set a custom schema validator for the client.
322
- *
323
- * This allows you to use a different validation library or custom validation logic
324
- * for all requests made by this client instance.
325
- *
326
- * @param validator - The schema validator to use for all validation operations
327
- *
328
- * @example
329
- * ```ts
330
- * import { createCustomValidator } from './custom-validator'
331
- *
332
- * // Set a custom validator
333
- * client.setSchemaValidator(createCustomValidator());
334
- *
335
- * // Now all requests will use the custom validator
336
- * const response = await client.post('/users', userData, {
337
- * schema: customUserSchema
338
- * });
339
- * ```
340
- */
341
- setSchemaValidator(validator) {
342
- this.schemaValidator = validator;
343
- }
344
309
  /**
345
310
  * Determines if a request should be retried based on error type and retry configuration
346
311
  *
@@ -567,7 +532,7 @@ class HttpClient {
567
532
  resolvedUrl
568
533
  );
569
534
  if (options.schema) {
570
- responseData.data = this.validateResponseData(
535
+ responseData.data = this.validateWithSchema(
571
536
  options.schema,
572
537
  responseData.data
573
538
  );
@@ -592,7 +557,7 @@ class HttpClient {
592
557
  cleanupSignals?.();
593
558
  }
594
559
  }
595
- validateWithSchema(schema, data, errorPrefix) {
560
+ validateWithSchema(schema, data, errorPrefix = "Response schema validation failed") {
596
561
  try {
597
562
  return this.schemaValidator.validate(schema, data);
598
563
  } catch (error) {
@@ -604,64 +569,6 @@ class HttpClient {
604
569
  );
605
570
  }
606
571
  }
607
- validateResponseData(schema, data) {
608
- return this.validateWithSchema(
609
- schema,
610
- data,
611
- "Response schema validation failed"
612
- );
613
- }
614
- /**
615
- * Public method to validate data against any schema
616
- *
617
- * @param schema - Schema to validate against
618
- * @param data - Data to validate
619
- * @returns Validated data
620
- *
621
- * @example
622
- * ```ts
623
- * const validatedUser = client.validateSchema(userSchema, userData);
624
- * ```
625
- */
626
- /**
627
- * Validate data against a schema using the configured schema validator.
628
- *
629
- * This method uses the same schema validator that's configured for the client,
630
- * ensuring consistent validation behavior across all requests.
631
- *
632
- * @template T - The expected type after validation
633
- * @param schema - The schema to validate against (Zod, Valibot, or Arktype)
634
- * @param data - The data to validate
635
- *
636
- * @returns The validated data with the correct type
637
- *
638
- * @throws {SchemaValidationError} If the data doesn't match the schema
639
- *
640
- * @example
641
- * ```ts
642
- * import { z } from 'zod'
643
- *
644
- * const userSchema = z.object({
645
- * id: z.string(),
646
- * name: z.string(),
647
- * email: z.email()
648
- * });
649
- *
650
- * // Validate data manually
651
- * try {
652
- * const validatedUser = client.validateSchema(userSchema, userData);
653
- * console.log('Valid user:', validatedUser);
654
- * } catch (error) {
655
- * console.error('Invalid user data:', error);
656
- * }
657
- *
658
- * // This is equivalent to the validation that happens automatically
659
- * // when you use schema in requests
660
- * ```
661
- */
662
- validateSchema(schema, data) {
663
- return this.validateWithSchema(schema, data, "Schema validation failed");
664
- }
665
572
  /**
666
573
  * Prepares headers for HTTP requests by merging default and custom headers
667
574
  *
@@ -909,11 +816,6 @@ export {
909
816
  PathParameterError,
910
817
  SchemaValidationError,
911
818
  SerializationError,
912
- TimeoutError,
913
- createSchemaValidator,
914
- createStandardSchemaValidator,
915
- generatePath,
916
- isStandardSchema,
917
- standardSchemaAdapter
819
+ TimeoutError
918
820
  };
919
821
  //# sourceMappingURL=index.es.js.map
@@ -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":["export 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 functions and types needed for Standard Schema support\nimport {\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\ntype ValidateNoOptionalParams<T extends string> =\n T extends `${string}:${string}?${string}`\n ? never // Optional parameters are not supported yet\n : T extends `${string}:${string}/${infer Rest}`\n ? ValidateNoOptionalParams<Rest>\n : T\n\ntype ExtractRouteParams<T extends string> =\n T extends `${string}:${infer Param}/${infer Rest}`\n ? Param | ExtractRouteParams<Rest>\n : T extends `${string}:${infer Param}`\n ? Param\n : never\n\nexport type HasRequiredParams<T extends string> =\n T extends `${string}:${string}` ? true : false\n\nexport type PathParams<Path extends string> =\n ValidateNoOptionalParams<Path> extends never\n ? never // Optional parameters are not supported yet\n : {\n [K in ExtractRouteParams<Path>]: string | number\n }\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 HttpClientOptions,\n HttpMethod,\n RequestContext,\n RequestInterceptor,\n RequestOptions,\n RequestParamsType,\n ResponseInterceptor,\n ResponseType,\n RetryOptions,\n Schema,\n TypedRequestOptions,\n} from './types'\nimport { generatePath, 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 if (!baseUrl) {\n return ''\n }\n\n try {\n new URL(baseUrl)\n } catch {\n throw new Error(`Invalid baseUrl: \"${baseUrl}\". Must be a valid URL.`)\n }\n\n return baseUrl.endsWith('/') ? baseUrl.slice(0, -1) : baseUrl\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 * Set a custom schema validator for request/response validation\n *\n * @param validator - The schema validator to use for validation\n *\n * @example\n * ```ts\n * // Set a custom validator\n * client.setSchemaValidator(customValidator);\n * ```\n */\n /**\n * Set a custom schema validator for the client.\n *\n * This allows you to use a different validation library or custom validation logic\n * for all requests made by this client instance.\n *\n * @param validator - The schema validator to use for all validation operations\n *\n * @example\n * ```ts\n * import { createCustomValidator } from './custom-validator'\n *\n * // Set a custom validator\n * client.setSchemaValidator(createCustomValidator());\n *\n * // Now all requests will use the custom validator\n * const response = await client.post('/users', userData, {\n * schema: customUserSchema\n * });\n * ```\n */\n public setSchemaValidator(validator: SchemaValidator): void {\n this.schemaValidator = validator\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 // Ensure we never return negative delays and have a minimum delay of 1ms\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\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 */\n public async 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 ): 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.validateResponseData<TResponse>(\n options.schema,\n responseData.data\n )\n }\n\n return responseData\n } catch (error) {\n // Check for timeout-related errors more comprehensively\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: string\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 private validateResponseData<T>(schema: Schema<T>, data: unknown): T {\n return this.validateWithSchema(\n schema,\n data,\n 'Response schema validation failed'\n )\n }\n\n /**\n * Public method to validate data against any schema\n *\n * @param schema - Schema to validate against\n * @param data - Data to validate\n * @returns Validated data\n *\n * @example\n * ```ts\n * const validatedUser = client.validateSchema(userSchema, userData);\n * ```\n */\n /**\n * Validate data against a schema using the configured schema validator.\n *\n * This method uses the same schema validator that's configured for the client,\n * ensuring consistent validation behavior across all requests.\n *\n * @template T - The expected type after validation\n * @param schema - The schema to validate against (Zod, Valibot, or Arktype)\n * @param data - The data to validate\n *\n * @returns The validated data with the correct type\n *\n * @throws {SchemaValidationError} If the data doesn't match the schema\n *\n * @example\n * ```ts\n * import { z } from 'zod'\n *\n * const userSchema = z.object({\n * id: z.string(),\n * name: z.string(),\n * email: z.email()\n * });\n *\n * // Validate data manually\n * try {\n * const validatedUser = client.validateSchema(userSchema, userData);\n * console.log('Valid user:', validatedUser);\n * } catch (error) {\n * console.error('Invalid user data:', error);\n * }\n *\n * // This is equivalent to the validation that happens automatically\n * // when you use schema in requests\n * ```\n */\n public validateSchema<T>(schema: Schema<T>, data: unknown): T {\n return this.validateWithSchema(schema, data, 'Schema validation failed')\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 // Check validateStatus first, before response.ok\n const validateStatus =\n options.validateStatus ||\n ((status: number) => status >= 200 && status < 300)\n\n // Parse response body once (for both success and error cases)\n const data = await this.parseResponseBody(response, options)\n\n // Check if this is an error response after parsing\n if (!validateStatus(response.status)) {\n throw this.createHttpError(response, data, url, method)\n }\n\n // Create response object with unknown data initially\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 // Apply response interceptors\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 * // JSON 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 * // Blob response\n * const response = await client.get('/avatar', {\n * responseType: 'blob',\n * schema: z.instanceof(Blob)\n * })\n *\n * @example\n * // Text response\n * const response = await client.get('/raw', {\n * responseType: 'text',\n * schema: z.string()\n * })\n */\n public get<\n TResponse,\n Path extends string = string,\n TParams extends RequestParamsType = RequestParamsType,\n >(\n url: Path,\n options: TypedRequestOptions<void, TResponse, TParams, Path> & {\n schema: Schema<TResponse>\n }\n ): Promise<ResponseType<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 public get<\n Path extends string = string,\n TParams extends RequestParamsType = RequestParamsType,\n >(\n url: Path,\n options?: Omit<TypedRequestOptions<void, unknown, TParams, Path>, 'schema'>\n ): Promise<ResponseType<unknown>>\n\n public get<\n TResponse,\n Path extends string = string,\n TParams extends RequestParamsType = RequestParamsType,\n >(\n url: Path,\n options?: TypedRequestOptions<void, TResponse, TParams, Path>\n ): Promise<ResponseType<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 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 TypedRequestOptions<TBody, TResponse, TParams, Path>,\n 'body'\n > & { schema: Schema<TResponse> }\n ): Promise<ResponseType<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 public post<\n Path extends string = string,\n TParams extends RequestParamsType = RequestParamsType,\n TBody = unknown,\n >(\n url: Path,\n body?: TBody,\n options?: Omit<\n TypedRequestOptions<TBody, unknown, TParams, Path>,\n 'body' | 'schema'\n >\n ): Promise<ResponseType<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<TypedRequestOptions<TBody, TResponse, TParams, Path>, 'body'>\n ): Promise<ResponseType<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 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 TypedRequestOptions<TBody, TResponse, TParams, Path>,\n 'body'\n > & { schema: Schema<TResponse> }\n ): Promise<ResponseType<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 public put<\n Path extends string = string,\n TParams extends RequestParamsType = RequestParamsType,\n TBody = unknown,\n >(\n url: Path,\n body?: TBody,\n options?: Omit<\n TypedRequestOptions<TBody, unknown, TParams, Path>,\n 'body' | 'schema'\n >\n ): Promise<ResponseType<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<TypedRequestOptions<TBody, TResponse, TParams, Path>, 'body'>\n ): Promise<ResponseType<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 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 TypedRequestOptions<TBody, TResponse, TParams, Path>,\n 'body'\n > & { schema: Schema<TResponse> }\n ): Promise<ResponseType<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 public patch<\n Path extends string = string,\n TParams extends RequestParamsType = RequestParamsType,\n TBody = unknown,\n >(\n url: Path,\n body?: TBody,\n options?: Omit<\n TypedRequestOptions<TBody, unknown, TParams, Path>,\n 'body' | 'schema'\n >\n ): Promise<ResponseType<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<TypedRequestOptions<TBody, TResponse, TParams, Path>, 'body'>\n ): Promise<ResponseType<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 public delete<\n TResponse,\n Path extends string = string,\n TParams extends RequestParamsType = RequestParamsType,\n >(\n url: Path,\n options: TypedRequestOptions<void, TResponse, TParams, Path> & {\n schema: Schema<TResponse>\n }\n ): Promise<ResponseType<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 public delete<\n Path extends string = string,\n TParams extends RequestParamsType = RequestParamsType,\n >(\n url: Path,\n options?: Omit<TypedRequestOptions<void, unknown, TParams, Path>, 'schema'>\n ): Promise<ResponseType<unknown>>\n\n public delete<\n TResponse,\n Path extends string = string,\n TParams extends RequestParamsType = RequestParamsType,\n >(\n url: Path,\n options?: TypedRequestOptions<void, TResponse, TParams, Path>\n ): Promise<ResponseType<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 // Check if URL contains required path parameters\n const requiredParams = this.extractRequiredPathParams(url)\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 // Validate that all required parameters are provided\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 const matches = url.match(/:([a-zA-Z0-9_]+)/g)\n if (!matches) return []\n\n return 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 *\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\ntype ValidateNoOptionalParams<T extends string> =\n T extends `${string}:${string}?${string}`\n ? never // Optional parameters are not supported yet\n : T extends `${string}:${string}/${infer Rest}`\n ? ValidateNoOptionalParams<Rest>\n : T\n\ntype ExtractRouteParams<T extends string> =\n T extends `${string}:${infer Param}/${infer Rest}`\n ? Param | ExtractRouteParams<Rest>\n : T extends `${string}:${infer Param}`\n ? Param\n : never\n\ntype HasRequiredParams<T extends string> = T extends `${string}:${string}`\n ? true\n : false\n\nexport type PathParams<Path extends string> =\n ValidateNoOptionalParams<Path> extends never\n ? never // Optional parameters are not supported yet\n : {\n [K in ExtractRouteParams<Path>]: string | number\n }\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 HttpClientOptions,\n HttpMethod,\n RequestContext,\n RequestInterceptor,\n RequestOptions,\n RequestParamsType,\n ResponseInterceptor,\n ResponseType,\n RetryOptions,\n Schema,\n TypedRequestOptions,\n} from './types'\nimport { generatePath, 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 if (!baseUrl) {\n return ''\n }\n\n try {\n new URL(baseUrl)\n } catch {\n throw new Error(`Invalid baseUrl: \"${baseUrl}\". Must be a valid URL.`)\n }\n\n return baseUrl.endsWith('/') ? baseUrl.slice(0, -1) : baseUrl\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\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 */\n public async 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 ): 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 * // JSON 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 * // Blob response\n * const response = await client.get('/avatar', {\n * responseType: 'blob',\n * schema: z.instanceof(Blob)\n * })\n *\n * @example\n * // Text response\n * const response = await client.get('/raw', {\n * responseType: 'text',\n * schema: z.string()\n * })\n */\n public get<\n TResponse,\n Path extends string = string,\n TParams extends RequestParamsType = RequestParamsType,\n >(\n url: Path,\n options: TypedRequestOptions<void, TResponse, TParams, Path> & {\n schema: Schema<TResponse>\n }\n ): Promise<ResponseType<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 public get<\n Path extends string = string,\n TParams extends RequestParamsType = RequestParamsType,\n >(\n url: Path,\n options?: Omit<TypedRequestOptions<void, unknown, TParams, Path>, 'schema'>\n ): Promise<ResponseType<unknown>>\n\n public get<\n TResponse,\n Path extends string = string,\n TParams extends RequestParamsType = RequestParamsType,\n >(\n url: Path,\n options?: TypedRequestOptions<void, TResponse, TParams, Path>\n ): Promise<ResponseType<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 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 TypedRequestOptions<TBody, TResponse, TParams, Path>,\n 'body'\n > & { schema: Schema<TResponse> }\n ): Promise<ResponseType<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 public post<\n Path extends string = string,\n TParams extends RequestParamsType = RequestParamsType,\n TBody = unknown,\n >(\n url: Path,\n body?: TBody,\n options?: Omit<\n TypedRequestOptions<TBody, unknown, TParams, Path>,\n 'body' | 'schema'\n >\n ): Promise<ResponseType<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<TypedRequestOptions<TBody, TResponse, TParams, Path>, 'body'>\n ): Promise<ResponseType<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 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 TypedRequestOptions<TBody, TResponse, TParams, Path>,\n 'body'\n > & { schema: Schema<TResponse> }\n ): Promise<ResponseType<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 public put<\n Path extends string = string,\n TParams extends RequestParamsType = RequestParamsType,\n TBody = unknown,\n >(\n url: Path,\n body?: TBody,\n options?: Omit<\n TypedRequestOptions<TBody, unknown, TParams, Path>,\n 'body' | 'schema'\n >\n ): Promise<ResponseType<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<TypedRequestOptions<TBody, TResponse, TParams, Path>, 'body'>\n ): Promise<ResponseType<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 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 TypedRequestOptions<TBody, TResponse, TParams, Path>,\n 'body'\n > & { schema: Schema<TResponse> }\n ): Promise<ResponseType<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 public patch<\n Path extends string = string,\n TParams extends RequestParamsType = RequestParamsType,\n TBody = unknown,\n >(\n url: Path,\n body?: TBody,\n options?: Omit<\n TypedRequestOptions<TBody, unknown, TParams, Path>,\n 'body' | 'schema'\n >\n ): Promise<ResponseType<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<TypedRequestOptions<TBody, TResponse, TParams, Path>, 'body'>\n ): Promise<ResponseType<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 public delete<\n TResponse,\n Path extends string = string,\n TParams extends RequestParamsType = RequestParamsType,\n >(\n url: Path,\n options: TypedRequestOptions<void, TResponse, TParams, Path> & {\n schema: Schema<TResponse>\n }\n ): Promise<ResponseType<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 public delete<\n Path extends string = string,\n TParams extends RequestParamsType = RequestParamsType,\n >(\n url: Path,\n options?: Omit<TypedRequestOptions<void, unknown, TParams, Path>, 'schema'>\n ): Promise<ResponseType<unknown>>\n\n public delete<\n TResponse,\n Path extends string = string,\n TParams extends RequestParamsType = RequestParamsType,\n >(\n url: Path,\n options?: TypedRequestOptions<void, TResponse, TParams, Path>\n ): Promise<ResponseType<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 const matches = url.match(/:([a-zA-Z0-9_]+)/g)\n if (!matches) return []\n\n return 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.1",
3
+ "version": "0.1.2",
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,20 +54,19 @@
54
54
  },
55
55
  "homepage": "https://github.com/your-username/1000fetches#readme",
56
56
  "devDependencies": {
57
- "@types/node": "22.18.6",
58
- "@vitejs/plugin-react": "4.7.0",
57
+ "@types/node": "22.18.8",
59
58
  "@vitest/coverage-v8": "3.2.4",
60
59
  "arktype": "2.1.22",
61
60
  "expect-type": "1.2.2",
62
61
  "msw": "2.11.3",
63
- "rollup-plugin-visualizer": "6.0.3",
62
+ "rollup-plugin-visualizer": "6.0.4",
64
63
  "terser": "5.44.0",
65
- "typescript": "5.9.2",
64
+ "typescript": "5.9.3",
66
65
  "valibot": "1.1.0",
67
- "vite": "7.1.7",
66
+ "vite": "7.1.9",
68
67
  "vite-plugin-dts": "4.5.4",
69
68
  "vitest": "3.2.4",
70
- "zod": "4.1.11"
69
+ "zod": "4.1.12"
71
70
  },
72
71
  "peerDependencies": {
73
72
  "arktype": "^2.0.0",