1000fetches 0.2.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs.js +1 -1
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.es.js +6 -0
- package/dist/index.es.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});class e extends Error{name="HttpError";status;statusText;data;response;url;method;cause;constructor(e,t,r,a,n,s,o,i){const c=t>=500?"Server Error":t>=400?"Client Error":t>=300?"Redirect":"Success",d=a?JSON.stringify(a):"No response data";super(`HTTP ${c} (${t}): ${e}\nRequest: ${o} ${s}\nData: ${d.length>500?d.substring(0,500)+"...":d}`,{cause:i}),this.status=t,this.statusText=r,this.data=a,this.response=n,this.url=s,this.method=o}}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,a){super(e,{cause:a}),this.schema=t,this.data=r}}class a extends Error{name="TimeoutError";cause;constructor(e,t){super(e,{cause:t})}}class n extends Error{name="PathParameterError";url;requiredParams;providedParams;cause;constructor(e,t,r,a,n){super(`${e}\nURL Template: ${t}\nExpected: [${r.map(e=>`"${e}"`).join(", ")}], Actual: [${a.map(e=>`"${e}"`).join(", ")}]`,{cause:n}),this.url=t,this.requiredParams=r,this.providedParams=a}}class s extends Error{name="MiddlewareError";type;url;method;cause;constructor(e,t,r,a,n){const s=r?`Request: ${a||"UNKNOWN"} ${r}`:"";super(s?`${e}\n${s}`:e,{cause:n}),this.type=t,this.url=r,this.method=a}}class o extends Error{name="SerializationError";cause;constructor(e,t){super(e,{cause:t})}}class i extends Error{name="InvalidSchemaError";schema;cause;constructor(e,t,r){super(e,{cause:r}),this.schema=t}}class c extends Error{name="AsyncSchemaValidationError";schema;cause;constructor(e,t,r){super(e,{cause:r}),this.schema=t}}class d extends Error{name="InvalidBaseUrlError";baseUrl;cause;constructor(e,t,r){super(`${e}\nBase URL: ${t}`,{cause:r}),this.baseUrl=t}}function u(e,t,r,a){let n=0,s=!1,o=!1;const i=()=>{if(!s){s=!0;try{e.releaseLock()}catch{}}},c=()=>{o=!0,i()};return a?.addEventListener("abort",c),new ReadableStream({async start(s){try{for(;!o;){const{done:a,value:o}=await e.read();if(a)break;n+=o.length,t(o,r,n),s.enqueue(o)}o||s.close()}catch(d){throw o||s.error(d),d}finally{a?.removeEventListener("abort",c),i()}},cancel(){o=!0,a?.removeEventListener("abort",c),i()}})}async function l(e,t){if(!t||!e.body)return e;if(!e.body.getReader)return e;const r=u(e.body.getReader(),(e,r,a)=>{t({chunk:e,totalBytes:r,transferredBytes:a})},e.headers.get("content-length")?parseInt(e.headers.get("content-length")||"0",10):void 0,e.signal);return new Request(e.url,{method:e.method,headers:e.headers,body:r,signal:e.signal,credentials:e.credentials,cache:e.cache,mode:e.mode,redirect:e.redirect,referrer:e.referrer,referrerPolicy:e.referrerPolicy,integrity:e.integrity,keepalive:e.keepalive,duplex:"half"})}async function h(e,t){if(!t||!e.body)return e;if(!e.body.getReader)return e;const r=u(e.body.getReader(),(e,r,a)=>{t({chunk:e,totalBytes:r,transferredBytes:a})},e.headers.get("content-length")?parseInt(e.headers.get("content-length")||"0",10):void 0);return new Response(r,{status:e.status,statusText:e.statusText,headers:e.headers})}const f={maxRetries:3,retryDelay:300,backoffFactor:2,retryStatusCodes:[429,500,502,503,504],retryNetworkErrors:!0,maxRetryDelay:3e4,shouldRetry:()=>!0};function p(e={}){const{baseUrl:t="",headers:r={},timeout:o=3e4,fetch:i=fetch,serializeBody:c,serializeParams:d,onRequestMiddleware:u,onResponseMiddleware:p}=e;return async function(S,R={}){const{method:$="GET",headers:T={},params:P,pathParams:U,body:j,timeout:O=o,signal:L,credentials:k,cache:A,mode:q,redirect:N,onUploadStreaming:B,onDownloadStreaming:D,responseType:M,retryOptions:C}=R;let H,I=function(e,t={}){return e.replace(/:([^/\s?#]+)\??/g,(r,a)=>{if(!/^[a-zA-Z0-9_]+$/.test(a))throw new n(`Invalid path parameter name: "${a}"`,e,[a],Object.keys(t));const s=t[a];if(void 0===s)throw new n(`Missing required path parameter: "${a}"`,e,[a],Object.keys(t));const o=String(s);if(o.includes("/")||o.includes("?"))throw new n(`Invalid path parameter value for "${a}": contains invalid characters`,e,[a],Object.keys(t));return o})}(S,U);(t||P)&&(t?(I=function(e,t){if(t.startsWith("http://")||t.startsWith("https://"))return t;const r=new URL(e),a=r.pathname.replace(/\/$/,""),[n,s]=t.split("?");t.startsWith("/")?r.pathname=a+n:t&&(r.pathname=a+"/"+n);s&&(r.search=r.search?`${r.search}&${s}`:`?${s}`);return r.toString()}(t,I),H=new URL(I)):H=new URL(I));const W={url:I,method:$,params:P,headers:new Headers({...r,...T}),body:j,signal:L,fetchOptions:{credentials:k,cache:A,mode:q,redirect:N}};let z=W;if(u)try{const e={...W,headers:new Headers(W.headers),fetchOptions:{...W.fetchOptions}};z=await u(e),z.url!==I&&(H=new URL(z.url))}catch(G){throw new s(g("Request middleware failed",G),"request",z.url,z.method,v(G,"Request middleware"))}if(z.params){H||(H=new URL(z.url));const e=d?d(z.params):function(e){const t=new URLSearchParams;for(const[r,a]of Object.entries(e))if(Array.isArray(a))for(const e of a)null!=e&&t.append(r,String(e));else null!=a&&t.append(r,String(a));return t.toString()}(z.params);if(e){if(d){const t=e.startsWith("?")?e.slice(1):e,r=H.search?"&":"?";H.search+=r+t}else{const t=new URLSearchParams(e);for(const[e,r]of t)H.searchParams.append(e,r)}z.url=H.toString()}}const J={method:z.method,headers:z.headers,...z.fetchOptions};if(void 0!==z.body&&("POST"===z.method||"PUT"===z.method||"PATCH"===z.method)){let e,t;if(c){const r=c(z.body);null==r?e="":(e=r,b(z.body)&&"string"==typeof r&&!z.headers.has("content-type")&&(t="application/json"))}else{const r=function(e){if("string"==typeof e||e instanceof FormData||e instanceof URLSearchParams||e instanceof ArrayBuffer||e instanceof Blob||e instanceof ReadableStream)return{body:e};if(b(e))return{body:JSON.stringify(e),contentType:"application/json"};if(null==e)return{body:""};return{body:String(e)}}(z.body);e=r.body,t=r.contentType}J.body=e,t&&z.headers.set("content-type",t),J.duplex="half"}const V={...f,...e.retryOptions,...C},F=V.maxRetries;let _;for(let e=0;e<=F;e+=1){const t=new AbortController,r=setTimeout(()=>t.abort(),O),n=x(z.signal,t.signal,()=>clearTimeout(r));try{const e=new Request(z.url,J),t=B?await l(e,B):e,r=await i(t.url,{method:t.method,headers:t.headers,body:t.body,signal:n,...z.fetchOptions,...t.body&&{duplex:"half"}}),a=D?await h(r,D):r,o=await m(a,{responseType:M,method:$,url:z.url});if(p)try{const e=await p(o);if(!e||"object"!=typeof e||!("data"in e))throw new s("Response middleware must return a valid ResponseType object","response",z.url,$);return e}catch(G){throw new s(g("Response middleware failed",G),"response",z.url,$,v(G,"Response middleware"))}return o}catch(G){if(clearTimeout(r),_=v(G,"Request execution"),"AbortError"===_.name&&(_=new a(`Request timeout after ${O}ms`,_)),e>=F||!(await y(_,e,V)))throw _;const t=w(e,V);await E(t)}}throw new Error("Retry loop terminated unexpectedly")}}async function m(t,r){const a=Object.fromEntries(t.headers.entries());let n;try{const e=r.responseType,a=t.headers.get("content-type")??"",s=a.includes("application/json")?"json":a.includes("text/")?"text":a.includes("application/octet-stream")||a.includes("application/pdf")||a.includes("image/")||a.includes("video/")||a.includes("audio/")?"arrayBuffer":a.includes("multipart/form-data")||a.includes("application/x-www-form-urlencoded")?"formData":void 0,o=e??s;if("json"===o)n=await t.json();else if("text"===o)n=await t.text();else if("blob"===o)n=await t.blob();else if("arrayBuffer"===o)n=await t.arrayBuffer();else if("formData"===o)n=await t.formData();else{const e=t.clone();try{n=await t.json()}catch{n=await e.text()}}}catch(s){throw new o(g("Failed to parse response body",s),s instanceof Error?s:void 0)}if(!t.ok)throw new e(`HTTP ${t.status} ${t.statusText}`,t.status,t.statusText,n,t,r.url,r.method);return{data:n,status:t.status,statusText:t.statusText,headers:a,method:r.method,url:r.url,raw:t}}async function y(r,a,n){return!!n&&(n.shouldRetry?await n.shouldRetry(r,a):r instanceof e?n.retryStatusCodes?.includes(r.status)??!1:(r instanceof t||"TypeError"===r.name)&&(n.retryNetworkErrors??!1))}function w(e,t){if(!t)return 0;const r=t.retryDelay??300,a=t.backoffFactor??2,n=t.maxRetryDelay??3e4,s=r*Math.pow(a,e);return Math.min(s,n)}function b(e){return null!==e&&"object"==typeof e&&"Object"===e.constructor?.name||Array.isArray(e)||null!==e&&"object"==typeof e&&"toJSON"in e&&"function"==typeof e.toJSON}function g(e,t){return`${e}: ${t instanceof Error?t.message:String(t)}`}function E(e){return new Promise(t=>setTimeout(t,e))}function x(e,t,r){if(!e&&!t)return(new AbortController).signal;if(e?.aborted)return e;const a=new AbortController,n=()=>{r?.(),a.abort()};return e?.addEventListener("abort",n),t?.addEventListener("abort",n),a.signal}function v(e,t){return e instanceof Error?e:new Error(`${t}: ${String(e)}`)}function S(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 R(e){const t="undefined"!=typeof window&&void 0!==window.location&&"null"!==window.location.origin;if(!e)return t?window.location.origin:"";if(e.startsWith("/"))return t?new URL(e,window.location.origin).href.replace(/\/$/,""):e.replace(/\/$/,"");try{new URL(e)}catch{throw new d(`Invalid baseUrl: "${e}". Must be a valid absolute URL or relative path starting with "/".`,e)}return e.endsWith("/")?e.slice(0,-1):e}function $(e,t,a,n){const s=a(e,t);return Object.assign(s,{schema:e=>function(e){const t=e;return t.data=async()=>(await e).data,t}(s.then(t=>{try{const r=n.validate(e,t.data);return{...t,data:r}}catch(a){throw new r(`Schema validation failed: ${a instanceof Error?a.message:String(a)}`,e,t.data,a instanceof Error?a:void 0)}})),data:async()=>(await s).data})}function T(e={}){const t=p({...e,baseUrl:R(e.baseUrl)}),a=e.schemaValidator??{validate(e,t){if(!S(e))throw new i("Schema must implement the Standard Schema interface",e);const a=e["~standard"].validate(t);if(a instanceof Promise)throw new c("Async Standard Schema validation is not supported in this context",e);if(a.issues)throw new r(JSON.stringify(a.issues),e,t);return a.value},isSchema:e=>S(e)};return{get:function(e,...r){return $(e,{...r[0]??{},method:"GET"},t,a)},post:(e,r,...n)=>$(e,{...n[0]??{},method:"POST",body:r},t,a),put:(e,r,...n)=>$(e,{...n[0]??{},method:"PUT",body:r},t,a),patch:(e,r,...n)=>$(e,{...n[0]??{},method:"PATCH",body:r},t,a),delete:(e,...r)=>$(e,{...r[0]??{},method:"DELETE"},t,a),request:(e,r)=>$(e,r??{},t,a)}}const P=T();exports.AsyncSchemaValidationError=c,exports.HttpError=e,exports.MiddlewareError=s,exports.NetworkError=t,exports.PathParameterError=n,exports.SchemaValidationError=r,exports.SerializationError=o,exports.TimeoutError=a,exports.createHttpClient=T,exports.default=P,exports.http=P;
|
|
1
|
+
"use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});class e extends Error{name="HttpError";status;statusText;data;response;url;method;cause;constructor(e,t,r,a,n,s,o,i){const c=t>=500?"Server Error":t>=400?"Client Error":t>=300?"Redirect":"Success",d=a?JSON.stringify(a):"No response data";super(`HTTP ${c} (${t}): ${e}\nRequest: ${o} ${s}\nData: ${d.length>500?d.substring(0,500)+"...":d}`,{cause:i}),this.status=t,this.statusText=r,this.data=a,this.response=n,this.url=s,this.method=o}}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,a){super(e,{cause:a}),this.schema=t,this.data=r}}class a extends Error{name="TimeoutError";cause;constructor(e,t){super(e,{cause:t})}}class n extends Error{name="PathParameterError";url;requiredParams;providedParams;cause;constructor(e,t,r,a,n){super(`${e}\nURL Template: ${t}\nExpected: [${r.map(e=>`"${e}"`).join(", ")}], Actual: [${a.map(e=>`"${e}"`).join(", ")}]`,{cause:n}),this.url=t,this.requiredParams=r,this.providedParams=a}}class s extends Error{name="MiddlewareError";type;url;method;cause;constructor(e,t,r,a,n){const s=r?`Request: ${a||"UNKNOWN"} ${r}`:"";super(s?`${e}\n${s}`:e,{cause:n}),this.type=t,this.url=r,this.method=a}}class o extends Error{name="SerializationError";cause;constructor(e,t){super(e,{cause:t})}}class i extends Error{name="InvalidSchemaError";schema;cause;constructor(e,t,r){super(e,{cause:r}),this.schema=t}}class c extends Error{name="AsyncSchemaValidationError";schema;cause;constructor(e,t,r){super(e,{cause:r}),this.schema=t}}class d extends Error{name="InvalidBaseUrlError";baseUrl;cause;constructor(e,t,r){super(`${e}\nBase URL: ${t}`,{cause:r}),this.baseUrl=t}}function u(e,t,r,a){let n=0,s=!1,o=!1;const i=()=>{if(!s){s=!0;try{e.releaseLock()}catch{}}},c=()=>{o=!0,i()};return a?.addEventListener("abort",c),new ReadableStream({async start(s){try{for(;!o;){const{done:a,value:o}=await e.read();if(a)break;n+=o.length,t(o,r,n),s.enqueue(o)}o||s.close()}catch(d){throw o||s.error(d),d}finally{a?.removeEventListener("abort",c),i()}},cancel(){o=!0,a?.removeEventListener("abort",c),i()}})}async function l(e,t){if(!t||!e.body)return e;if(!e.body.getReader)return e;const r=u(e.body.getReader(),(e,r,a)=>{t({chunk:e,totalBytes:r,transferredBytes:a})},e.headers.get("content-length")?parseInt(e.headers.get("content-length")||"0",10):void 0,e.signal);return new Request(e.url,{method:e.method,headers:e.headers,body:r,signal:e.signal,credentials:e.credentials,cache:e.cache,mode:e.mode,redirect:e.redirect,referrer:e.referrer,referrerPolicy:e.referrerPolicy,integrity:e.integrity,keepalive:e.keepalive,duplex:"half"})}async function h(e,t){if(!t||!e.body)return e;if(!e.body.getReader)return e;const r=u(e.body.getReader(),(e,r,a)=>{t({chunk:e,totalBytes:r,transferredBytes:a})},e.headers.get("content-length")?parseInt(e.headers.get("content-length")||"0",10):void 0);return new Response(r,{status:e.status,statusText:e.statusText,headers:e.headers})}const f={maxRetries:3,retryDelay:300,backoffFactor:2,retryStatusCodes:[429,500,502,503,504],retryNetworkErrors:!0,maxRetryDelay:3e4,shouldRetry:()=>!0};function p(e={}){const{baseUrl:t="",headers:r={},timeout:o=3e4,fetch:i=fetch,serializeBody:c,serializeParams:d,onRequestMiddleware:u,onResponseMiddleware:p}=e;return async function(S,R={}){const{method:$="GET",headers:T={},params:P,pathParams:U,body:j,timeout:O=o,signal:L,credentials:k,cache:A,mode:q,redirect:N,onUploadStreaming:B,onDownloadStreaming:D,responseType:M,retryOptions:C}=R;let H,I=function(e,t={}){return e.replace(/:([^/\s?#]+)\??/g,(r,a)=>{if(!/^[a-zA-Z0-9_]+$/.test(a))throw new n(`Invalid path parameter name: "${a}"`,e,[a],Object.keys(t));const s=t[a];if(void 0===s)throw new n(`Missing required path parameter: "${a}"`,e,[a],Object.keys(t));const o=String(s);if(o.includes("/")||o.includes("?"))throw new n(`Invalid path parameter value for "${a}": contains invalid characters`,e,[a],Object.keys(t));return o})}(S,U);(t||P)&&(t?(I=function(e,t){if(t.startsWith("http://")||t.startsWith("https://"))return t;const r=new URL(e),a=r.pathname.replace(/\/$/,""),[n,s]=t.split("?");t.startsWith("/")?r.pathname=a+n:t&&(r.pathname=a+"/"+n);s&&(r.search=r.search?`${r.search}&${s}`:`?${s}`);return r.toString()}(t,I),H=new URL(I)):H=new URL(I));const W={url:I,method:$,params:P,headers:new Headers({...r,...T}),body:j,signal:L,fetchOptions:{credentials:k,cache:A,mode:q,redirect:N}};let z=W;if(u)try{const e={...W,headers:new Headers(W.headers),fetchOptions:{...W.fetchOptions}};z=await u(e),z.url!==I&&(H=new URL(z.url))}catch(G){throw new s(g("Request middleware failed",G),"request",z.url,z.method,x(G,"Request middleware"))}if(z.params){H||(H=new URL(z.url));const e=d?d(z.params):function(e){const t=new URLSearchParams;for(const[r,a]of Object.entries(e))if(Array.isArray(a))for(const e of a)null!=e&&t.append(r,String(e));else null!=a&&t.append(r,String(a));return t.toString()}(z.params);if(e){if(d){const t=e.startsWith("?")?e.slice(1):e,r=H.search?"&":"?";H.search+=r+t}else{const t=new URLSearchParams(e);for(const[e,r]of t)H.searchParams.append(e,r)}z.url=H.toString()}}const J={method:z.method,headers:z.headers,...z.fetchOptions};if(void 0!==z.body&&("POST"===z.method||"PUT"===z.method||"PATCH"===z.method)){let e,t;if(c){const r=c(z.body);null==r?e="":(e=r,b(z.body)&&"string"==typeof r&&!z.headers.has("content-type")&&(t="application/json"))}else{const r=function(e){if("string"==typeof e||e instanceof FormData||e instanceof URLSearchParams||e instanceof ArrayBuffer||e instanceof Blob||e instanceof ReadableStream)return{body:e};if(b(e))return{body:JSON.stringify(e),contentType:"application/json"};if(null==e)return{body:""};return{body:String(e)}}(z.body);e=r.body,t=r.contentType}J.body=e,t&&z.headers.set("content-type",t),J.duplex="half"}const V={...f,...e.retryOptions,...C},F=V.maxRetries;let _;for(let e=0;e<=F;e+=1){const t=new AbortController,r=setTimeout(()=>t.abort(),O),n=v(z.signal,t.signal,()=>clearTimeout(r));try{const e=new Request(z.url,J),t=B?await l(e,B):e,r=await i(t.url,{method:t.method,headers:t.headers,body:t.body,signal:n,...z.fetchOptions,...t.body&&{duplex:"half"}}),a=D?await h(r,D):r,o=await m(a,{responseType:M,method:$,url:z.url});if(p)try{const e=await p(o);if(!e||"object"!=typeof e||!("data"in e))throw new s("Response middleware must return a valid ResponseType object","response",z.url,$);return e}catch(G){throw new s(g("Response middleware failed",G),"response",z.url,$,x(G,"Response middleware"))}return o}catch(G){if(clearTimeout(r),_=x(G,"Request execution"),"AbortError"===_.name&&(_=new a(`Request timeout after ${O}ms`,_)),e>=F||!(await y(_,e,V)))throw _;const t=w(e,V);await E(t)}}throw new Error("Retry loop terminated unexpectedly")}}async function m(t,r){const a=Object.fromEntries(t.headers.entries());let n;try{const e=r.responseType,a=t.headers.get("content-type")??"",s=a.includes("application/json")?"json":a.includes("text/")?"text":a.includes("application/octet-stream")||a.includes("application/pdf")||a.includes("image/")||a.includes("video/")||a.includes("audio/")?"arrayBuffer":a.includes("multipart/form-data")||a.includes("application/x-www-form-urlencoded")?"formData":void 0,o=e??s;if("json"===o)n=await t.json();else if("text"===o)n=await t.text();else if("blob"===o)n=await t.blob();else if("arrayBuffer"===o)n=await t.arrayBuffer();else if("formData"===o)n=await t.formData();else{const e=t.clone();try{n=await t.json()}catch{n=await e.text()}}}catch(s){throw new o(g("Failed to parse response body",s),s instanceof Error?s:void 0)}if(!t.ok)throw new e(`HTTP ${t.status} ${t.statusText}`,t.status,t.statusText,n,t,r.url,r.method);return{data:n,status:t.status,statusText:t.statusText,headers:a,method:r.method,url:r.url,raw:t}}async function y(r,a,n){return!!n&&(n.shouldRetry?await n.shouldRetry(r,a):r instanceof e?n.retryStatusCodes?.includes(r.status)??!1:(r instanceof t||"TypeError"===r.name)&&(n.retryNetworkErrors??!1))}function w(e,t){if(!t)return 0;const r=t.retryDelay??300,a=t.backoffFactor??2,n=t.maxRetryDelay??3e4,s=r*Math.pow(a,e);return Math.min(s,n)}function b(e){return null!==e&&"object"==typeof e&&"Object"===e.constructor?.name||Array.isArray(e)||null!==e&&"object"==typeof e&&"toJSON"in e&&"function"==typeof e.toJSON}function g(e,t){return`${e}: ${t instanceof Error?t.message:String(t)}`}function E(e){return new Promise(t=>setTimeout(t,e))}function v(e,t,r){if(!e&&!t)return(new AbortController).signal;if(e?.aborted)return e;const a=new AbortController,n=()=>{r?.(),a.abort()};return e?.addEventListener("abort",n),t?.addEventListener("abort",n),a.signal}function x(e,t){return e instanceof Error?e:new Error(`${t}: ${String(e)}`)}function S(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 R(e){const t="undefined"!=typeof window&&void 0!==window.location&&"null"!==window.location.origin;if(!e)return t?window.location.origin:"";if(e.startsWith("/"))return t?new URL(e,window.location.origin).href.replace(/\/$/,""):e.replace(/\/$/,"");try{new URL(e)}catch{throw new d(`Invalid baseUrl: "${e}". Must be a valid absolute URL or relative path starting with "/".`,e)}return e.endsWith("/")?e.slice(0,-1):e}function $(e,t,a,n){const s=a(e,t);return Object.assign(s,{schema:e=>function(e){const t=e;return t.data=async()=>(await e).data,t.void=async()=>{await e},t}(s.then(t=>{try{const r=n.validate(e,t.data);return{...t,data:r}}catch(a){throw new r(`Schema validation failed: ${a instanceof Error?a.message:String(a)}`,e,t.data,a instanceof Error?a:void 0)}})),data:async()=>(await s).data,async void(){await s}})}function T(e={}){const t=p({...e,baseUrl:R(e.baseUrl)}),a=e.schemaValidator??{validate(e,t){if(!S(e))throw new i("Schema must implement the Standard Schema interface",e);const a=e["~standard"].validate(t);if(a instanceof Promise)throw new c("Async Standard Schema validation is not supported in this context",e);if(a.issues)throw new r(JSON.stringify(a.issues),e,t);return a.value},isSchema:e=>S(e)};return{get:function(e,...r){return $(e,{...r[0]??{},method:"GET"},t,a)},post:(e,r,...n)=>$(e,{...n[0]??{},method:"POST",body:r},t,a),put:(e,r,...n)=>$(e,{...n[0]??{},method:"PUT",body:r},t,a),patch:(e,r,...n)=>$(e,{...n[0]??{},method:"PATCH",body:r},t,a),delete:(e,...r)=>$(e,{...r[0]??{},method:"DELETE"},t,a),request:(e,r)=>$(e,r??{},t,a)}}const P=T();exports.AsyncSchemaValidationError=c,exports.HttpError=e,exports.MiddlewareError=s,exports.NetworkError=t,exports.PathParameterError=n,exports.SchemaValidationError=r,exports.SerializationError=o,exports.TimeoutError=a,exports.createHttpClient=T,exports.default=P,exports.http=P;
|
|
2
2
|
//# sourceMappingURL=index.cjs.js.map
|
package/dist/index.cjs.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs.js","sources":["../src/errors.ts","../src/utils/streaming.ts","../src/core.ts","../src/utils/path.ts","../src/schema.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 statusCategory =\n status >= 500\n ? 'Server Error'\n : status >= 400\n ? 'Client Error'\n : status >= 300\n ? 'Redirect'\n : 'Success'\n\n const dataString = data ? JSON.stringify(data) : 'No response data'\n const truncatedData =\n dataString.length > 500\n ? dataString.substring(0, 500) + '...'\n : dataString\n\n const enhancedMessage = `HTTP ${statusCategory} (${status}): ${message}\nRequest: ${method} ${url}\nData: ${truncatedData}`\n\n super(enhancedMessage, { cause })\n this.status = status\n this.statusText = statusText\n this.data = data\n this.response = response\n this.url = url\n this.method = method\n }\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 const enhancedMessage = `${message}\nURL Template: ${url}\nExpected: [${requiredParams.map(p => `\"${p}\"`).join(', ')}], Actual: [${providedParams.map(p => `\"${p}\"`).join(', ')}]`\n\n super(enhancedMessage, { cause })\n this.url = url\n this.requiredParams = requiredParams\n this.providedParams = providedParams\n }\n}\n\nexport class MiddlewareError extends Error implements HttpClientError {\n public readonly name = 'MiddlewareError'\n public readonly type: 'request' | 'response'\n public readonly url?: string\n public readonly method?: string\n public override readonly cause?: Error\n\n constructor(\n message: string,\n type: 'request' | 'response',\n url?: string,\n method?: string,\n cause?: Error\n ) {\n const requestInfo = url ? `Request: ${method || 'UNKNOWN'} ${url}` : ''\n const enhancedMessage = requestInfo ? `${message}\\n${requestInfo}` : message\n\n super(enhancedMessage, { cause })\n this.type = type\n this.url = url\n this.method = method\n }\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\nexport class InvalidSchemaError extends Error implements HttpClientError {\n public readonly name = 'InvalidSchemaError'\n public readonly schema: unknown\n public override readonly cause?: Error\n\n constructor(message: string, schema: unknown, cause?: Error) {\n super(message, { cause })\n this.schema = schema\n }\n}\n\nexport class AsyncSchemaValidationError\n extends Error\n implements HttpClientError\n{\n public readonly name = 'AsyncSchemaValidationError'\n public readonly schema: unknown\n public override readonly cause?: Error\n\n constructor(message: string, schema: unknown, cause?: Error) {\n super(message, { cause })\n this.schema = schema\n }\n}\n\nexport class InvalidBaseUrlError extends Error implements HttpClientError {\n public readonly name = 'InvalidBaseUrlError'\n public readonly baseUrl: string\n public override readonly cause?: Error\n\n constructor(message: string, baseUrl: string, cause?: Error) {\n const enhancedMessage = `${message}\nBase URL: ${baseUrl}`\n\n super(enhancedMessage, { cause })\n this.baseUrl = baseUrl\n }\n}\n","import type { DownloadStreamingEvent, UploadStreamingEvent } from '../types'\n\nfunction createStreamingStream(\n reader: ReadableStreamDefaultReader<Uint8Array>,\n onChunk: (\n chunk: Uint8Array,\n totalBytes: number | undefined,\n transferredBytes: number\n ) => void,\n totalBytes: number | undefined,\n signal?: AbortSignal\n): ReadableStream<Uint8Array> {\n let transferredBytes = 0\n let readerReleased = false\n let isAborted = false\n\n const releaseReader = () => {\n if (!readerReleased) {\n readerReleased = true\n try {\n reader.releaseLock()\n } catch {\n // Reader might already be released, ignore\n }\n }\n }\n\n // Handle abort signal\n const abortHandler = () => {\n isAborted = true\n releaseReader()\n }\n\n signal?.addEventListener('abort', abortHandler)\n\n return new ReadableStream({\n async start(controller) {\n try {\n while (!isAborted) {\n const { done, value } = await reader.read()\n if (done) break\n\n transferredBytes += value.length\n onChunk(value, totalBytes, transferredBytes)\n controller.enqueue(value)\n }\n\n if (!isAborted) {\n controller.close()\n }\n } catch (error) {\n if (!isAborted) {\n controller.error(error)\n }\n throw error\n } finally {\n signal?.removeEventListener('abort', abortHandler)\n releaseReader()\n }\n },\n cancel() {\n isAborted = true\n signal?.removeEventListener('abort', abortHandler)\n releaseReader()\n },\n })\n}\n\n/**\n * Creates a request with upload streaming tracking\n */\nexport async function toStreamableRequest(\n request: Request,\n onUploadStreaming?: (event: UploadStreamingEvent) => void\n): Promise<Request> {\n if (!onUploadStreaming || !request.body) {\n return request\n }\n\n if (!request.body.getReader) {\n return request\n }\n\n const reader = request.body.getReader()\n const totalBytes = request.headers.get('content-length')\n ? parseInt(request.headers.get('content-length') || '0', 10)\n : undefined\n\n const stream = createStreamingStream(\n reader,\n (chunk, totalBytes, transferredBytes) => {\n onUploadStreaming({\n chunk,\n totalBytes,\n transferredBytes,\n })\n },\n totalBytes,\n request.signal\n )\n\n return new Request(request.url, {\n method: request.method,\n headers: request.headers,\n body: stream,\n signal: request.signal,\n credentials: request.credentials,\n cache: request.cache,\n mode: request.mode,\n redirect: request.redirect,\n referrer: request.referrer,\n referrerPolicy: request.referrerPolicy,\n integrity: request.integrity,\n keepalive: request.keepalive,\n duplex: 'half',\n } as RequestInit)\n}\n\n/**\n * Creates a response with download streaming tracking\n */\nexport async function toStreamableResponse(\n response: Response,\n onDownloadStreaming?: (event: DownloadStreamingEvent) => void\n): Promise<Response> {\n if (!onDownloadStreaming || !response.body) {\n return response\n }\n\n if (!response.body.getReader) {\n return response\n }\n\n const reader = response.body.getReader()\n const totalBytes = response.headers.get('content-length')\n ? parseInt(response.headers.get('content-length') || '0', 10)\n : undefined\n\n const stream = createStreamingStream(\n reader,\n (chunk, totalBytes, transferredBytes) => {\n onDownloadStreaming({\n chunk,\n totalBytes,\n transferredBytes,\n })\n },\n totalBytes\n )\n\n return new Response(stream, {\n status: response.status,\n statusText: response.statusText,\n headers: response.headers,\n })\n}\n","import {\n HttpError,\n MiddlewareError,\n NetworkError,\n SerializationError,\n TimeoutError,\n} from './errors'\nimport type { SchemaValidator } from './schema'\nimport type {\n CustomFetch,\n DownloadStreamingEvent,\n ExtendedRequestInit,\n HttpHeaders,\n HttpMethod,\n RequestContext,\n RequestParamsType,\n ResponseType,\n RetryOptions,\n SerializeBody,\n SerializeParams,\n UploadStreamingEvent,\n} from './types'\nimport {\n generatePath,\n toStreamableRequest,\n toStreamableResponse,\n type PathParams,\n} from './utils'\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: 30_000,\n shouldRetry: () => true,\n}\n\nexport interface HttpRequestOptions<\n TBody = unknown,\n TParams extends RequestParamsType = RequestParamsType,\n> {\n method?: HttpMethod\n headers?: HttpHeaders\n /** Query parameters */\n params?: TParams\n /** Path parameters for URL template */\n pathParams?: Record<string, string | number>\n /** Request body */\n body?: TBody\n timeout?: number\n signal?: AbortSignal\n /** Fetch options */\n credentials?: RequestCredentials\n cache?: RequestCache\n mode?: RequestMode\n redirect?: RequestRedirect\n /** Upload streaming tracking for this specific request */\n onUploadStreaming?: (event: UploadStreamingEvent) => void\n /** Download streaming tracking for this specific request */\n onDownloadStreaming?: (event: DownloadStreamingEvent) => void\n /** Response type override */\n responseType?: 'json' | 'text' | 'blob' | 'arrayBuffer' | 'formData'\n retryOptions?: RetryOptions\n}\n\nexport interface HttpClientConfig {\n /** Base URL for all requests */\n baseUrl?: string\n /** Default headers */\n headers?: HttpHeaders\n /** Default timeout */\n timeout?: number\n /** Schema validator */\n schemaValidator?: SchemaValidator\n /** Default retry options */\n retryOptions?: RetryOptions\n /** Custom fetch implementation */\n fetch?: CustomFetch\n /** Custom body serializer */\n serializeBody?: SerializeBody\n /** Custom params serializer */\n serializeParams?: SerializeParams\n /** Request middleware - can modify request before sending */\n onRequestMiddleware?: <TBody = unknown>(\n context: RequestContext<TBody>\n ) => RequestContext<TBody> | Promise<RequestContext<TBody>>\n /** Response middleware - can modify response after receiving */\n onResponseMiddleware?: (\n response: ResponseType<unknown>\n ) => ResponseType<unknown> | Promise<ResponseType<unknown>>\n}\n\n/**\n * Creates an HTTP request handler with the given configuration.\n * This is the core function that handles all HTTP requests with retry logic,\n * interceptors, and streaming.\n */\nexport function createHttpRequest(config: HttpClientConfig = {}) {\n const {\n baseUrl = '',\n headers: defaultHeaders = {},\n timeout: defaultTimeout = 30_000,\n fetch: customFetch = fetch,\n serializeBody: customSerializeBody,\n serializeParams: customSerializeParams,\n onRequestMiddleware,\n onResponseMiddleware,\n } = config\n\n return async function fetcher<\n Path extends string = string,\n TResponse = unknown,\n TBody = unknown,\n TParams extends RequestParamsType = RequestParamsType,\n >(\n url: Path,\n options: HttpRequestOptions<TBody, TParams> = {}\n ): Promise<ResponseType<TResponse>> {\n const {\n method = 'GET',\n headers = {},\n params,\n pathParams,\n body,\n timeout = defaultTimeout,\n signal,\n credentials,\n cache,\n mode,\n redirect,\n onUploadStreaming,\n onDownloadStreaming,\n responseType,\n retryOptions: requestRetryOptions,\n } = options\n\n let urlObj: URL | undefined\n let resolvedUrl = generatePath(url, pathParams as PathParams<Path>)\n\n if (baseUrl || params) {\n if (baseUrl) {\n resolvedUrl = constructUrl(baseUrl, resolvedUrl)\n urlObj = new URL(resolvedUrl)\n } else {\n urlObj = new URL(resolvedUrl)\n }\n }\n\n const baseRequestContext: RequestContext<TBody> = {\n url: resolvedUrl,\n method,\n params,\n headers: new Headers({ ...defaultHeaders, ...headers }),\n body,\n signal,\n fetchOptions: { credentials, cache, mode, redirect },\n }\n\n let requestContext: RequestContext<TBody> = baseRequestContext\n\n if (onRequestMiddleware) {\n try {\n // prevent middleware from mutating the original context\n const contextCopy: RequestContext<TBody> = {\n ...baseRequestContext,\n headers: new Headers(baseRequestContext.headers),\n fetchOptions: { ...baseRequestContext.fetchOptions },\n }\n\n requestContext = await onRequestMiddleware(contextCopy)\n\n if (requestContext.url !== resolvedUrl) {\n urlObj = new URL(requestContext.url)\n }\n } catch (error) {\n throw new MiddlewareError(\n createErrorMessage('Request middleware failed', error),\n 'request',\n requestContext.url,\n requestContext.method,\n createStandardizedError(error, 'Request middleware')\n )\n }\n }\n\n if (requestContext.params) {\n if (!urlObj) {\n urlObj = new URL(requestContext.url)\n }\n\n const serializedParams = customSerializeParams\n ? customSerializeParams(requestContext.params)\n : serializeQueryParams(requestContext.params)\n\n if (serializedParams) {\n if (customSerializeParams) {\n const queryString = serializedParams.startsWith('?')\n ? serializedParams.slice(1)\n : serializedParams\n const separator = urlObj.search ? '&' : '?'\n urlObj.search += separator + queryString\n } else {\n const newSearchParams = new URLSearchParams(serializedParams)\n for (const [key, value] of newSearchParams) {\n urlObj.searchParams.append(key, value)\n }\n }\n requestContext.url = urlObj.toString()\n }\n }\n\n const requestInit: ExtendedRequestInit = {\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 let body: BodyInit\n let contentType: string | undefined\n\n if (customSerializeBody) {\n const serializedBody = customSerializeBody(requestContext.body)\n if (serializedBody == null) {\n body = ''\n } else {\n body = serializedBody\n\n if (\n isObjectLike(requestContext.body) &&\n typeof serializedBody === 'string' &&\n !requestContext.headers.has('content-type')\n ) {\n contentType = 'application/json'\n }\n }\n } else {\n const serialized = serializeRequestBody(requestContext.body)\n body = serialized.body\n contentType = serialized.contentType\n }\n\n requestInit.body = body\n\n if (contentType) {\n requestContext.headers.set('content-type', contentType)\n }\n\n requestInit.duplex = 'half'\n }\n\n const mergedRetryOptions = {\n ...DEFAULT_RETRY_OPTIONS,\n ...config.retryOptions,\n ...requestRetryOptions,\n }\n const maxRetries = mergedRetryOptions.maxRetries\n let lastError: Error | undefined\n\n for (let attempt = 0; attempt <= maxRetries; attempt += 1) {\n const controller = new AbortController()\n const timeoutId = setTimeout(() => controller.abort(), timeout)\n\n const finalSignal = createCombinedSignal(\n requestContext.signal,\n controller.signal,\n () => clearTimeout(timeoutId)\n )\n\n try {\n const request = new Request(requestContext.url, requestInit)\n const trackedRequest = onUploadStreaming\n ? await toStreamableRequest(request, onUploadStreaming)\n : request\n\n const response = await customFetch(trackedRequest.url, {\n method: trackedRequest.method,\n headers: trackedRequest.headers,\n body: trackedRequest.body,\n signal: finalSignal,\n ...requestContext.fetchOptions,\n ...(trackedRequest.body && { duplex: 'half' }),\n } satisfies ExtendedRequestInit)\n\n const trackedResponse = onDownloadStreaming\n ? await toStreamableResponse(response, onDownloadStreaming)\n : response\n\n const responseData = await processResponse<TResponse>(trackedResponse, {\n responseType,\n method,\n url: requestContext.url,\n })\n\n if (onResponseMiddleware) {\n try {\n const middlewareResult = await onResponseMiddleware(responseData)\n if (\n !middlewareResult ||\n typeof middlewareResult !== 'object' ||\n !('data' in middlewareResult)\n ) {\n throw new MiddlewareError(\n 'Response middleware must return a valid ResponseType object',\n 'response',\n requestContext.url,\n method\n )\n }\n return middlewareResult as ResponseType<TResponse>\n } catch (error) {\n throw new MiddlewareError(\n createErrorMessage('Response middleware failed', error),\n 'response',\n requestContext.url,\n method,\n createStandardizedError(error, 'Response middleware')\n )\n }\n }\n\n return responseData\n } catch (error) {\n clearTimeout(timeoutId)\n lastError = createStandardizedError(error, 'Request execution')\n\n if (lastError.name === 'AbortError') {\n lastError = new TimeoutError(\n `Request timeout after ${timeout}ms`,\n lastError\n )\n }\n\n if (\n attempt >= maxRetries ||\n !(await shouldRetry(lastError, attempt, mergedRetryOptions))\n ) {\n throw lastError\n }\n\n const delay = calculateRetryDelay(attempt, mergedRetryOptions)\n await sleep(delay)\n }\n }\n\n throw new Error('Retry loop terminated unexpectedly')\n }\n}\n\nasync function processResponse<T = unknown>(\n response: Response,\n options: {\n responseType?: 'json' | 'text' | 'blob' | 'arrayBuffer' | 'formData'\n method: HttpMethod\n url: string\n }\n): Promise<ResponseType<T>> {\n const headers = Object.fromEntries(response.headers.entries())\n\n let data: unknown\n try {\n const requestedType = options.responseType\n const contentType = response.headers.get('content-type') ?? ''\n\n const detectedType:\n | 'json'\n | 'text'\n | 'arrayBuffer'\n | 'formData'\n | undefined = contentType.includes('application/json')\n ? 'json'\n : contentType.includes('text/')\n ? 'text'\n : contentType.includes('application/octet-stream') ||\n contentType.includes('application/pdf') ||\n contentType.includes('image/') ||\n contentType.includes('video/') ||\n contentType.includes('audio/')\n ? 'arrayBuffer'\n : contentType.includes('multipart/form-data') ||\n contentType.includes('application/x-www-form-urlencoded')\n ? 'formData'\n : undefined\n\n const finalType:\n | 'json'\n | 'text'\n | 'arrayBuffer'\n | 'blob'\n | 'formData'\n | undefined = requestedType ?? detectedType\n\n if (finalType === 'json') {\n data = await response.json()\n } else if (finalType === 'text') {\n data = await response.text()\n } else if (finalType === 'blob') {\n data = await response.blob()\n } else if (finalType === 'arrayBuffer') {\n data = await response.arrayBuffer()\n } else if (finalType === 'formData') {\n data = await response.formData()\n } else {\n const responseClone = response.clone()\n try {\n data = await response.json()\n } catch {\n data = await responseClone.text()\n }\n }\n } catch (error) {\n throw new SerializationError(\n createErrorMessage('Failed to parse response body', error),\n error instanceof Error ? error : undefined\n )\n }\n\n if (!response.ok) {\n throw new HttpError(\n `HTTP ${response.status} ${response.statusText}`,\n response.status,\n response.statusText,\n data,\n response,\n options.url,\n options.method\n )\n }\n\n return {\n data: data as T,\n status: response.status,\n statusText: response.statusText,\n headers,\n method: options.method,\n url: options.url,\n raw: response,\n }\n}\n\nasync function shouldRetry(\n error: Error,\n retryCount: number,\n retryOptions?: RetryOptions\n): Promise<boolean> {\n if (!retryOptions) return false\n\n if (retryOptions.shouldRetry) {\n return await retryOptions.shouldRetry(error, retryCount)\n }\n\n if (error instanceof HttpError) {\n return retryOptions.retryStatusCodes?.includes(error.status) ?? false\n }\n\n if (error instanceof NetworkError || error.name === 'TypeError') {\n return retryOptions.retryNetworkErrors ?? false\n }\n\n return false\n}\n\nfunction calculateRetryDelay(\n attempt: number,\n retryOptions?: RetryOptions\n): number {\n if (!retryOptions) return 0\n\n const baseDelay = retryOptions.retryDelay ?? 300\n const backoffFactor = retryOptions.backoffFactor ?? 2\n const maxDelay = retryOptions.maxRetryDelay ?? 30_000\n\n const delay = baseDelay * Math.pow(backoffFactor, attempt)\n return Math.min(delay, maxDelay)\n}\n\nfunction isObjectLike(\n value: unknown\n): value is Record<string, unknown> | unknown[] | { toJSON(): unknown } {\n return (\n (value !== null &&\n typeof value === 'object' &&\n value.constructor?.name === 'Object') ||\n Array.isArray(value) ||\n (value !== null &&\n typeof value === 'object' &&\n 'toJSON' in value &&\n typeof value.toJSON === 'function')\n )\n}\n\nfunction serializeQueryParams(params: RequestParamsType): string {\n const searchParams = new URLSearchParams()\n\n for (const [key, value] of Object.entries(params)) {\n if (Array.isArray(value)) {\n for (const item of value) {\n if (item !== undefined && item !== null) {\n searchParams.append(key, String(item))\n }\n }\n } else if (value !== undefined && value !== null) {\n searchParams.append(key, String(value))\n }\n }\n\n return searchParams.toString()\n}\n\nfunction serializeRequestBody(body: unknown): {\n body: BodyInit\n contentType?: string\n} {\n if (\n typeof body === 'string' ||\n body instanceof FormData ||\n body instanceof URLSearchParams ||\n body instanceof ArrayBuffer ||\n body instanceof Blob ||\n body instanceof ReadableStream\n ) {\n return { body: body }\n }\n\n if (isObjectLike(body)) {\n return {\n body: JSON.stringify(body),\n contentType: 'application/json',\n }\n }\n\n if (body === null || body === undefined) {\n return { body: '' }\n }\n\n return { body: String(body) }\n}\n\nfunction createErrorMessage(context: string, error: unknown): string {\n return `${context}: ${error instanceof Error ? error.message : String(error)}`\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms))\n}\n\nfunction createCombinedSignal(\n requestSignal?: AbortSignal,\n timeoutSignal?: AbortSignal,\n cleanup?: () => void\n): AbortSignal {\n if (!requestSignal && !timeoutSignal) {\n return new AbortController().signal\n }\n\n if (requestSignal?.aborted) {\n return requestSignal\n }\n\n const combinedController = new AbortController()\n\n const handleAbort = () => {\n cleanup?.()\n combinedController.abort()\n }\n\n requestSignal?.addEventListener('abort', handleAbort)\n timeoutSignal?.addEventListener('abort', handleAbort)\n\n return combinedController.signal\n}\n\nfunction createStandardizedError(error: unknown, context: string): Error {\n if (error instanceof Error) {\n return error\n }\n\n return new Error(`${context}: ${String(error)}`)\n}\n\nfunction constructUrl(baseUrl: string, requestUrl: string): string {\n if (requestUrl.startsWith('http://') || requestUrl.startsWith('https://')) {\n return requestUrl\n }\n\n const baseUrlObj = new URL(baseUrl)\n const basePath = baseUrlObj.pathname.replace(/\\/$/, '')\n const [path, query] = requestUrl.split('?')\n\n if (requestUrl.startsWith('/')) {\n baseUrlObj.pathname = basePath + path\n } else if (requestUrl) {\n baseUrlObj.pathname = basePath + '/' + path\n }\n\n if (query) {\n baseUrlObj.search = baseUrlObj.search\n ? `${baseUrlObj.search}&${query}`\n : `?${query}`\n }\n\n return baseUrlObj.toString()\n}\n","import { PathParameterError } from '../errors'\n\n/**\n * Strips protocol from URL (e.g., https://, http://)\n */\ntype StripProtocol<T extends string> = T extends `${string}://${infer After}`\n ? After\n : T\n\n/**\n * Strips host and optional port from URL, keeping only the path\n * Handles cases like \"localhost:3000/users\" -> \"/users\"\n */\ntype StripHost<T extends string> = T extends `${infer _Host}/${infer Path}`\n ? `/${Path}`\n : T\n\n/**\n * Strips query string from path (e.g., \"/users?x=1\" -> \"/users\")\n * Only strips ? that comes after the path, not ? that's part of path parameters\n */\ntype StripQuery<T extends string> = T extends `${infer Path}?${infer Query}`\n ? Query extends\n | `${string}=${string}`\n | `${string}&${string}`\n | `${string}=${string}&${string}`\n ? Path // Contains query parameters (has = or &)\n : Query extends `/${string}`\n ? T // It's another path segment, not a query\n : Query extends ``\n ? T // It's an optional param marker (?)\n : Path // Plain query params like ?param\n : T\n\n/**\n * Normalizes URL to path only, stripping protocol, host, port, and query\n */\ntype NormalizePath<T extends string> = StripQuery<StripHost<StripProtocol<T>>>\n\n/**\n * Removes optional suffix from param name (e.g., \":id?\" -> \"id\", \":id\" -> \"id\")\n */\ntype CleanParamName<S extends string> = S extends `:${infer Name}?`\n ? Name\n : S extends `:${infer Name}`\n ? Name\n : S\n\n/**\n * Extracts all path parameters from a route\n */\nexport type ExtractRouteParams<T extends string> =\n NormalizePath<T> extends `${infer _Before}:${infer AfterColon}`\n ? AfterColon extends `${infer Param}/${infer Rest}`\n ? CleanParamName<`:${Param}`> | ExtractRouteParams<`/${Rest}`>\n : CleanParamName<`:${AfterColon}`>\n : never\n\nexport type HasRequiredParams<T extends string> = [\n ExtractRouteParams<T>,\n] extends [never]\n ? false\n : true\n\n/**\n * PathParams type - extracts parameter names and their types\n */\nexport type PathParams<Path extends string> = {\n [K in ExtractRouteParams<Path>]: string | number\n}\n\n/**\n * RequirePathParams enforces pathParams when needed\n */\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(/:([^/\\s?#]+)\\??/g, (_match, paramName: string) => {\n // Validate parameter name\n if (!/^[a-zA-Z0-9_]+$/.test(paramName)) {\n throw new PathParameterError(\n `Invalid path parameter name: \"${paramName}\"`,\n path,\n [paramName],\n Object.keys(params)\n )\n }\n\n // Get and validate parameter value\n const paramValue = params[paramName as keyof PathParams<Path>]\n if (paramValue === undefined) {\n throw new PathParameterError(\n `Missing required path parameter: \"${paramName}\"`,\n path,\n [paramName],\n Object.keys(params)\n )\n }\n\n const stringValue = String(paramValue)\n if (stringValue.includes('/') || stringValue.includes('?')) {\n throw new PathParameterError(\n `Invalid path parameter value for \"${paramName}\": contains invalid characters`,\n path,\n [paramName],\n Object.keys(params)\n )\n }\n\n return stringValue\n })\n}\n","import type { StandardSchemaV1 } from '@standard-schema/spec'\nimport {\n AsyncSchemaValidationError,\n InvalidSchemaError,\n SchemaValidationError,\n} from './errors'\nimport { Schema } from './types'\n\n/**\n * Type guard to check if an object conforms to the Standard Schema V1 specification\n */\nfunction isStandardSchema(obj: unknown): obj is StandardSchemaV1 {\n return (\n obj !== null &&\n (typeof obj === 'object' || typeof obj === 'function') &&\n '~standard' in obj &&\n typeof obj['~standard'] === 'object' &&\n obj['~standard'] !== null &&\n 'validate' in obj['~standard'] &&\n typeof obj['~standard'].validate === 'function' &&\n 'version' in obj['~standard'] &&\n typeof obj['~standard'].version === 'number' &&\n 'vendor' in obj['~standard'] &&\n typeof obj['~standard'].vendor === 'string'\n )\n}\n\n/**\n * Interface for schema validators that can validate data against schemas.\n *\n * This interface allows you to create custom schema validators that work\n * with different validation libraries (Zod, Valibot, Arktype, etc.).\n */\nexport interface SchemaValidator {\n /**\n * Validate data against a schema.\n *\n * @template T - The expected type after validation\n * @param schema - The schema to validate against\n * @param data - The data to validate\n * @returns The validated data with the correct type\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 InvalidSchemaError(\n 'Schema must implement the Standard Schema interface',\n schema\n )\n }\n\n const result = schema['~standard'].validate(data)\n\n if (result instanceof Promise) {\n throw new AsyncSchemaValidationError(\n 'Async Standard Schema validation is not supported in this context',\n schema\n )\n }\n\n if (result.issues) {\n throw new SchemaValidationError(\n JSON.stringify(result.issues),\n schema,\n data\n )\n }\n\n return result.value as T\n },\n\n isSchema(obj: unknown): boolean {\n return isStandardSchema(obj)\n },\n }\n}\n","import type { HttpClientConfig, HttpRequestOptions } from './core'\nimport { createHttpRequest } from './core'\nimport { InvalidBaseUrlError, SchemaValidationError } from './errors'\nimport { createSchemaValidator } from './schema'\nimport type {\n EnforcedPathParamsOptions,\n ExtractableResponse,\n InferSchemaOutput,\n RequestParamsType,\n ResponseType,\n Schema,\n SchemaableResponse,\n} from './types'\nimport type { HasRequiredParams } from './utils'\n\nfunction validateAndNormalizeBaseUrl(baseUrl?: string): string {\n const hasLocation =\n typeof window !== 'undefined' &&\n typeof window.location !== 'undefined' &&\n window.location.origin !== 'null'\n\n if (!baseUrl) {\n // In browser environment, default to location.origin for relative paths\n return hasLocation ? window.location.origin : ''\n }\n\n if (baseUrl.startsWith('/')) {\n // In Node.js or non-browser environments, relative paths are preserved as-is\n return hasLocation\n ? new URL(baseUrl, window.location.origin).href.replace(/\\/$/, '')\n : baseUrl.replace(/\\/$/, '')\n }\n\n try {\n new URL(baseUrl)\n } catch {\n throw new InvalidBaseUrlError(\n `Invalid baseUrl: \"${baseUrl}\". Must be a valid absolute URL or relative path starting with \"/\".`,\n baseUrl\n )\n }\n\n return baseUrl.endsWith('/') ? baseUrl.slice(0, -1) : baseUrl\n}\n\nfunction createExtractableResponse<T>(\n promise: Promise<ResponseType<T>>\n): ExtractableResponse<T> {\n const extractable = promise as ExtractableResponse<T>\n extractable.data = async () => (await promise).data\n return extractable\n}\n\n/**\n * Creates a chainable response that allows adding schema validation and extracting data\n */\nfunction createSchemaableResponse<\n Path extends string,\n TResponse,\n TBody,\n TParams extends RequestParamsType,\n>(\n url: Path,\n options: HttpRequestOptions<TBody, TParams>,\n requestHandler: ReturnType<typeof createHttpRequest>,\n schemaValidator: ReturnType<typeof createSchemaValidator>\n): SchemaableResponse<TResponse> {\n const basePromise = requestHandler<Path, TResponse, TBody, TParams>(\n url,\n options\n )\n\n return Object.assign(basePromise, {\n schema<S extends Schema>(\n schema: S\n ): ExtractableResponse<InferSchemaOutput<S>> {\n const validatedPromise = basePromise.then(response => {\n try {\n const validatedData = schemaValidator.validate(\n schema,\n response.data\n ) as InferSchemaOutput<S>\n return {\n ...response,\n data: validatedData,\n }\n } catch (error) {\n throw new SchemaValidationError(\n `Schema validation failed: ${\n error instanceof Error ? error.message : String(error)\n }`,\n schema,\n response.data,\n error instanceof Error ? error : undefined\n )\n }\n })\n\n return createExtractableResponse(validatedPromise)\n },\n async data() {\n return (await basePromise).data\n },\n })\n}\n\n/**\n * Creates a complete HTTP client with method builders\n */\nexport function createHttpClient(config: HttpClientConfig = {}) {\n const validatedConfig = {\n ...config,\n baseUrl: validateAndNormalizeBaseUrl(config.baseUrl),\n }\n\n const requestHandler = createHttpRequest(validatedConfig)\n const schemaValidator = config.schemaValidator ?? createSchemaValidator()\n\n function get<\n Path extends string = string,\n TParams extends RequestParamsType = RequestParamsType,\n >(\n url: Path,\n ...args: HasRequiredParams<Path> extends true\n ? [options: EnforcedPathParamsOptions<never, TParams, Path>]\n : [options?: EnforcedPathParamsOptions<never, TParams, Path>]\n ) {\n return createSchemaableResponse<Path, unknown, never, TParams>(\n url,\n {\n ...(args[0] ?? {}),\n method: 'GET',\n },\n requestHandler,\n schemaValidator\n )\n }\n\n return {\n get,\n\n post: <\n Path extends string = string,\n TBody = unknown,\n TParams extends RequestParamsType = RequestParamsType,\n >(\n url: Path,\n body?: TBody,\n ...args: HasRequiredParams<Path> extends true\n ? [options: EnforcedPathParamsOptions<TBody, TParams, Path>]\n : [options?: EnforcedPathParamsOptions<TBody, TParams, Path>]\n ) =>\n createSchemaableResponse<Path, unknown, TBody, TParams>(\n url,\n {\n ...(args[0] ?? {}),\n method: 'POST',\n body,\n },\n requestHandler,\n schemaValidator\n ),\n\n put: <\n Path extends string = string,\n TBody = unknown,\n TParams extends RequestParamsType = RequestParamsType,\n >(\n url: Path,\n body?: TBody,\n ...args: HasRequiredParams<Path> extends true\n ? [options: EnforcedPathParamsOptions<TBody, TParams, Path>]\n : [options?: EnforcedPathParamsOptions<TBody, TParams, Path>]\n ) =>\n createSchemaableResponse<Path, unknown, TBody, TParams>(\n url,\n {\n ...(args[0] ?? {}),\n method: 'PUT',\n body,\n },\n requestHandler,\n schemaValidator\n ),\n\n patch: <\n Path extends string = string,\n TBody = unknown,\n TParams extends RequestParamsType = RequestParamsType,\n >(\n url: Path,\n body?: TBody,\n ...args: HasRequiredParams<Path> extends true\n ? [options: EnforcedPathParamsOptions<TBody, TParams, Path>]\n : [options?: EnforcedPathParamsOptions<TBody, TParams, Path>]\n ) =>\n createSchemaableResponse<Path, unknown, TBody, TParams>(\n url,\n {\n ...(args[0] ?? {}),\n method: 'PATCH',\n body,\n },\n requestHandler,\n schemaValidator\n ),\n\n delete: <\n Path extends string = string,\n TParams extends RequestParamsType = RequestParamsType,\n >(\n url: Path,\n ...args: HasRequiredParams<Path> extends true\n ? [options: EnforcedPathParamsOptions<never, TParams, Path>]\n : [options?: EnforcedPathParamsOptions<never, TParams, Path>]\n ) =>\n createSchemaableResponse<Path, unknown, never, TParams>(\n url,\n {\n ...(args[0] ?? {}),\n method: 'DELETE',\n },\n requestHandler,\n schemaValidator\n ),\n\n /**\n * Generic request method for custom HTTP methods and full control\n */\n request: <\n Path extends string = string,\n TBody = unknown,\n TParams extends RequestParamsType = RequestParamsType,\n >(\n url: Path,\n options?: HttpRequestOptions<TBody, TParams>\n ) =>\n createSchemaableResponse<Path, unknown, TBody, TParams>(\n url,\n options ?? {},\n requestHandler,\n schemaValidator\n ),\n }\n}\n\nexport const http = createHttpClient()\n"],"names":["HttpError","Error","name","status","statusText","data","response","url","method","cause","constructor","message","statusCategory","dataString","JSON","stringify","super","length","substring","this","NetworkError","SchemaValidationError","schema","TimeoutError","PathParameterError","requiredParams","providedParams","map","p","join","MiddlewareError","type","requestInfo","SerializationError","InvalidSchemaError","AsyncSchemaValidationError","InvalidBaseUrlError","baseUrl","createStreamingStream","reader","onChunk","totalBytes","signal","transferredBytes","readerReleased","isAborted","releaseReader","releaseLock","abortHandler","addEventListener","ReadableStream","start","controller","done","value","read","enqueue","close","error","removeEventListener","cancel","async","toStreamableRequest","request","onUploadStreaming","body","getReader","stream","chunk","headers","get","parseInt","Request","credentials","cache","mode","redirect","referrer","referrerPolicy","integrity","keepalive","duplex","toStreamableResponse","onDownloadStreaming","Response","DEFAULT_RETRY_OPTIONS","maxRetries","retryDelay","backoffFactor","retryStatusCodes","retryNetworkErrors","maxRetryDelay","shouldRetry","createHttpRequest","config","defaultHeaders","timeout","defaultTimeout","fetch","customFetch","serializeBody","customSerializeBody","serializeParams","customSerializeParams","onRequestMiddleware","onResponseMiddleware","options","params","pathParams","responseType","retryOptions","requestRetryOptions","urlObj","resolvedUrl","path","replace","_match","paramName","test","Object","keys","paramValue","stringValue","String","includes","generatePath","requestUrl","startsWith","baseUrlObj","URL","basePath","pathname","query","split","search","toString","constructUrl","baseRequestContext","Headers","fetchOptions","requestContext","contextCopy","createErrorMessage","createStandardizedError","serializedParams","searchParams","URLSearchParams","key","entries","Array","isArray","item","append","serializeQueryParams","queryString","slice","separator","newSearchParams","requestInit","contentType","serializedBody","isObjectLike","has","serialized","FormData","ArrayBuffer","Blob","serializeRequestBody","set","mergedRetryOptions","lastError","attempt","AbortController","timeoutId","setTimeout","abort","finalSignal","createCombinedSignal","clearTimeout","trackedRequest","trackedResponse","responseData","processResponse","middlewareResult","delay","calculateRetryDelay","sleep","fromEntries","requestedType","detectedType","finalType","json","text","blob","arrayBuffer","formData","responseClone","clone","ok","raw","retryCount","baseDelay","maxDelay","Math","pow","min","toJSON","context","ms","Promise","resolve","requestSignal","timeoutSignal","cleanup","aborted","combinedController","handleAbort","isStandardSchema","obj","validate","version","vendor","validateAndNormalizeBaseUrl","hasLocation","window","location","origin","href","endsWith","createSchemaableResponse","requestHandler","schemaValidator","basePromise","assign","promise","extractable","createExtractableResponse","then","validatedData","createHttpClient","result","issues","isSchema","args","post","put","patch","delete","http"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs.js","sources":["../src/errors.ts","../src/utils/streaming.ts","../src/core.ts","../src/utils/path.ts","../src/schema.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 statusCategory =\n status >= 500\n ? 'Server Error'\n : status >= 400\n ? 'Client Error'\n : status >= 300\n ? 'Redirect'\n : 'Success'\n\n const dataString = data ? JSON.stringify(data) : 'No response data'\n const truncatedData =\n dataString.length > 500\n ? dataString.substring(0, 500) + '...'\n : dataString\n\n const enhancedMessage = `HTTP ${statusCategory} (${status}): ${message}\nRequest: ${method} ${url}\nData: ${truncatedData}`\n\n super(enhancedMessage, { cause })\n this.status = status\n this.statusText = statusText\n this.data = data\n this.response = response\n this.url = url\n this.method = method\n }\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 const enhancedMessage = `${message}\nURL Template: ${url}\nExpected: [${requiredParams.map(p => `\"${p}\"`).join(', ')}], Actual: [${providedParams.map(p => `\"${p}\"`).join(', ')}]`\n\n super(enhancedMessage, { cause })\n this.url = url\n this.requiredParams = requiredParams\n this.providedParams = providedParams\n }\n}\n\nexport class MiddlewareError extends Error implements HttpClientError {\n public readonly name = 'MiddlewareError'\n public readonly type: 'request' | 'response'\n public readonly url?: string\n public readonly method?: string\n public override readonly cause?: Error\n\n constructor(\n message: string,\n type: 'request' | 'response',\n url?: string,\n method?: string,\n cause?: Error\n ) {\n const requestInfo = url ? `Request: ${method || 'UNKNOWN'} ${url}` : ''\n const enhancedMessage = requestInfo ? `${message}\\n${requestInfo}` : message\n\n super(enhancedMessage, { cause })\n this.type = type\n this.url = url\n this.method = method\n }\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\nexport class InvalidSchemaError extends Error implements HttpClientError {\n public readonly name = 'InvalidSchemaError'\n public readonly schema: unknown\n public override readonly cause?: Error\n\n constructor(message: string, schema: unknown, cause?: Error) {\n super(message, { cause })\n this.schema = schema\n }\n}\n\nexport class AsyncSchemaValidationError\n extends Error\n implements HttpClientError\n{\n public readonly name = 'AsyncSchemaValidationError'\n public readonly schema: unknown\n public override readonly cause?: Error\n\n constructor(message: string, schema: unknown, cause?: Error) {\n super(message, { cause })\n this.schema = schema\n }\n}\n\nexport class InvalidBaseUrlError extends Error implements HttpClientError {\n public readonly name = 'InvalidBaseUrlError'\n public readonly baseUrl: string\n public override readonly cause?: Error\n\n constructor(message: string, baseUrl: string, cause?: Error) {\n const enhancedMessage = `${message}\nBase URL: ${baseUrl}`\n\n super(enhancedMessage, { cause })\n this.baseUrl = baseUrl\n }\n}\n","import type { DownloadStreamingEvent, UploadStreamingEvent } from '../types'\n\nfunction createStreamingStream(\n reader: ReadableStreamDefaultReader<Uint8Array>,\n onChunk: (\n chunk: Uint8Array,\n totalBytes: number | undefined,\n transferredBytes: number\n ) => void,\n totalBytes: number | undefined,\n signal?: AbortSignal\n): ReadableStream<Uint8Array> {\n let transferredBytes = 0\n let readerReleased = false\n let isAborted = false\n\n const releaseReader = () => {\n if (!readerReleased) {\n readerReleased = true\n try {\n reader.releaseLock()\n } catch {\n // Reader might already be released, ignore\n }\n }\n }\n\n // Handle abort signal\n const abortHandler = () => {\n isAborted = true\n releaseReader()\n }\n\n signal?.addEventListener('abort', abortHandler)\n\n return new ReadableStream({\n async start(controller) {\n try {\n while (!isAborted) {\n const { done, value } = await reader.read()\n if (done) break\n\n transferredBytes += value.length\n onChunk(value, totalBytes, transferredBytes)\n controller.enqueue(value)\n }\n\n if (!isAborted) {\n controller.close()\n }\n } catch (error) {\n if (!isAborted) {\n controller.error(error)\n }\n throw error\n } finally {\n signal?.removeEventListener('abort', abortHandler)\n releaseReader()\n }\n },\n cancel() {\n isAborted = true\n signal?.removeEventListener('abort', abortHandler)\n releaseReader()\n },\n })\n}\n\n/**\n * Creates a request with upload streaming tracking\n */\nexport async function toStreamableRequest(\n request: Request,\n onUploadStreaming?: (event: UploadStreamingEvent) => void\n): Promise<Request> {\n if (!onUploadStreaming || !request.body) {\n return request\n }\n\n if (!request.body.getReader) {\n return request\n }\n\n const reader = request.body.getReader()\n const totalBytes = request.headers.get('content-length')\n ? parseInt(request.headers.get('content-length') || '0', 10)\n : undefined\n\n const stream = createStreamingStream(\n reader,\n (chunk, totalBytes, transferredBytes) => {\n onUploadStreaming({\n chunk,\n totalBytes,\n transferredBytes,\n })\n },\n totalBytes,\n request.signal\n )\n\n return new Request(request.url, {\n method: request.method,\n headers: request.headers,\n body: stream,\n signal: request.signal,\n credentials: request.credentials,\n cache: request.cache,\n mode: request.mode,\n redirect: request.redirect,\n referrer: request.referrer,\n referrerPolicy: request.referrerPolicy,\n integrity: request.integrity,\n keepalive: request.keepalive,\n duplex: 'half',\n } as RequestInit)\n}\n\n/**\n * Creates a response with download streaming tracking\n */\nexport async function toStreamableResponse(\n response: Response,\n onDownloadStreaming?: (event: DownloadStreamingEvent) => void\n): Promise<Response> {\n if (!onDownloadStreaming || !response.body) {\n return response\n }\n\n if (!response.body.getReader) {\n return response\n }\n\n const reader = response.body.getReader()\n const totalBytes = response.headers.get('content-length')\n ? parseInt(response.headers.get('content-length') || '0', 10)\n : undefined\n\n const stream = createStreamingStream(\n reader,\n (chunk, totalBytes, transferredBytes) => {\n onDownloadStreaming({\n chunk,\n totalBytes,\n transferredBytes,\n })\n },\n totalBytes\n )\n\n return new Response(stream, {\n status: response.status,\n statusText: response.statusText,\n headers: response.headers,\n })\n}\n","import {\n HttpError,\n MiddlewareError,\n NetworkError,\n SerializationError,\n TimeoutError,\n} from './errors'\nimport type { SchemaValidator } from './schema'\nimport type {\n CustomFetch,\n DownloadStreamingEvent,\n ExtendedRequestInit,\n HttpHeaders,\n HttpMethod,\n RequestContext,\n RequestParamsType,\n ResponseType,\n RetryOptions,\n SerializeBody,\n SerializeParams,\n UploadStreamingEvent,\n} from './types'\nimport {\n generatePath,\n toStreamableRequest,\n toStreamableResponse,\n type PathParams,\n} from './utils'\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: 30_000,\n shouldRetry: () => true,\n}\n\nexport interface HttpRequestOptions<\n TBody = unknown,\n TParams extends RequestParamsType = RequestParamsType,\n> {\n method?: HttpMethod\n headers?: HttpHeaders\n /** Query parameters */\n params?: TParams\n /** Path parameters for URL template */\n pathParams?: Record<string, string | number>\n /** Request body */\n body?: TBody\n timeout?: number\n signal?: AbortSignal\n /** Fetch options */\n credentials?: RequestCredentials\n cache?: RequestCache\n mode?: RequestMode\n redirect?: RequestRedirect\n /** Upload streaming tracking for this specific request */\n onUploadStreaming?: (event: UploadStreamingEvent) => void\n /** Download streaming tracking for this specific request */\n onDownloadStreaming?: (event: DownloadStreamingEvent) => void\n /** Response type override */\n responseType?: 'json' | 'text' | 'blob' | 'arrayBuffer' | 'formData'\n retryOptions?: RetryOptions\n}\n\nexport interface HttpClientConfig {\n /** Base URL for all requests */\n baseUrl?: string\n /** Default headers */\n headers?: HttpHeaders\n /** Default timeout */\n timeout?: number\n /** Schema validator */\n schemaValidator?: SchemaValidator\n /** Default retry options */\n retryOptions?: RetryOptions\n /** Custom fetch implementation */\n fetch?: CustomFetch\n /** Custom body serializer */\n serializeBody?: SerializeBody\n /** Custom params serializer */\n serializeParams?: SerializeParams\n /** Request middleware - can modify request before sending */\n onRequestMiddleware?: <TBody = unknown>(\n context: RequestContext<TBody>\n ) => RequestContext<TBody> | Promise<RequestContext<TBody>>\n /** Response middleware - can modify response after receiving */\n onResponseMiddleware?: (\n response: ResponseType<unknown>\n ) => ResponseType<unknown> | Promise<ResponseType<unknown>>\n}\n\n/**\n * Creates an HTTP request handler with the given configuration.\n * This is the core function that handles all HTTP requests with retry logic,\n * interceptors, and streaming.\n */\nexport function createHttpRequest(config: HttpClientConfig = {}) {\n const {\n baseUrl = '',\n headers: defaultHeaders = {},\n timeout: defaultTimeout = 30_000,\n fetch: customFetch = fetch,\n serializeBody: customSerializeBody,\n serializeParams: customSerializeParams,\n onRequestMiddleware,\n onResponseMiddleware,\n } = config\n\n return async function fetcher<\n Path extends string = string,\n TResponse = unknown,\n TBody = unknown,\n TParams extends RequestParamsType = RequestParamsType,\n >(\n url: Path,\n options: HttpRequestOptions<TBody, TParams> = {}\n ): Promise<ResponseType<TResponse>> {\n const {\n method = 'GET',\n headers = {},\n params,\n pathParams,\n body,\n timeout = defaultTimeout,\n signal,\n credentials,\n cache,\n mode,\n redirect,\n onUploadStreaming,\n onDownloadStreaming,\n responseType,\n retryOptions: requestRetryOptions,\n } = options\n\n let urlObj: URL | undefined\n let resolvedUrl = generatePath(url, pathParams as PathParams<Path>)\n\n if (baseUrl || params) {\n if (baseUrl) {\n resolvedUrl = constructUrl(baseUrl, resolvedUrl)\n urlObj = new URL(resolvedUrl)\n } else {\n urlObj = new URL(resolvedUrl)\n }\n }\n\n const baseRequestContext: RequestContext<TBody> = {\n url: resolvedUrl,\n method,\n params,\n headers: new Headers({ ...defaultHeaders, ...headers }),\n body,\n signal,\n fetchOptions: { credentials, cache, mode, redirect },\n }\n\n let requestContext: RequestContext<TBody> = baseRequestContext\n\n if (onRequestMiddleware) {\n try {\n // prevent middleware from mutating the original context\n const contextCopy: RequestContext<TBody> = {\n ...baseRequestContext,\n headers: new Headers(baseRequestContext.headers),\n fetchOptions: { ...baseRequestContext.fetchOptions },\n }\n\n requestContext = await onRequestMiddleware(contextCopy)\n\n if (requestContext.url !== resolvedUrl) {\n urlObj = new URL(requestContext.url)\n }\n } catch (error) {\n throw new MiddlewareError(\n createErrorMessage('Request middleware failed', error),\n 'request',\n requestContext.url,\n requestContext.method,\n createStandardizedError(error, 'Request middleware')\n )\n }\n }\n\n if (requestContext.params) {\n if (!urlObj) {\n urlObj = new URL(requestContext.url)\n }\n\n const serializedParams = customSerializeParams\n ? customSerializeParams(requestContext.params)\n : serializeQueryParams(requestContext.params)\n\n if (serializedParams) {\n if (customSerializeParams) {\n const queryString = serializedParams.startsWith('?')\n ? serializedParams.slice(1)\n : serializedParams\n const separator = urlObj.search ? '&' : '?'\n urlObj.search += separator + queryString\n } else {\n const newSearchParams = new URLSearchParams(serializedParams)\n for (const [key, value] of newSearchParams) {\n urlObj.searchParams.append(key, value)\n }\n }\n requestContext.url = urlObj.toString()\n }\n }\n\n const requestInit: ExtendedRequestInit = {\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 let body: BodyInit\n let contentType: string | undefined\n\n if (customSerializeBody) {\n const serializedBody = customSerializeBody(requestContext.body)\n if (serializedBody == null) {\n body = ''\n } else {\n body = serializedBody\n\n if (\n isObjectLike(requestContext.body) &&\n typeof serializedBody === 'string' &&\n !requestContext.headers.has('content-type')\n ) {\n contentType = 'application/json'\n }\n }\n } else {\n const serialized = serializeRequestBody(requestContext.body)\n body = serialized.body\n contentType = serialized.contentType\n }\n\n requestInit.body = body\n\n if (contentType) {\n requestContext.headers.set('content-type', contentType)\n }\n\n requestInit.duplex = 'half'\n }\n\n const mergedRetryOptions = {\n ...DEFAULT_RETRY_OPTIONS,\n ...config.retryOptions,\n ...requestRetryOptions,\n }\n const maxRetries = mergedRetryOptions.maxRetries\n let lastError: Error | undefined\n\n for (let attempt = 0; attempt <= maxRetries; attempt += 1) {\n const controller = new AbortController()\n const timeoutId = setTimeout(() => controller.abort(), timeout)\n\n const finalSignal = createCombinedSignal(\n requestContext.signal,\n controller.signal,\n () => clearTimeout(timeoutId)\n )\n\n try {\n const request = new Request(requestContext.url, requestInit)\n const trackedRequest = onUploadStreaming\n ? await toStreamableRequest(request, onUploadStreaming)\n : request\n\n const response = await customFetch(trackedRequest.url, {\n method: trackedRequest.method,\n headers: trackedRequest.headers,\n body: trackedRequest.body,\n signal: finalSignal,\n ...requestContext.fetchOptions,\n ...(trackedRequest.body && { duplex: 'half' }),\n } satisfies ExtendedRequestInit)\n\n const trackedResponse = onDownloadStreaming\n ? await toStreamableResponse(response, onDownloadStreaming)\n : response\n\n const responseData = await processResponse<TResponse>(trackedResponse, {\n responseType,\n method,\n url: requestContext.url,\n })\n\n if (onResponseMiddleware) {\n try {\n const middlewareResult = await onResponseMiddleware(responseData)\n if (\n !middlewareResult ||\n typeof middlewareResult !== 'object' ||\n !('data' in middlewareResult)\n ) {\n throw new MiddlewareError(\n 'Response middleware must return a valid ResponseType object',\n 'response',\n requestContext.url,\n method\n )\n }\n return middlewareResult as ResponseType<TResponse>\n } catch (error) {\n throw new MiddlewareError(\n createErrorMessage('Response middleware failed', error),\n 'response',\n requestContext.url,\n method,\n createStandardizedError(error, 'Response middleware')\n )\n }\n }\n\n return responseData\n } catch (error) {\n clearTimeout(timeoutId)\n lastError = createStandardizedError(error, 'Request execution')\n\n if (lastError.name === 'AbortError') {\n lastError = new TimeoutError(\n `Request timeout after ${timeout}ms`,\n lastError\n )\n }\n\n if (\n attempt >= maxRetries ||\n !(await shouldRetry(lastError, attempt, mergedRetryOptions))\n ) {\n throw lastError\n }\n\n const delay = calculateRetryDelay(attempt, mergedRetryOptions)\n await sleep(delay)\n }\n }\n\n throw new Error('Retry loop terminated unexpectedly')\n }\n}\n\nasync function processResponse<T = unknown>(\n response: Response,\n options: {\n responseType?: 'json' | 'text' | 'blob' | 'arrayBuffer' | 'formData'\n method: HttpMethod\n url: string\n }\n): Promise<ResponseType<T>> {\n const headers = Object.fromEntries(response.headers.entries())\n\n let data: unknown\n try {\n const requestedType = options.responseType\n const contentType = response.headers.get('content-type') ?? ''\n\n const detectedType:\n | 'json'\n | 'text'\n | 'arrayBuffer'\n | 'formData'\n | undefined = contentType.includes('application/json')\n ? 'json'\n : contentType.includes('text/')\n ? 'text'\n : contentType.includes('application/octet-stream') ||\n contentType.includes('application/pdf') ||\n contentType.includes('image/') ||\n contentType.includes('video/') ||\n contentType.includes('audio/')\n ? 'arrayBuffer'\n : contentType.includes('multipart/form-data') ||\n contentType.includes('application/x-www-form-urlencoded')\n ? 'formData'\n : undefined\n\n const finalType:\n | 'json'\n | 'text'\n | 'arrayBuffer'\n | 'blob'\n | 'formData'\n | undefined = requestedType ?? detectedType\n\n if (finalType === 'json') {\n data = await response.json()\n } else if (finalType === 'text') {\n data = await response.text()\n } else if (finalType === 'blob') {\n data = await response.blob()\n } else if (finalType === 'arrayBuffer') {\n data = await response.arrayBuffer()\n } else if (finalType === 'formData') {\n data = await response.formData()\n } else {\n const responseClone = response.clone()\n try {\n data = await response.json()\n } catch {\n data = await responseClone.text()\n }\n }\n } catch (error) {\n throw new SerializationError(\n createErrorMessage('Failed to parse response body', error),\n error instanceof Error ? error : undefined\n )\n }\n\n if (!response.ok) {\n throw new HttpError(\n `HTTP ${response.status} ${response.statusText}`,\n response.status,\n response.statusText,\n data,\n response,\n options.url,\n options.method\n )\n }\n\n return {\n data: data as T,\n status: response.status,\n statusText: response.statusText,\n headers,\n method: options.method,\n url: options.url,\n raw: response,\n }\n}\n\nasync function shouldRetry(\n error: Error,\n retryCount: number,\n retryOptions?: RetryOptions\n): Promise<boolean> {\n if (!retryOptions) return false\n\n if (retryOptions.shouldRetry) {\n return await retryOptions.shouldRetry(error, retryCount)\n }\n\n if (error instanceof HttpError) {\n return retryOptions.retryStatusCodes?.includes(error.status) ?? false\n }\n\n if (error instanceof NetworkError || error.name === 'TypeError') {\n return retryOptions.retryNetworkErrors ?? false\n }\n\n return false\n}\n\nfunction calculateRetryDelay(\n attempt: number,\n retryOptions?: RetryOptions\n): number {\n if (!retryOptions) return 0\n\n const baseDelay = retryOptions.retryDelay ?? 300\n const backoffFactor = retryOptions.backoffFactor ?? 2\n const maxDelay = retryOptions.maxRetryDelay ?? 30_000\n\n const delay = baseDelay * Math.pow(backoffFactor, attempt)\n return Math.min(delay, maxDelay)\n}\n\nfunction isObjectLike(\n value: unknown\n): value is Record<string, unknown> | unknown[] | { toJSON(): unknown } {\n return (\n (value !== null &&\n typeof value === 'object' &&\n value.constructor?.name === 'Object') ||\n Array.isArray(value) ||\n (value !== null &&\n typeof value === 'object' &&\n 'toJSON' in value &&\n typeof value.toJSON === 'function')\n )\n}\n\nfunction serializeQueryParams(params: RequestParamsType): string {\n const searchParams = new URLSearchParams()\n\n for (const [key, value] of Object.entries(params)) {\n if (Array.isArray(value)) {\n for (const item of value) {\n if (item !== undefined && item !== null) {\n searchParams.append(key, String(item))\n }\n }\n } else if (value !== undefined && value !== null) {\n searchParams.append(key, String(value))\n }\n }\n\n return searchParams.toString()\n}\n\nfunction serializeRequestBody(body: unknown): {\n body: BodyInit\n contentType?: string\n} {\n if (\n typeof body === 'string' ||\n body instanceof FormData ||\n body instanceof URLSearchParams ||\n body instanceof ArrayBuffer ||\n body instanceof Blob ||\n body instanceof ReadableStream\n ) {\n return { body: body }\n }\n\n if (isObjectLike(body)) {\n return {\n body: JSON.stringify(body),\n contentType: 'application/json',\n }\n }\n\n if (body === null || body === undefined) {\n return { body: '' }\n }\n\n return { body: String(body) }\n}\n\nfunction createErrorMessage(context: string, error: unknown): string {\n return `${context}: ${error instanceof Error ? error.message : String(error)}`\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms))\n}\n\nfunction createCombinedSignal(\n requestSignal?: AbortSignal,\n timeoutSignal?: AbortSignal,\n cleanup?: () => void\n): AbortSignal {\n if (!requestSignal && !timeoutSignal) {\n return new AbortController().signal\n }\n\n if (requestSignal?.aborted) {\n return requestSignal\n }\n\n const combinedController = new AbortController()\n\n const handleAbort = () => {\n cleanup?.()\n combinedController.abort()\n }\n\n requestSignal?.addEventListener('abort', handleAbort)\n timeoutSignal?.addEventListener('abort', handleAbort)\n\n return combinedController.signal\n}\n\nfunction createStandardizedError(error: unknown, context: string): Error {\n if (error instanceof Error) {\n return error\n }\n\n return new Error(`${context}: ${String(error)}`)\n}\n\nfunction constructUrl(baseUrl: string, requestUrl: string): string {\n if (requestUrl.startsWith('http://') || requestUrl.startsWith('https://')) {\n return requestUrl\n }\n\n const baseUrlObj = new URL(baseUrl)\n const basePath = baseUrlObj.pathname.replace(/\\/$/, '')\n const [path, query] = requestUrl.split('?')\n\n if (requestUrl.startsWith('/')) {\n baseUrlObj.pathname = basePath + path\n } else if (requestUrl) {\n baseUrlObj.pathname = basePath + '/' + path\n }\n\n if (query) {\n baseUrlObj.search = baseUrlObj.search\n ? `${baseUrlObj.search}&${query}`\n : `?${query}`\n }\n\n return baseUrlObj.toString()\n}\n","import { PathParameterError } from '../errors'\n\n/**\n * Strips protocol from URL (e.g., https://, http://)\n */\ntype StripProtocol<T extends string> = T extends `${string}://${infer After}`\n ? After\n : T\n\n/**\n * Strips host and optional port from URL, keeping only the path\n * Handles cases like \"localhost:3000/users\" -> \"/users\"\n */\ntype StripHost<T extends string> = T extends `${infer _Host}/${infer Path}`\n ? `/${Path}`\n : T\n\n/**\n * Strips query string from path (e.g., \"/users?x=1\" -> \"/users\")\n * Only strips ? that comes after the path, not ? that's part of path parameters\n */\ntype StripQuery<T extends string> = T extends `${infer Path}?${infer Query}`\n ? Query extends\n | `${string}=${string}`\n | `${string}&${string}`\n | `${string}=${string}&${string}`\n ? Path // Contains query parameters (has = or &)\n : Query extends `/${string}`\n ? T // It's another path segment, not a query\n : Query extends ``\n ? T // It's an optional param marker (?)\n : Path // Plain query params like ?param\n : T\n\n/**\n * Normalizes URL to path only, stripping protocol, host, port, and query\n */\ntype NormalizePath<T extends string> = StripQuery<StripHost<StripProtocol<T>>>\n\n/**\n * Removes optional suffix from param name (e.g., \":id?\" -> \"id\", \":id\" -> \"id\")\n */\ntype CleanParamName<S extends string> = S extends `:${infer Name}?`\n ? Name\n : S extends `:${infer Name}`\n ? Name\n : S\n\n/**\n * Extracts all path parameters from a route\n */\nexport type ExtractRouteParams<T extends string> =\n NormalizePath<T> extends `${infer _Before}:${infer AfterColon}`\n ? AfterColon extends `${infer Param}/${infer Rest}`\n ? CleanParamName<`:${Param}`> | ExtractRouteParams<`/${Rest}`>\n : CleanParamName<`:${AfterColon}`>\n : never\n\nexport type HasRequiredParams<T extends string> = [\n ExtractRouteParams<T>,\n] extends [never]\n ? false\n : true\n\n/**\n * PathParams type - extracts parameter names and their types\n */\nexport type PathParams<Path extends string> = {\n [K in ExtractRouteParams<Path>]: string | number\n}\n\n/**\n * RequirePathParams enforces pathParams when needed\n */\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(/:([^/\\s?#]+)\\??/g, (_match, paramName: string) => {\n // Validate parameter name\n if (!/^[a-zA-Z0-9_]+$/.test(paramName)) {\n throw new PathParameterError(\n `Invalid path parameter name: \"${paramName}\"`,\n path,\n [paramName],\n Object.keys(params)\n )\n }\n\n // Get and validate parameter value\n const paramValue = params[paramName as keyof PathParams<Path>]\n if (paramValue === undefined) {\n throw new PathParameterError(\n `Missing required path parameter: \"${paramName}\"`,\n path,\n [paramName],\n Object.keys(params)\n )\n }\n\n const stringValue = String(paramValue)\n if (stringValue.includes('/') || stringValue.includes('?')) {\n throw new PathParameterError(\n `Invalid path parameter value for \"${paramName}\": contains invalid characters`,\n path,\n [paramName],\n Object.keys(params)\n )\n }\n\n return stringValue\n })\n}\n","import type { StandardSchemaV1 } from '@standard-schema/spec'\nimport {\n AsyncSchemaValidationError,\n InvalidSchemaError,\n SchemaValidationError,\n} from './errors'\nimport { Schema } from './types'\n\n/**\n * Type guard to check if an object conforms to the Standard Schema V1 specification\n */\nfunction isStandardSchema(obj: unknown): obj is StandardSchemaV1 {\n return (\n obj !== null &&\n (typeof obj === 'object' || typeof obj === 'function') &&\n '~standard' in obj &&\n typeof obj['~standard'] === 'object' &&\n obj['~standard'] !== null &&\n 'validate' in obj['~standard'] &&\n typeof obj['~standard'].validate === 'function' &&\n 'version' in obj['~standard'] &&\n typeof obj['~standard'].version === 'number' &&\n 'vendor' in obj['~standard'] &&\n typeof obj['~standard'].vendor === 'string'\n )\n}\n\n/**\n * Interface for schema validators that can validate data against schemas.\n *\n * This interface allows you to create custom schema validators that work\n * with different validation libraries (Zod, Valibot, Arktype, etc.).\n */\nexport interface SchemaValidator {\n /**\n * Validate data against a schema.\n *\n * @template T - The expected type after validation\n * @param schema - The schema to validate against\n * @param data - The data to validate\n * @returns The validated data with the correct type\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 InvalidSchemaError(\n 'Schema must implement the Standard Schema interface',\n schema\n )\n }\n\n const result = schema['~standard'].validate(data)\n\n if (result instanceof Promise) {\n throw new AsyncSchemaValidationError(\n 'Async Standard Schema validation is not supported in this context',\n schema\n )\n }\n\n if (result.issues) {\n throw new SchemaValidationError(\n JSON.stringify(result.issues),\n schema,\n data\n )\n }\n\n return result.value as T\n },\n\n isSchema(obj: unknown): boolean {\n return isStandardSchema(obj)\n },\n }\n}\n","import type { HttpClientConfig, HttpRequestOptions } from './core'\nimport { createHttpRequest } from './core'\nimport { InvalidBaseUrlError, SchemaValidationError } from './errors'\nimport { createSchemaValidator } from './schema'\nimport type {\n EnforcedPathParamsOptions,\n ExtractableResponse,\n InferSchemaOutput,\n RequestParamsType,\n ResponseType,\n Schema,\n SchemaableResponse,\n} from './types'\nimport type { HasRequiredParams } from './utils'\n\nfunction validateAndNormalizeBaseUrl(baseUrl?: string): string {\n const hasLocation =\n typeof window !== 'undefined' &&\n typeof window.location !== 'undefined' &&\n window.location.origin !== 'null'\n\n if (!baseUrl) {\n // In browser environment, default to location.origin for relative paths\n return hasLocation ? window.location.origin : ''\n }\n\n if (baseUrl.startsWith('/')) {\n // In Node.js or non-browser environments, relative paths are preserved as-is\n return hasLocation\n ? new URL(baseUrl, window.location.origin).href.replace(/\\/$/, '')\n : baseUrl.replace(/\\/$/, '')\n }\n\n try {\n new URL(baseUrl)\n } catch {\n throw new InvalidBaseUrlError(\n `Invalid baseUrl: \"${baseUrl}\". Must be a valid absolute URL or relative path starting with \"/\".`,\n baseUrl\n )\n }\n\n return baseUrl.endsWith('/') ? baseUrl.slice(0, -1) : baseUrl\n}\n\nfunction createExtractableResponse<T>(\n promise: Promise<ResponseType<T>>\n): ExtractableResponse<T> {\n const extractable = promise as ExtractableResponse<T>\n extractable.data = async () => (await promise).data\n extractable.void = async () => {\n await promise\n }\n return extractable\n}\n\n/**\n * Creates a chainable response that allows adding schema validation and extracting data\n */\nfunction createSchemaableResponse<\n Path extends string,\n TResponse,\n TBody,\n TParams extends RequestParamsType,\n>(\n url: Path,\n options: HttpRequestOptions<TBody, TParams>,\n requestHandler: ReturnType<typeof createHttpRequest>,\n schemaValidator: ReturnType<typeof createSchemaValidator>\n): SchemaableResponse<TResponse> {\n const basePromise = requestHandler<Path, TResponse, TBody, TParams>(\n url,\n options\n )\n\n return Object.assign(basePromise, {\n schema<S extends Schema>(\n schema: S\n ): ExtractableResponse<InferSchemaOutput<S>> {\n const validatedPromise = basePromise.then(response => {\n try {\n const validatedData = schemaValidator.validate(\n schema,\n response.data\n ) as InferSchemaOutput<S>\n return {\n ...response,\n data: validatedData,\n }\n } catch (error) {\n throw new SchemaValidationError(\n `Schema validation failed: ${\n error instanceof Error ? error.message : String(error)\n }`,\n schema,\n response.data,\n error instanceof Error ? error : undefined\n )\n }\n })\n\n return createExtractableResponse(validatedPromise)\n },\n async data() {\n return (await basePromise).data\n },\n async void() {\n await basePromise\n },\n })\n}\n\n/**\n * Creates a complete HTTP client with method builders\n */\nexport function createHttpClient(config: HttpClientConfig = {}) {\n const validatedConfig = {\n ...config,\n baseUrl: validateAndNormalizeBaseUrl(config.baseUrl),\n }\n\n const requestHandler = createHttpRequest(validatedConfig)\n const schemaValidator = config.schemaValidator ?? createSchemaValidator()\n\n function get<\n Path extends string = string,\n TParams extends RequestParamsType = RequestParamsType,\n >(\n url: Path,\n ...args: HasRequiredParams<Path> extends true\n ? [options: EnforcedPathParamsOptions<never, TParams, Path>]\n : [options?: EnforcedPathParamsOptions<never, TParams, Path>]\n ) {\n return createSchemaableResponse<Path, unknown, never, TParams>(\n url,\n {\n ...(args[0] ?? {}),\n method: 'GET',\n },\n requestHandler,\n schemaValidator\n )\n }\n\n return {\n get,\n\n post: <\n Path extends string = string,\n TBody = unknown,\n TParams extends RequestParamsType = RequestParamsType,\n >(\n url: Path,\n body?: TBody,\n ...args: HasRequiredParams<Path> extends true\n ? [options: EnforcedPathParamsOptions<TBody, TParams, Path>]\n : [options?: EnforcedPathParamsOptions<TBody, TParams, Path>]\n ) =>\n createSchemaableResponse<Path, unknown, TBody, TParams>(\n url,\n {\n ...(args[0] ?? {}),\n method: 'POST',\n body,\n },\n requestHandler,\n schemaValidator\n ),\n\n put: <\n Path extends string = string,\n TBody = unknown,\n TParams extends RequestParamsType = RequestParamsType,\n >(\n url: Path,\n body?: TBody,\n ...args: HasRequiredParams<Path> extends true\n ? [options: EnforcedPathParamsOptions<TBody, TParams, Path>]\n : [options?: EnforcedPathParamsOptions<TBody, TParams, Path>]\n ) =>\n createSchemaableResponse<Path, unknown, TBody, TParams>(\n url,\n {\n ...(args[0] ?? {}),\n method: 'PUT',\n body,\n },\n requestHandler,\n schemaValidator\n ),\n\n patch: <\n Path extends string = string,\n TBody = unknown,\n TParams extends RequestParamsType = RequestParamsType,\n >(\n url: Path,\n body?: TBody,\n ...args: HasRequiredParams<Path> extends true\n ? [options: EnforcedPathParamsOptions<TBody, TParams, Path>]\n : [options?: EnforcedPathParamsOptions<TBody, TParams, Path>]\n ) =>\n createSchemaableResponse<Path, unknown, TBody, TParams>(\n url,\n {\n ...(args[0] ?? {}),\n method: 'PATCH',\n body,\n },\n requestHandler,\n schemaValidator\n ),\n\n delete: <\n Path extends string = string,\n TParams extends RequestParamsType = RequestParamsType,\n >(\n url: Path,\n ...args: HasRequiredParams<Path> extends true\n ? [options: EnforcedPathParamsOptions<never, TParams, Path>]\n : [options?: EnforcedPathParamsOptions<never, TParams, Path>]\n ) =>\n createSchemaableResponse<Path, unknown, never, TParams>(\n url,\n {\n ...(args[0] ?? {}),\n method: 'DELETE',\n },\n requestHandler,\n schemaValidator\n ),\n\n /**\n * Generic request method for custom HTTP methods and full control\n */\n request: <\n Path extends string = string,\n TBody = unknown,\n TParams extends RequestParamsType = RequestParamsType,\n >(\n url: Path,\n options?: HttpRequestOptions<TBody, TParams>\n ) =>\n createSchemaableResponse<Path, unknown, TBody, TParams>(\n url,\n options ?? {},\n requestHandler,\n schemaValidator\n ),\n }\n}\n\nexport const http = createHttpClient()\n"],"names":["HttpError","Error","name","status","statusText","data","response","url","method","cause","constructor","message","statusCategory","dataString","JSON","stringify","super","length","substring","this","NetworkError","SchemaValidationError","schema","TimeoutError","PathParameterError","requiredParams","providedParams","map","p","join","MiddlewareError","type","requestInfo","SerializationError","InvalidSchemaError","AsyncSchemaValidationError","InvalidBaseUrlError","baseUrl","createStreamingStream","reader","onChunk","totalBytes","signal","transferredBytes","readerReleased","isAborted","releaseReader","releaseLock","abortHandler","addEventListener","ReadableStream","start","controller","done","value","read","enqueue","close","error","removeEventListener","cancel","async","toStreamableRequest","request","onUploadStreaming","body","getReader","stream","chunk","headers","get","parseInt","Request","credentials","cache","mode","redirect","referrer","referrerPolicy","integrity","keepalive","duplex","toStreamableResponse","onDownloadStreaming","Response","DEFAULT_RETRY_OPTIONS","maxRetries","retryDelay","backoffFactor","retryStatusCodes","retryNetworkErrors","maxRetryDelay","shouldRetry","createHttpRequest","config","defaultHeaders","timeout","defaultTimeout","fetch","customFetch","serializeBody","customSerializeBody","serializeParams","customSerializeParams","onRequestMiddleware","onResponseMiddleware","options","params","pathParams","responseType","retryOptions","requestRetryOptions","urlObj","resolvedUrl","path","replace","_match","paramName","test","Object","keys","paramValue","stringValue","String","includes","generatePath","requestUrl","startsWith","baseUrlObj","URL","basePath","pathname","query","split","search","toString","constructUrl","baseRequestContext","Headers","fetchOptions","requestContext","contextCopy","createErrorMessage","createStandardizedError","serializedParams","searchParams","URLSearchParams","key","entries","Array","isArray","item","append","serializeQueryParams","queryString","slice","separator","newSearchParams","requestInit","contentType","serializedBody","isObjectLike","has","serialized","FormData","ArrayBuffer","Blob","serializeRequestBody","set","mergedRetryOptions","lastError","attempt","AbortController","timeoutId","setTimeout","abort","finalSignal","createCombinedSignal","clearTimeout","trackedRequest","trackedResponse","responseData","processResponse","middlewareResult","delay","calculateRetryDelay","sleep","fromEntries","requestedType","detectedType","finalType","json","text","blob","arrayBuffer","formData","responseClone","clone","ok","raw","retryCount","baseDelay","maxDelay","Math","pow","min","toJSON","context","ms","Promise","resolve","requestSignal","timeoutSignal","cleanup","aborted","combinedController","handleAbort","isStandardSchema","obj","validate","version","vendor","validateAndNormalizeBaseUrl","hasLocation","window","location","origin","href","endsWith","createSchemaableResponse","requestHandler","schemaValidator","basePromise","assign","promise","extractable","void","createExtractableResponse","then","validatedData","createHttpClient","result","issues","isSchema","args","post","put","patch","delete","http"],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
package/dist/index.es.js
CHANGED
|
@@ -665,6 +665,9 @@ function validateAndNormalizeBaseUrl(baseUrl) {
|
|
|
665
665
|
function createExtractableResponse(promise) {
|
|
666
666
|
const extractable = promise;
|
|
667
667
|
extractable.data = async () => (await promise).data;
|
|
668
|
+
extractable.void = async () => {
|
|
669
|
+
await promise;
|
|
670
|
+
};
|
|
668
671
|
return extractable;
|
|
669
672
|
}
|
|
670
673
|
function createSchemaableResponse(url, options, requestHandler, schemaValidator) {
|
|
@@ -697,6 +700,9 @@ function createSchemaableResponse(url, options, requestHandler, schemaValidator)
|
|
|
697
700
|
},
|
|
698
701
|
async data() {
|
|
699
702
|
return (await basePromise).data;
|
|
703
|
+
},
|
|
704
|
+
async void() {
|
|
705
|
+
await basePromise;
|
|
700
706
|
}
|
|
701
707
|
});
|
|
702
708
|
}
|
package/dist/index.es.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.es.js","sources":["../src/errors.ts","../src/utils/path.ts","../src/utils/streaming.ts","../src/core.ts","../src/schema.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 statusCategory =\n status >= 500\n ? 'Server Error'\n : status >= 400\n ? 'Client Error'\n : status >= 300\n ? 'Redirect'\n : 'Success'\n\n const dataString = data ? JSON.stringify(data) : 'No response data'\n const truncatedData =\n dataString.length > 500\n ? dataString.substring(0, 500) + '...'\n : dataString\n\n const enhancedMessage = `HTTP ${statusCategory} (${status}): ${message}\nRequest: ${method} ${url}\nData: ${truncatedData}`\n\n super(enhancedMessage, { cause })\n this.status = status\n this.statusText = statusText\n this.data = data\n this.response = response\n this.url = url\n this.method = method\n }\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 const enhancedMessage = `${message}\nURL Template: ${url}\nExpected: [${requiredParams.map(p => `\"${p}\"`).join(', ')}], Actual: [${providedParams.map(p => `\"${p}\"`).join(', ')}]`\n\n super(enhancedMessage, { cause })\n this.url = url\n this.requiredParams = requiredParams\n this.providedParams = providedParams\n }\n}\n\nexport class MiddlewareError extends Error implements HttpClientError {\n public readonly name = 'MiddlewareError'\n public readonly type: 'request' | 'response'\n public readonly url?: string\n public readonly method?: string\n public override readonly cause?: Error\n\n constructor(\n message: string,\n type: 'request' | 'response',\n url?: string,\n method?: string,\n cause?: Error\n ) {\n const requestInfo = url ? `Request: ${method || 'UNKNOWN'} ${url}` : ''\n const enhancedMessage = requestInfo ? `${message}\\n${requestInfo}` : message\n\n super(enhancedMessage, { cause })\n this.type = type\n this.url = url\n this.method = method\n }\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\nexport class InvalidSchemaError extends Error implements HttpClientError {\n public readonly name = 'InvalidSchemaError'\n public readonly schema: unknown\n public override readonly cause?: Error\n\n constructor(message: string, schema: unknown, cause?: Error) {\n super(message, { cause })\n this.schema = schema\n }\n}\n\nexport class AsyncSchemaValidationError\n extends Error\n implements HttpClientError\n{\n public readonly name = 'AsyncSchemaValidationError'\n public readonly schema: unknown\n public override readonly cause?: Error\n\n constructor(message: string, schema: unknown, cause?: Error) {\n super(message, { cause })\n this.schema = schema\n }\n}\n\nexport class InvalidBaseUrlError extends Error implements HttpClientError {\n public readonly name = 'InvalidBaseUrlError'\n public readonly baseUrl: string\n public override readonly cause?: Error\n\n constructor(message: string, baseUrl: string, cause?: Error) {\n const enhancedMessage = `${message}\nBase URL: ${baseUrl}`\n\n super(enhancedMessage, { cause })\n this.baseUrl = baseUrl\n }\n}\n","import { PathParameterError } from '../errors'\n\n/**\n * Strips protocol from URL (e.g., https://, http://)\n */\ntype StripProtocol<T extends string> = T extends `${string}://${infer After}`\n ? After\n : T\n\n/**\n * Strips host and optional port from URL, keeping only the path\n * Handles cases like \"localhost:3000/users\" -> \"/users\"\n */\ntype StripHost<T extends string> = T extends `${infer _Host}/${infer Path}`\n ? `/${Path}`\n : T\n\n/**\n * Strips query string from path (e.g., \"/users?x=1\" -> \"/users\")\n * Only strips ? that comes after the path, not ? that's part of path parameters\n */\ntype StripQuery<T extends string> = T extends `${infer Path}?${infer Query}`\n ? Query extends\n | `${string}=${string}`\n | `${string}&${string}`\n | `${string}=${string}&${string}`\n ? Path // Contains query parameters (has = or &)\n : Query extends `/${string}`\n ? T // It's another path segment, not a query\n : Query extends ``\n ? T // It's an optional param marker (?)\n : Path // Plain query params like ?param\n : T\n\n/**\n * Normalizes URL to path only, stripping protocol, host, port, and query\n */\ntype NormalizePath<T extends string> = StripQuery<StripHost<StripProtocol<T>>>\n\n/**\n * Removes optional suffix from param name (e.g., \":id?\" -> \"id\", \":id\" -> \"id\")\n */\ntype CleanParamName<S extends string> = S extends `:${infer Name}?`\n ? Name\n : S extends `:${infer Name}`\n ? Name\n : S\n\n/**\n * Extracts all path parameters from a route\n */\nexport type ExtractRouteParams<T extends string> =\n NormalizePath<T> extends `${infer _Before}:${infer AfterColon}`\n ? AfterColon extends `${infer Param}/${infer Rest}`\n ? CleanParamName<`:${Param}`> | ExtractRouteParams<`/${Rest}`>\n : CleanParamName<`:${AfterColon}`>\n : never\n\nexport type HasRequiredParams<T extends string> = [\n ExtractRouteParams<T>,\n] extends [never]\n ? false\n : true\n\n/**\n * PathParams type - extracts parameter names and their types\n */\nexport type PathParams<Path extends string> = {\n [K in ExtractRouteParams<Path>]: string | number\n}\n\n/**\n * RequirePathParams enforces pathParams when needed\n */\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(/:([^/\\s?#]+)\\??/g, (_match, paramName: string) => {\n // Validate parameter name\n if (!/^[a-zA-Z0-9_]+$/.test(paramName)) {\n throw new PathParameterError(\n `Invalid path parameter name: \"${paramName}\"`,\n path,\n [paramName],\n Object.keys(params)\n )\n }\n\n // Get and validate parameter value\n const paramValue = params[paramName as keyof PathParams<Path>]\n if (paramValue === undefined) {\n throw new PathParameterError(\n `Missing required path parameter: \"${paramName}\"`,\n path,\n [paramName],\n Object.keys(params)\n )\n }\n\n const stringValue = String(paramValue)\n if (stringValue.includes('/') || stringValue.includes('?')) {\n throw new PathParameterError(\n `Invalid path parameter value for \"${paramName}\": contains invalid characters`,\n path,\n [paramName],\n Object.keys(params)\n )\n }\n\n return stringValue\n })\n}\n","import type { DownloadStreamingEvent, UploadStreamingEvent } from '../types'\n\nfunction createStreamingStream(\n reader: ReadableStreamDefaultReader<Uint8Array>,\n onChunk: (\n chunk: Uint8Array,\n totalBytes: number | undefined,\n transferredBytes: number\n ) => void,\n totalBytes: number | undefined,\n signal?: AbortSignal\n): ReadableStream<Uint8Array> {\n let transferredBytes = 0\n let readerReleased = false\n let isAborted = false\n\n const releaseReader = () => {\n if (!readerReleased) {\n readerReleased = true\n try {\n reader.releaseLock()\n } catch {\n // Reader might already be released, ignore\n }\n }\n }\n\n // Handle abort signal\n const abortHandler = () => {\n isAborted = true\n releaseReader()\n }\n\n signal?.addEventListener('abort', abortHandler)\n\n return new ReadableStream({\n async start(controller) {\n try {\n while (!isAborted) {\n const { done, value } = await reader.read()\n if (done) break\n\n transferredBytes += value.length\n onChunk(value, totalBytes, transferredBytes)\n controller.enqueue(value)\n }\n\n if (!isAborted) {\n controller.close()\n }\n } catch (error) {\n if (!isAborted) {\n controller.error(error)\n }\n throw error\n } finally {\n signal?.removeEventListener('abort', abortHandler)\n releaseReader()\n }\n },\n cancel() {\n isAborted = true\n signal?.removeEventListener('abort', abortHandler)\n releaseReader()\n },\n })\n}\n\n/**\n * Creates a request with upload streaming tracking\n */\nexport async function toStreamableRequest(\n request: Request,\n onUploadStreaming?: (event: UploadStreamingEvent) => void\n): Promise<Request> {\n if (!onUploadStreaming || !request.body) {\n return request\n }\n\n if (!request.body.getReader) {\n return request\n }\n\n const reader = request.body.getReader()\n const totalBytes = request.headers.get('content-length')\n ? parseInt(request.headers.get('content-length') || '0', 10)\n : undefined\n\n const stream = createStreamingStream(\n reader,\n (chunk, totalBytes, transferredBytes) => {\n onUploadStreaming({\n chunk,\n totalBytes,\n transferredBytes,\n })\n },\n totalBytes,\n request.signal\n )\n\n return new Request(request.url, {\n method: request.method,\n headers: request.headers,\n body: stream,\n signal: request.signal,\n credentials: request.credentials,\n cache: request.cache,\n mode: request.mode,\n redirect: request.redirect,\n referrer: request.referrer,\n referrerPolicy: request.referrerPolicy,\n integrity: request.integrity,\n keepalive: request.keepalive,\n duplex: 'half',\n } as RequestInit)\n}\n\n/**\n * Creates a response with download streaming tracking\n */\nexport async function toStreamableResponse(\n response: Response,\n onDownloadStreaming?: (event: DownloadStreamingEvent) => void\n): Promise<Response> {\n if (!onDownloadStreaming || !response.body) {\n return response\n }\n\n if (!response.body.getReader) {\n return response\n }\n\n const reader = response.body.getReader()\n const totalBytes = response.headers.get('content-length')\n ? parseInt(response.headers.get('content-length') || '0', 10)\n : undefined\n\n const stream = createStreamingStream(\n reader,\n (chunk, totalBytes, transferredBytes) => {\n onDownloadStreaming({\n chunk,\n totalBytes,\n transferredBytes,\n })\n },\n totalBytes\n )\n\n return new Response(stream, {\n status: response.status,\n statusText: response.statusText,\n headers: response.headers,\n })\n}\n","import {\n HttpError,\n MiddlewareError,\n NetworkError,\n SerializationError,\n TimeoutError,\n} from './errors'\nimport type { SchemaValidator } from './schema'\nimport type {\n CustomFetch,\n DownloadStreamingEvent,\n ExtendedRequestInit,\n HttpHeaders,\n HttpMethod,\n RequestContext,\n RequestParamsType,\n ResponseType,\n RetryOptions,\n SerializeBody,\n SerializeParams,\n UploadStreamingEvent,\n} from './types'\nimport {\n generatePath,\n toStreamableRequest,\n toStreamableResponse,\n type PathParams,\n} from './utils'\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: 30_000,\n shouldRetry: () => true,\n}\n\nexport interface HttpRequestOptions<\n TBody = unknown,\n TParams extends RequestParamsType = RequestParamsType,\n> {\n method?: HttpMethod\n headers?: HttpHeaders\n /** Query parameters */\n params?: TParams\n /** Path parameters for URL template */\n pathParams?: Record<string, string | number>\n /** Request body */\n body?: TBody\n timeout?: number\n signal?: AbortSignal\n /** Fetch options */\n credentials?: RequestCredentials\n cache?: RequestCache\n mode?: RequestMode\n redirect?: RequestRedirect\n /** Upload streaming tracking for this specific request */\n onUploadStreaming?: (event: UploadStreamingEvent) => void\n /** Download streaming tracking for this specific request */\n onDownloadStreaming?: (event: DownloadStreamingEvent) => void\n /** Response type override */\n responseType?: 'json' | 'text' | 'blob' | 'arrayBuffer' | 'formData'\n retryOptions?: RetryOptions\n}\n\nexport interface HttpClientConfig {\n /** Base URL for all requests */\n baseUrl?: string\n /** Default headers */\n headers?: HttpHeaders\n /** Default timeout */\n timeout?: number\n /** Schema validator */\n schemaValidator?: SchemaValidator\n /** Default retry options */\n retryOptions?: RetryOptions\n /** Custom fetch implementation */\n fetch?: CustomFetch\n /** Custom body serializer */\n serializeBody?: SerializeBody\n /** Custom params serializer */\n serializeParams?: SerializeParams\n /** Request middleware - can modify request before sending */\n onRequestMiddleware?: <TBody = unknown>(\n context: RequestContext<TBody>\n ) => RequestContext<TBody> | Promise<RequestContext<TBody>>\n /** Response middleware - can modify response after receiving */\n onResponseMiddleware?: (\n response: ResponseType<unknown>\n ) => ResponseType<unknown> | Promise<ResponseType<unknown>>\n}\n\n/**\n * Creates an HTTP request handler with the given configuration.\n * This is the core function that handles all HTTP requests with retry logic,\n * interceptors, and streaming.\n */\nexport function createHttpRequest(config: HttpClientConfig = {}) {\n const {\n baseUrl = '',\n headers: defaultHeaders = {},\n timeout: defaultTimeout = 30_000,\n fetch: customFetch = fetch,\n serializeBody: customSerializeBody,\n serializeParams: customSerializeParams,\n onRequestMiddleware,\n onResponseMiddleware,\n } = config\n\n return async function fetcher<\n Path extends string = string,\n TResponse = unknown,\n TBody = unknown,\n TParams extends RequestParamsType = RequestParamsType,\n >(\n url: Path,\n options: HttpRequestOptions<TBody, TParams> = {}\n ): Promise<ResponseType<TResponse>> {\n const {\n method = 'GET',\n headers = {},\n params,\n pathParams,\n body,\n timeout = defaultTimeout,\n signal,\n credentials,\n cache,\n mode,\n redirect,\n onUploadStreaming,\n onDownloadStreaming,\n responseType,\n retryOptions: requestRetryOptions,\n } = options\n\n let urlObj: URL | undefined\n let resolvedUrl = generatePath(url, pathParams as PathParams<Path>)\n\n if (baseUrl || params) {\n if (baseUrl) {\n resolvedUrl = constructUrl(baseUrl, resolvedUrl)\n urlObj = new URL(resolvedUrl)\n } else {\n urlObj = new URL(resolvedUrl)\n }\n }\n\n const baseRequestContext: RequestContext<TBody> = {\n url: resolvedUrl,\n method,\n params,\n headers: new Headers({ ...defaultHeaders, ...headers }),\n body,\n signal,\n fetchOptions: { credentials, cache, mode, redirect },\n }\n\n let requestContext: RequestContext<TBody> = baseRequestContext\n\n if (onRequestMiddleware) {\n try {\n // prevent middleware from mutating the original context\n const contextCopy: RequestContext<TBody> = {\n ...baseRequestContext,\n headers: new Headers(baseRequestContext.headers),\n fetchOptions: { ...baseRequestContext.fetchOptions },\n }\n\n requestContext = await onRequestMiddleware(contextCopy)\n\n if (requestContext.url !== resolvedUrl) {\n urlObj = new URL(requestContext.url)\n }\n } catch (error) {\n throw new MiddlewareError(\n createErrorMessage('Request middleware failed', error),\n 'request',\n requestContext.url,\n requestContext.method,\n createStandardizedError(error, 'Request middleware')\n )\n }\n }\n\n if (requestContext.params) {\n if (!urlObj) {\n urlObj = new URL(requestContext.url)\n }\n\n const serializedParams = customSerializeParams\n ? customSerializeParams(requestContext.params)\n : serializeQueryParams(requestContext.params)\n\n if (serializedParams) {\n if (customSerializeParams) {\n const queryString = serializedParams.startsWith('?')\n ? serializedParams.slice(1)\n : serializedParams\n const separator = urlObj.search ? '&' : '?'\n urlObj.search += separator + queryString\n } else {\n const newSearchParams = new URLSearchParams(serializedParams)\n for (const [key, value] of newSearchParams) {\n urlObj.searchParams.append(key, value)\n }\n }\n requestContext.url = urlObj.toString()\n }\n }\n\n const requestInit: ExtendedRequestInit = {\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 let body: BodyInit\n let contentType: string | undefined\n\n if (customSerializeBody) {\n const serializedBody = customSerializeBody(requestContext.body)\n if (serializedBody == null) {\n body = ''\n } else {\n body = serializedBody\n\n if (\n isObjectLike(requestContext.body) &&\n typeof serializedBody === 'string' &&\n !requestContext.headers.has('content-type')\n ) {\n contentType = 'application/json'\n }\n }\n } else {\n const serialized = serializeRequestBody(requestContext.body)\n body = serialized.body\n contentType = serialized.contentType\n }\n\n requestInit.body = body\n\n if (contentType) {\n requestContext.headers.set('content-type', contentType)\n }\n\n requestInit.duplex = 'half'\n }\n\n const mergedRetryOptions = {\n ...DEFAULT_RETRY_OPTIONS,\n ...config.retryOptions,\n ...requestRetryOptions,\n }\n const maxRetries = mergedRetryOptions.maxRetries\n let lastError: Error | undefined\n\n for (let attempt = 0; attempt <= maxRetries; attempt += 1) {\n const controller = new AbortController()\n const timeoutId = setTimeout(() => controller.abort(), timeout)\n\n const finalSignal = createCombinedSignal(\n requestContext.signal,\n controller.signal,\n () => clearTimeout(timeoutId)\n )\n\n try {\n const request = new Request(requestContext.url, requestInit)\n const trackedRequest = onUploadStreaming\n ? await toStreamableRequest(request, onUploadStreaming)\n : request\n\n const response = await customFetch(trackedRequest.url, {\n method: trackedRequest.method,\n headers: trackedRequest.headers,\n body: trackedRequest.body,\n signal: finalSignal,\n ...requestContext.fetchOptions,\n ...(trackedRequest.body && { duplex: 'half' }),\n } satisfies ExtendedRequestInit)\n\n const trackedResponse = onDownloadStreaming\n ? await toStreamableResponse(response, onDownloadStreaming)\n : response\n\n const responseData = await processResponse<TResponse>(trackedResponse, {\n responseType,\n method,\n url: requestContext.url,\n })\n\n if (onResponseMiddleware) {\n try {\n const middlewareResult = await onResponseMiddleware(responseData)\n if (\n !middlewareResult ||\n typeof middlewareResult !== 'object' ||\n !('data' in middlewareResult)\n ) {\n throw new MiddlewareError(\n 'Response middleware must return a valid ResponseType object',\n 'response',\n requestContext.url,\n method\n )\n }\n return middlewareResult as ResponseType<TResponse>\n } catch (error) {\n throw new MiddlewareError(\n createErrorMessage('Response middleware failed', error),\n 'response',\n requestContext.url,\n method,\n createStandardizedError(error, 'Response middleware')\n )\n }\n }\n\n return responseData\n } catch (error) {\n clearTimeout(timeoutId)\n lastError = createStandardizedError(error, 'Request execution')\n\n if (lastError.name === 'AbortError') {\n lastError = new TimeoutError(\n `Request timeout after ${timeout}ms`,\n lastError\n )\n }\n\n if (\n attempt >= maxRetries ||\n !(await shouldRetry(lastError, attempt, mergedRetryOptions))\n ) {\n throw lastError\n }\n\n const delay = calculateRetryDelay(attempt, mergedRetryOptions)\n await sleep(delay)\n }\n }\n\n throw new Error('Retry loop terminated unexpectedly')\n }\n}\n\nasync function processResponse<T = unknown>(\n response: Response,\n options: {\n responseType?: 'json' | 'text' | 'blob' | 'arrayBuffer' | 'formData'\n method: HttpMethod\n url: string\n }\n): Promise<ResponseType<T>> {\n const headers = Object.fromEntries(response.headers.entries())\n\n let data: unknown\n try {\n const requestedType = options.responseType\n const contentType = response.headers.get('content-type') ?? ''\n\n const detectedType:\n | 'json'\n | 'text'\n | 'arrayBuffer'\n | 'formData'\n | undefined = contentType.includes('application/json')\n ? 'json'\n : contentType.includes('text/')\n ? 'text'\n : contentType.includes('application/octet-stream') ||\n contentType.includes('application/pdf') ||\n contentType.includes('image/') ||\n contentType.includes('video/') ||\n contentType.includes('audio/')\n ? 'arrayBuffer'\n : contentType.includes('multipart/form-data') ||\n contentType.includes('application/x-www-form-urlencoded')\n ? 'formData'\n : undefined\n\n const finalType:\n | 'json'\n | 'text'\n | 'arrayBuffer'\n | 'blob'\n | 'formData'\n | undefined = requestedType ?? detectedType\n\n if (finalType === 'json') {\n data = await response.json()\n } else if (finalType === 'text') {\n data = await response.text()\n } else if (finalType === 'blob') {\n data = await response.blob()\n } else if (finalType === 'arrayBuffer') {\n data = await response.arrayBuffer()\n } else if (finalType === 'formData') {\n data = await response.formData()\n } else {\n const responseClone = response.clone()\n try {\n data = await response.json()\n } catch {\n data = await responseClone.text()\n }\n }\n } catch (error) {\n throw new SerializationError(\n createErrorMessage('Failed to parse response body', error),\n error instanceof Error ? error : undefined\n )\n }\n\n if (!response.ok) {\n throw new HttpError(\n `HTTP ${response.status} ${response.statusText}`,\n response.status,\n response.statusText,\n data,\n response,\n options.url,\n options.method\n )\n }\n\n return {\n data: data as T,\n status: response.status,\n statusText: response.statusText,\n headers,\n method: options.method,\n url: options.url,\n raw: response,\n }\n}\n\nasync function shouldRetry(\n error: Error,\n retryCount: number,\n retryOptions?: RetryOptions\n): Promise<boolean> {\n if (!retryOptions) return false\n\n if (retryOptions.shouldRetry) {\n return await retryOptions.shouldRetry(error, retryCount)\n }\n\n if (error instanceof HttpError) {\n return retryOptions.retryStatusCodes?.includes(error.status) ?? false\n }\n\n if (error instanceof NetworkError || error.name === 'TypeError') {\n return retryOptions.retryNetworkErrors ?? false\n }\n\n return false\n}\n\nfunction calculateRetryDelay(\n attempt: number,\n retryOptions?: RetryOptions\n): number {\n if (!retryOptions) return 0\n\n const baseDelay = retryOptions.retryDelay ?? 300\n const backoffFactor = retryOptions.backoffFactor ?? 2\n const maxDelay = retryOptions.maxRetryDelay ?? 30_000\n\n const delay = baseDelay * Math.pow(backoffFactor, attempt)\n return Math.min(delay, maxDelay)\n}\n\nfunction isObjectLike(\n value: unknown\n): value is Record<string, unknown> | unknown[] | { toJSON(): unknown } {\n return (\n (value !== null &&\n typeof value === 'object' &&\n value.constructor?.name === 'Object') ||\n Array.isArray(value) ||\n (value !== null &&\n typeof value === 'object' &&\n 'toJSON' in value &&\n typeof value.toJSON === 'function')\n )\n}\n\nfunction serializeQueryParams(params: RequestParamsType): string {\n const searchParams = new URLSearchParams()\n\n for (const [key, value] of Object.entries(params)) {\n if (Array.isArray(value)) {\n for (const item of value) {\n if (item !== undefined && item !== null) {\n searchParams.append(key, String(item))\n }\n }\n } else if (value !== undefined && value !== null) {\n searchParams.append(key, String(value))\n }\n }\n\n return searchParams.toString()\n}\n\nfunction serializeRequestBody(body: unknown): {\n body: BodyInit\n contentType?: string\n} {\n if (\n typeof body === 'string' ||\n body instanceof FormData ||\n body instanceof URLSearchParams ||\n body instanceof ArrayBuffer ||\n body instanceof Blob ||\n body instanceof ReadableStream\n ) {\n return { body: body }\n }\n\n if (isObjectLike(body)) {\n return {\n body: JSON.stringify(body),\n contentType: 'application/json',\n }\n }\n\n if (body === null || body === undefined) {\n return { body: '' }\n }\n\n return { body: String(body) }\n}\n\nfunction createErrorMessage(context: string, error: unknown): string {\n return `${context}: ${error instanceof Error ? error.message : String(error)}`\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms))\n}\n\nfunction createCombinedSignal(\n requestSignal?: AbortSignal,\n timeoutSignal?: AbortSignal,\n cleanup?: () => void\n): AbortSignal {\n if (!requestSignal && !timeoutSignal) {\n return new AbortController().signal\n }\n\n if (requestSignal?.aborted) {\n return requestSignal\n }\n\n const combinedController = new AbortController()\n\n const handleAbort = () => {\n cleanup?.()\n combinedController.abort()\n }\n\n requestSignal?.addEventListener('abort', handleAbort)\n timeoutSignal?.addEventListener('abort', handleAbort)\n\n return combinedController.signal\n}\n\nfunction createStandardizedError(error: unknown, context: string): Error {\n if (error instanceof Error) {\n return error\n }\n\n return new Error(`${context}: ${String(error)}`)\n}\n\nfunction constructUrl(baseUrl: string, requestUrl: string): string {\n if (requestUrl.startsWith('http://') || requestUrl.startsWith('https://')) {\n return requestUrl\n }\n\n const baseUrlObj = new URL(baseUrl)\n const basePath = baseUrlObj.pathname.replace(/\\/$/, '')\n const [path, query] = requestUrl.split('?')\n\n if (requestUrl.startsWith('/')) {\n baseUrlObj.pathname = basePath + path\n } else if (requestUrl) {\n baseUrlObj.pathname = basePath + '/' + path\n }\n\n if (query) {\n baseUrlObj.search = baseUrlObj.search\n ? `${baseUrlObj.search}&${query}`\n : `?${query}`\n }\n\n return baseUrlObj.toString()\n}\n","import type { StandardSchemaV1 } from '@standard-schema/spec'\nimport {\n AsyncSchemaValidationError,\n InvalidSchemaError,\n SchemaValidationError,\n} from './errors'\nimport { Schema } from './types'\n\n/**\n * Type guard to check if an object conforms to the Standard Schema V1 specification\n */\nfunction isStandardSchema(obj: unknown): obj is StandardSchemaV1 {\n return (\n obj !== null &&\n (typeof obj === 'object' || typeof obj === 'function') &&\n '~standard' in obj &&\n typeof obj['~standard'] === 'object' &&\n obj['~standard'] !== null &&\n 'validate' in obj['~standard'] &&\n typeof obj['~standard'].validate === 'function' &&\n 'version' in obj['~standard'] &&\n typeof obj['~standard'].version === 'number' &&\n 'vendor' in obj['~standard'] &&\n typeof obj['~standard'].vendor === 'string'\n )\n}\n\n/**\n * Interface for schema validators that can validate data against schemas.\n *\n * This interface allows you to create custom schema validators that work\n * with different validation libraries (Zod, Valibot, Arktype, etc.).\n */\nexport interface SchemaValidator {\n /**\n * Validate data against a schema.\n *\n * @template T - The expected type after validation\n * @param schema - The schema to validate against\n * @param data - The data to validate\n * @returns The validated data with the correct type\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 InvalidSchemaError(\n 'Schema must implement the Standard Schema interface',\n schema\n )\n }\n\n const result = schema['~standard'].validate(data)\n\n if (result instanceof Promise) {\n throw new AsyncSchemaValidationError(\n 'Async Standard Schema validation is not supported in this context',\n schema\n )\n }\n\n if (result.issues) {\n throw new SchemaValidationError(\n JSON.stringify(result.issues),\n schema,\n data\n )\n }\n\n return result.value as T\n },\n\n isSchema(obj: unknown): boolean {\n return isStandardSchema(obj)\n },\n }\n}\n","import type { HttpClientConfig, HttpRequestOptions } from './core'\nimport { createHttpRequest } from './core'\nimport { InvalidBaseUrlError, SchemaValidationError } from './errors'\nimport { createSchemaValidator } from './schema'\nimport type {\n EnforcedPathParamsOptions,\n ExtractableResponse,\n InferSchemaOutput,\n RequestParamsType,\n ResponseType,\n Schema,\n SchemaableResponse,\n} from './types'\nimport type { HasRequiredParams } from './utils'\n\nfunction validateAndNormalizeBaseUrl(baseUrl?: string): string {\n const hasLocation =\n typeof window !== 'undefined' &&\n typeof window.location !== 'undefined' &&\n window.location.origin !== 'null'\n\n if (!baseUrl) {\n // In browser environment, default to location.origin for relative paths\n return hasLocation ? window.location.origin : ''\n }\n\n if (baseUrl.startsWith('/')) {\n // In Node.js or non-browser environments, relative paths are preserved as-is\n return hasLocation\n ? new URL(baseUrl, window.location.origin).href.replace(/\\/$/, '')\n : baseUrl.replace(/\\/$/, '')\n }\n\n try {\n new URL(baseUrl)\n } catch {\n throw new InvalidBaseUrlError(\n `Invalid baseUrl: \"${baseUrl}\". Must be a valid absolute URL or relative path starting with \"/\".`,\n baseUrl\n )\n }\n\n return baseUrl.endsWith('/') ? baseUrl.slice(0, -1) : baseUrl\n}\n\nfunction createExtractableResponse<T>(\n promise: Promise<ResponseType<T>>\n): ExtractableResponse<T> {\n const extractable = promise as ExtractableResponse<T>\n extractable.data = async () => (await promise).data\n return extractable\n}\n\n/**\n * Creates a chainable response that allows adding schema validation and extracting data\n */\nfunction createSchemaableResponse<\n Path extends string,\n TResponse,\n TBody,\n TParams extends RequestParamsType,\n>(\n url: Path,\n options: HttpRequestOptions<TBody, TParams>,\n requestHandler: ReturnType<typeof createHttpRequest>,\n schemaValidator: ReturnType<typeof createSchemaValidator>\n): SchemaableResponse<TResponse> {\n const basePromise = requestHandler<Path, TResponse, TBody, TParams>(\n url,\n options\n )\n\n return Object.assign(basePromise, {\n schema<S extends Schema>(\n schema: S\n ): ExtractableResponse<InferSchemaOutput<S>> {\n const validatedPromise = basePromise.then(response => {\n try {\n const validatedData = schemaValidator.validate(\n schema,\n response.data\n ) as InferSchemaOutput<S>\n return {\n ...response,\n data: validatedData,\n }\n } catch (error) {\n throw new SchemaValidationError(\n `Schema validation failed: ${\n error instanceof Error ? error.message : String(error)\n }`,\n schema,\n response.data,\n error instanceof Error ? error : undefined\n )\n }\n })\n\n return createExtractableResponse(validatedPromise)\n },\n async data() {\n return (await basePromise).data\n },\n })\n}\n\n/**\n * Creates a complete HTTP client with method builders\n */\nexport function createHttpClient(config: HttpClientConfig = {}) {\n const validatedConfig = {\n ...config,\n baseUrl: validateAndNormalizeBaseUrl(config.baseUrl),\n }\n\n const requestHandler = createHttpRequest(validatedConfig)\n const schemaValidator = config.schemaValidator ?? createSchemaValidator()\n\n function get<\n Path extends string = string,\n TParams extends RequestParamsType = RequestParamsType,\n >(\n url: Path,\n ...args: HasRequiredParams<Path> extends true\n ? [options: EnforcedPathParamsOptions<never, TParams, Path>]\n : [options?: EnforcedPathParamsOptions<never, TParams, Path>]\n ) {\n return createSchemaableResponse<Path, unknown, never, TParams>(\n url,\n {\n ...(args[0] ?? {}),\n method: 'GET',\n },\n requestHandler,\n schemaValidator\n )\n }\n\n return {\n get,\n\n post: <\n Path extends string = string,\n TBody = unknown,\n TParams extends RequestParamsType = RequestParamsType,\n >(\n url: Path,\n body?: TBody,\n ...args: HasRequiredParams<Path> extends true\n ? [options: EnforcedPathParamsOptions<TBody, TParams, Path>]\n : [options?: EnforcedPathParamsOptions<TBody, TParams, Path>]\n ) =>\n createSchemaableResponse<Path, unknown, TBody, TParams>(\n url,\n {\n ...(args[0] ?? {}),\n method: 'POST',\n body,\n },\n requestHandler,\n schemaValidator\n ),\n\n put: <\n Path extends string = string,\n TBody = unknown,\n TParams extends RequestParamsType = RequestParamsType,\n >(\n url: Path,\n body?: TBody,\n ...args: HasRequiredParams<Path> extends true\n ? [options: EnforcedPathParamsOptions<TBody, TParams, Path>]\n : [options?: EnforcedPathParamsOptions<TBody, TParams, Path>]\n ) =>\n createSchemaableResponse<Path, unknown, TBody, TParams>(\n url,\n {\n ...(args[0] ?? {}),\n method: 'PUT',\n body,\n },\n requestHandler,\n schemaValidator\n ),\n\n patch: <\n Path extends string = string,\n TBody = unknown,\n TParams extends RequestParamsType = RequestParamsType,\n >(\n url: Path,\n body?: TBody,\n ...args: HasRequiredParams<Path> extends true\n ? [options: EnforcedPathParamsOptions<TBody, TParams, Path>]\n : [options?: EnforcedPathParamsOptions<TBody, TParams, Path>]\n ) =>\n createSchemaableResponse<Path, unknown, TBody, TParams>(\n url,\n {\n ...(args[0] ?? {}),\n method: 'PATCH',\n body,\n },\n requestHandler,\n schemaValidator\n ),\n\n delete: <\n Path extends string = string,\n TParams extends RequestParamsType = RequestParamsType,\n >(\n url: Path,\n ...args: HasRequiredParams<Path> extends true\n ? [options: EnforcedPathParamsOptions<never, TParams, Path>]\n : [options?: EnforcedPathParamsOptions<never, TParams, Path>]\n ) =>\n createSchemaableResponse<Path, unknown, never, TParams>(\n url,\n {\n ...(args[0] ?? {}),\n method: 'DELETE',\n },\n requestHandler,\n schemaValidator\n ),\n\n /**\n * Generic request method for custom HTTP methods and full control\n */\n request: <\n Path extends string = string,\n TBody = unknown,\n TParams extends RequestParamsType = RequestParamsType,\n >(\n url: Path,\n options?: HttpRequestOptions<TBody, TParams>\n ) =>\n createSchemaableResponse<Path, unknown, TBody, TParams>(\n url,\n options ?? {},\n requestHandler,\n schemaValidator\n ),\n }\n}\n\nexport const http = createHttpClient()\n"],"names":["totalBytes","body"],"mappings":"AAOO,MAAM,kBACH,MAEV;AAAA,EACkB,OAAO;AAAA,EACP;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACS;AAAA,EAEzB,YACE,SACA,QACA,YACA,MACA,UACA,KACA,QACA,OACA;AACA,UAAM,iBACJ,UAAU,MACN,iBACA,UAAU,MACR,iBACA,UAAU,MACR,aACA;AAEV,UAAM,aAAa,OAAO,KAAK,UAAU,IAAI,IAAI;AACjD,UAAM,gBACJ,WAAW,SAAS,MAChB,WAAW,UAAU,GAAG,GAAG,IAAI,QAC/B;AAEN,UAAM,kBAAkB,QAAQ,cAAc,KAAK,MAAM,MAAM,OAAO;AAAA,WAC/D,MAAM,IAAI,GAAG;AAAA,QAChB,aAAa;AAEjB,UAAM,iBAAiB,EAAE,OAAO;AAChC,SAAK,SAAS;AACd,SAAK,aAAa;AAClB,SAAK,OAAO;AACZ,SAAK,WAAW;AAChB,SAAK,MAAM;AACX,SAAK,SAAS;AAAA,EAChB;AACF;AAEO,MAAM,qBAAqB,MAAiC;AAAA,EACjD,OAAO;AAAA,EACE;AAAA,EAEzB,YAAY,SAAiB,OAAe;AAC1C,UAAM,SAAS,EAAE,OAAO;AAAA,EAC1B;AACF;AAEO,MAAM,8BAA8B,MAAiC;AAAA,EAC1D,OAAO;AAAA,EACP;AAAA,EACA;AAAA,EACS;AAAA,EAEzB,YAAY,SAAiB,QAAiB,MAAe,OAAe;AAC1E,UAAM,SAAS,EAAE,OAAO;AACxB,SAAK,SAAS;AACd,SAAK,OAAO;AAAA,EACd;AACF;AAEO,MAAM,qBAAqB,MAAiC;AAAA,EACjD,OAAO;AAAA,EACE;AAAA,EAEzB,YAAY,SAAiB,OAAe;AAC1C,UAAM,SAAS,EAAE,OAAO;AAAA,EAC1B;AACF;AAEO,MAAM,2BAA2B,MAAiC;AAAA,EACvD,OAAO;AAAA,EACP;AAAA,EACA;AAAA,EACA;AAAA,EACS;AAAA,EAEzB,YACE,SACA,KACA,gBACA,gBACA,OACA;AACA,UAAM,kBAAkB,GAAG,OAAO;AAAA,gBACtB,GAAG;AAAA,aACN,eAAe,IAAI,CAAA,MAAK,IAAI,CAAC,GAAG,EAAE,KAAK,IAAI,CAAC,eAAe,eAAe,IAAI,OAAK,IAAI,CAAC,GAAG,EAAE,KAAK,IAAI,CAAC;AAEhH,UAAM,iBAAiB,EAAE,OAAO;AAChC,SAAK,MAAM;AACX,SAAK,iBAAiB;AACtB,SAAK,iBAAiB;AAAA,EACxB;AACF;AAEO,MAAM,wBAAwB,MAAiC;AAAA,EACpD,OAAO;AAAA,EACP;AAAA,EACA;AAAA,EACA;AAAA,EACS;AAAA,EAEzB,YACE,SACA,MACA,KACA,QACA,OACA;AACA,UAAM,cAAc,MAAM,YAAY,UAAU,SAAS,IAAI,GAAG,KAAK;AACrE,UAAM,kBAAkB,cAAc,GAAG,OAAO;AAAA,EAAK,WAAW,KAAK;AAErE,UAAM,iBAAiB,EAAE,OAAO;AAChC,SAAK,OAAO;AACZ,SAAK,MAAM;AACX,SAAK,SAAS;AAAA,EAChB;AACF;AAEO,MAAM,2BAA2B,MAAiC;AAAA,EACvD,OAAO;AAAA,EACE;AAAA,EAEzB,YAAY,SAAiB,OAAe;AAC1C,UAAM,SAAS,EAAE,OAAO;AAAA,EAC1B;AACF;AAEO,MAAM,2BAA2B,MAAiC;AAAA,EACvD,OAAO;AAAA,EACP;AAAA,EACS;AAAA,EAEzB,YAAY,SAAiB,QAAiB,OAAe;AAC3D,UAAM,SAAS,EAAE,OAAO;AACxB,SAAK,SAAS;AAAA,EAChB;AACF;AAEO,MAAM,mCACH,MAEV;AAAA,EACkB,OAAO;AAAA,EACP;AAAA,EACS;AAAA,EAEzB,YAAY,SAAiB,QAAiB,OAAe;AAC3D,UAAM,SAAS,EAAE,OAAO;AACxB,SAAK,SAAS;AAAA,EAChB;AACF;AAEO,MAAM,4BAA4B,MAAiC;AAAA,EACxD,OAAO;AAAA,EACP;AAAA,EACS;AAAA,EAEzB,YAAY,SAAiB,SAAiB,OAAe;AAC3D,UAAM,kBAAkB,GAAG,OAAO;AAAA,YAC1B,OAAO;AAEf,UAAM,iBAAiB,EAAE,OAAO;AAChC,SAAK,UAAU;AAAA,EACjB;AACF;AChGO,SAAS,aACd,MACA,SAA2B,IACnB;AACR,SAAO,KAAK,QAAQ,oBAAoB,CAAC,QAAQ,cAAsB;AAErE,QAAI,CAAC,kBAAkB,KAAK,SAAS,GAAG;AACtC,YAAM,IAAI;AAAA,QACR,iCAAiC,SAAS;AAAA,QAC1C;AAAA,QACA,CAAC,SAAS;AAAA,QACV,OAAO,KAAK,MAAM;AAAA,MAAA;AAAA,IAEtB;AAGA,UAAM,aAAa,OAAO,SAAmC;AAC7D,QAAI,eAAe,QAAW;AAC5B,YAAM,IAAI;AAAA,QACR,qCAAqC,SAAS;AAAA,QAC9C;AAAA,QACA,CAAC,SAAS;AAAA,QACV,OAAO,KAAK,MAAM;AAAA,MAAA;AAAA,IAEtB;AAEA,UAAM,cAAc,OAAO,UAAU;AACrC,QAAI,YAAY,SAAS,GAAG,KAAK,YAAY,SAAS,GAAG,GAAG;AAC1D,YAAM,IAAI;AAAA,QACR,qCAAqC,SAAS;AAAA,QAC9C;AAAA,QACA,CAAC,SAAS;AAAA,QACV,OAAO,KAAK,MAAM;AAAA,MAAA;AAAA,IAEtB;AAEA,WAAO;AAAA,EACT,CAAC;AACH;AC7HA,SAAS,sBACP,QACA,SAKA,YACA,QAC4B;AAC5B,MAAI,mBAAmB;AACvB,MAAI,iBAAiB;AACrB,MAAI,YAAY;AAEhB,QAAM,gBAAgB,MAAM;AAC1B,QAAI,CAAC,gBAAgB;AACnB,uBAAiB;AACjB,UAAI;AACF,eAAO,YAAA;AAAA,MACT,QAAQ;AAAA,MAER;AAAA,IACF;AAAA,EACF;AAGA,QAAM,eAAe,MAAM;AACzB,gBAAY;AACZ,kBAAA;AAAA,EACF;AAEA,UAAQ,iBAAiB,SAAS,YAAY;AAE9C,SAAO,IAAI,eAAe;AAAA,IACxB,MAAM,MAAM,YAAY;AACtB,UAAI;AACF,eAAO,CAAC,WAAW;AACjB,gBAAM,EAAE,MAAM,MAAA,IAAU,MAAM,OAAO,KAAA;AACrC,cAAI,KAAM;AAEV,8BAAoB,MAAM;AAC1B,kBAAQ,OAAO,YAAY,gBAAgB;AAC3C,qBAAW,QAAQ,KAAK;AAAA,QAC1B;AAEA,YAAI,CAAC,WAAW;AACd,qBAAW,MAAA;AAAA,QACb;AAAA,MACF,SAAS,OAAO;AACd,YAAI,CAAC,WAAW;AACd,qBAAW,MAAM,KAAK;AAAA,QACxB;AACA,cAAM;AAAA,MACR,UAAA;AACE,gBAAQ,oBAAoB,SAAS,YAAY;AACjD,sBAAA;AAAA,MACF;AAAA,IACF;AAAA,IACA,SAAS;AACP,kBAAY;AACZ,cAAQ,oBAAoB,SAAS,YAAY;AACjD,oBAAA;AAAA,IACF;AAAA,EAAA,CACD;AACH;AAKA,eAAsB,oBACpB,SACA,mBACkB;AAClB,MAAI,CAAC,qBAAqB,CAAC,QAAQ,MAAM;AACvC,WAAO;AAAA,EACT;AAEA,MAAI,CAAC,QAAQ,KAAK,WAAW;AAC3B,WAAO;AAAA,EACT;AAEA,QAAM,SAAS,QAAQ,KAAK,UAAA;AAC5B,QAAM,aAAa,QAAQ,QAAQ,IAAI,gBAAgB,IACnD,SAAS,QAAQ,QAAQ,IAAI,gBAAgB,KAAK,KAAK,EAAE,IACzD;AAEJ,QAAM,SAAS;AAAA,IACb;AAAA,IACA,CAAC,OAAOA,aAAY,qBAAqB;AACvC,wBAAkB;AAAA,QAChB;AAAA,QACA,YAAAA;AAAAA,QACA;AAAA,MAAA,CACD;AAAA,IACH;AAAA,IACA;AAAA,IACA,QAAQ;AAAA,EAAA;AAGV,SAAO,IAAI,QAAQ,QAAQ,KAAK;AAAA,IAC9B,QAAQ,QAAQ;AAAA,IAChB,SAAS,QAAQ;AAAA,IACjB,MAAM;AAAA,IACN,QAAQ,QAAQ;AAAA,IAChB,aAAa,QAAQ;AAAA,IACrB,OAAO,QAAQ;AAAA,IACf,MAAM,QAAQ;AAAA,IACd,UAAU,QAAQ;AAAA,IAClB,UAAU,QAAQ;AAAA,IAClB,gBAAgB,QAAQ;AAAA,IACxB,WAAW,QAAQ;AAAA,IACnB,WAAW,QAAQ;AAAA,IACnB,QAAQ;AAAA,EAAA,CACM;AAClB;AAKA,eAAsB,qBACpB,UACA,qBACmB;AACnB,MAAI,CAAC,uBAAuB,CAAC,SAAS,MAAM;AAC1C,WAAO;AAAA,EACT;AAEA,MAAI,CAAC,SAAS,KAAK,WAAW;AAC5B,WAAO;AAAA,EACT;AAEA,QAAM,SAAS,SAAS,KAAK,UAAA;AAC7B,QAAM,aAAa,SAAS,QAAQ,IAAI,gBAAgB,IACpD,SAAS,SAAS,QAAQ,IAAI,gBAAgB,KAAK,KAAK,EAAE,IAC1D;AAEJ,QAAM,SAAS;AAAA,IACb;AAAA,IACA,CAAC,OAAOA,aAAY,qBAAqB;AACvC,0BAAoB;AAAA,QAClB;AAAA,QACA,YAAAA;AAAAA,QACA;AAAA,MAAA,CACD;AAAA,IACH;AAAA,IACA;AAAA,EAAA;AAGF,SAAO,IAAI,SAAS,QAAQ;AAAA,IAC1B,QAAQ,SAAS;AAAA,IACjB,YAAY,SAAS;AAAA,IACrB,SAAS,SAAS;AAAA,EAAA,CACnB;AACH;AC9HA,MAAM,wBAAgD;AAAA,EACpD,YAAY;AAAA,EACZ,YAAY;AAAA,EACZ,eAAe;AAAA,EACf,kBAAkB,CAAC,KAAK,KAAK,KAAK,KAAK,GAAG;AAAA,EAC1C,oBAAoB;AAAA,EACpB,eAAe;AAAA,EACf,aAAa,MAAM;AACrB;AA8DO,SAAS,kBAAkB,SAA2B,IAAI;AAC/D,QAAM;AAAA,IACJ,UAAU;AAAA,IACV,SAAS,iBAAiB,CAAA;AAAA,IAC1B,SAAS,iBAAiB;AAAA,IAC1B,OAAO,cAAc;AAAA,IACrB,eAAe;AAAA,IACf,iBAAiB;AAAA,IACjB;AAAA,IACA;AAAA,EAAA,IACE;AAEJ,SAAO,eAAe,QAMpB,KACA,UAA8C,CAAA,GACZ;AAClC,UAAM;AAAA,MACJ,SAAS;AAAA,MACT,UAAU,CAAA;AAAA,MACV;AAAA,MACA;AAAA,MACA;AAAA,MACA,UAAU;AAAA,MACV;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,cAAc;AAAA,IAAA,IACZ;AAEJ,QAAI;AACJ,QAAI,cAAc,aAAa,KAAK,UAA8B;AAElE,QAAI,WAAW,QAAQ;AACrB,UAAI,SAAS;AACX,sBAAc,aAAa,SAAS,WAAW;AAC/C,iBAAS,IAAI,IAAI,WAAW;AAAA,MAC9B,OAAO;AACL,iBAAS,IAAI,IAAI,WAAW;AAAA,MAC9B;AAAA,IACF;AAEA,UAAM,qBAA4C;AAAA,MAChD,KAAK;AAAA,MACL;AAAA,MACA;AAAA,MACA,SAAS,IAAI,QAAQ,EAAE,GAAG,gBAAgB,GAAG,SAAS;AAAA,MACtD;AAAA,MACA;AAAA,MACA,cAAc,EAAE,aAAa,OAAO,MAAM,SAAA;AAAA,IAAS;AAGrD,QAAI,iBAAwC;AAE5C,QAAI,qBAAqB;AACvB,UAAI;AAEF,cAAM,cAAqC;AAAA,UACzC,GAAG;AAAA,UACH,SAAS,IAAI,QAAQ,mBAAmB,OAAO;AAAA,UAC/C,cAAc,EAAE,GAAG,mBAAmB,aAAA;AAAA,QAAa;AAGrD,yBAAiB,MAAM,oBAAoB,WAAW;AAEtD,YAAI,eAAe,QAAQ,aAAa;AACtC,mBAAS,IAAI,IAAI,eAAe,GAAG;AAAA,QACrC;AAAA,MACF,SAAS,OAAO;AACd,cAAM,IAAI;AAAA,UACR,mBAAmB,6BAA6B,KAAK;AAAA,UACrD;AAAA,UACA,eAAe;AAAA,UACf,eAAe;AAAA,UACf,wBAAwB,OAAO,oBAAoB;AAAA,QAAA;AAAA,MAEvD;AAAA,IACF;AAEA,QAAI,eAAe,QAAQ;AACzB,UAAI,CAAC,QAAQ;AACX,iBAAS,IAAI,IAAI,eAAe,GAAG;AAAA,MACrC;AAEA,YAAM,mBAAmB,wBACrB,sBAAsB,eAAe,MAAM,IAC3C,qBAAqB,eAAe,MAAM;AAE9C,UAAI,kBAAkB;AACpB,YAAI,uBAAuB;AACzB,gBAAM,cAAc,iBAAiB,WAAW,GAAG,IAC/C,iBAAiB,MAAM,CAAC,IACxB;AACJ,gBAAM,YAAY,OAAO,SAAS,MAAM;AACxC,iBAAO,UAAU,YAAY;AAAA,QAC/B,OAAO;AACL,gBAAM,kBAAkB,IAAI,gBAAgB,gBAAgB;AAC5D,qBAAW,CAAC,KAAK,KAAK,KAAK,iBAAiB;AAC1C,mBAAO,aAAa,OAAO,KAAK,KAAK;AAAA,UACvC;AAAA,QACF;AACA,uBAAe,MAAM,OAAO,SAAA;AAAA,MAC9B;AAAA,IACF;AAEA,UAAM,cAAmC;AAAA,MACvC,QAAQ,eAAe;AAAA,MACvB,SAAS,eAAe;AAAA,MACxB,GAAG,eAAe;AAAA,IAAA;AAGpB,QACE,eAAe,SAAS,WACvB,eAAe,WAAW,UACzB,eAAe,WAAW,SAC1B,eAAe,WAAW,UAC5B;AACA,UAAIC;AACJ,UAAI;AAEJ,UAAI,qBAAqB;AACvB,cAAM,iBAAiB,oBAAoB,eAAe,IAAI;AAC9D,YAAI,kBAAkB,MAAM;AAC1BA,kBAAO;AAAA,QACT,OAAO;AACLA,kBAAO;AAEP,cACE,aAAa,eAAe,IAAI,KAChC,OAAO,mBAAmB,YAC1B,CAAC,eAAe,QAAQ,IAAI,cAAc,GAC1C;AACA,0BAAc;AAAA,UAChB;AAAA,QACF;AAAA,MACF,OAAO;AACL,cAAM,aAAa,qBAAqB,eAAe,IAAI;AAC3DA,gBAAO,WAAW;AAClB,sBAAc,WAAW;AAAA,MAC3B;AAEA,kBAAY,OAAOA;AAEnB,UAAI,aAAa;AACf,uBAAe,QAAQ,IAAI,gBAAgB,WAAW;AAAA,MACxD;AAEA,kBAAY,SAAS;AAAA,IACvB;AAEA,UAAM,qBAAqB;AAAA,MACzB,GAAG;AAAA,MACH,GAAG,OAAO;AAAA,MACV,GAAG;AAAA,IAAA;AAEL,UAAM,aAAa,mBAAmB;AACtC,QAAI;AAEJ,aAAS,UAAU,GAAG,WAAW,YAAY,WAAW,GAAG;AACzD,YAAM,aAAa,IAAI,gBAAA;AACvB,YAAM,YAAY,WAAW,MAAM,WAAW,MAAA,GAAS,OAAO;AAE9D,YAAM,cAAc;AAAA,QAClB,eAAe;AAAA,QACf,WAAW;AAAA,QACX,MAAM,aAAa,SAAS;AAAA,MAAA;AAG9B,UAAI;AACF,cAAM,UAAU,IAAI,QAAQ,eAAe,KAAK,WAAW;AAC3D,cAAM,iBAAiB,oBACnB,MAAM,oBAAoB,SAAS,iBAAiB,IACpD;AAEJ,cAAM,WAAW,MAAM,YAAY,eAAe,KAAK;AAAA,UACrD,QAAQ,eAAe;AAAA,UACvB,SAAS,eAAe;AAAA,UACxB,MAAM,eAAe;AAAA,UACrB,QAAQ;AAAA,UACR,GAAG,eAAe;AAAA,UAClB,GAAI,eAAe,QAAQ,EAAE,QAAQ,OAAA;AAAA,QAAO,CACf;AAE/B,cAAM,kBAAkB,sBACpB,MAAM,qBAAqB,UAAU,mBAAmB,IACxD;AAEJ,cAAM,eAAe,MAAM,gBAA2B,iBAAiB;AAAA,UACrE;AAAA,UACA;AAAA,UACA,KAAK,eAAe;AAAA,QAAA,CACrB;AAED,YAAI,sBAAsB;AACxB,cAAI;AACF,kBAAM,mBAAmB,MAAM,qBAAqB,YAAY;AAChE,gBACE,CAAC,oBACD,OAAO,qBAAqB,YAC5B,EAAE,UAAU,mBACZ;AACA,oBAAM,IAAI;AAAA,gBACR;AAAA,gBACA;AAAA,gBACA,eAAe;AAAA,gBACf;AAAA,cAAA;AAAA,YAEJ;AACA,mBAAO;AAAA,UACT,SAAS,OAAO;AACd,kBAAM,IAAI;AAAA,cACR,mBAAmB,8BAA8B,KAAK;AAAA,cACtD;AAAA,cACA,eAAe;AAAA,cACf;AAAA,cACA,wBAAwB,OAAO,qBAAqB;AAAA,YAAA;AAAA,UAExD;AAAA,QACF;AAEA,eAAO;AAAA,MACT,SAAS,OAAO;AACd,qBAAa,SAAS;AACtB,oBAAY,wBAAwB,OAAO,mBAAmB;AAE9D,YAAI,UAAU,SAAS,cAAc;AACnC,sBAAY,IAAI;AAAA,YACd,yBAAyB,OAAO;AAAA,YAChC;AAAA,UAAA;AAAA,QAEJ;AAEA,YACE,WAAW,cACX,CAAE,MAAM,YAAY,WAAW,SAAS,kBAAkB,GAC1D;AACA,gBAAM;AAAA,QACR;AAEA,cAAM,QAAQ,oBAAoB,SAAS,kBAAkB;AAC7D,cAAM,MAAM,KAAK;AAAA,MACnB;AAAA,IACF;AAEA,UAAM,IAAI,MAAM,oCAAoC;AAAA,EACtD;AACF;AAEA,eAAe,gBACb,UACA,SAK0B;AAC1B,QAAM,UAAU,OAAO,YAAY,SAAS,QAAQ,SAAS;AAE7D,MAAI;AACJ,MAAI;AACF,UAAM,gBAAgB,QAAQ;AAC9B,UAAM,cAAc,SAAS,QAAQ,IAAI,cAAc,KAAK;AAE5D,UAAM,eAKU,YAAY,SAAS,kBAAkB,IACnD,SACA,YAAY,SAAS,OAAO,IAC1B,SACA,YAAY,SAAS,0BAA0B,KAC7C,YAAY,SAAS,iBAAiB,KACtC,YAAY,SAAS,QAAQ,KAC7B,YAAY,SAAS,QAAQ,KAC7B,YAAY,SAAS,QAAQ,IAC7B,gBACA,YAAY,SAAS,qBAAqB,KACxC,YAAY,SAAS,mCAAmC,IACxD,aACA;AAEV,UAAM,YAMU,iBAAiB;AAEjC,QAAI,cAAc,QAAQ;AACxB,aAAO,MAAM,SAAS,KAAA;AAAA,IACxB,WAAW,cAAc,QAAQ;AAC/B,aAAO,MAAM,SAAS,KAAA;AAAA,IACxB,WAAW,cAAc,QAAQ;AAC/B,aAAO,MAAM,SAAS,KAAA;AAAA,IACxB,WAAW,cAAc,eAAe;AACtC,aAAO,MAAM,SAAS,YAAA;AAAA,IACxB,WAAW,cAAc,YAAY;AACnC,aAAO,MAAM,SAAS,SAAA;AAAA,IACxB,OAAO;AACL,YAAM,gBAAgB,SAAS,MAAA;AAC/B,UAAI;AACF,eAAO,MAAM,SAAS,KAAA;AAAA,MACxB,QAAQ;AACN,eAAO,MAAM,cAAc,KAAA;AAAA,MAC7B;AAAA,IACF;AAAA,EACF,SAAS,OAAO;AACd,UAAM,IAAI;AAAA,MACR,mBAAmB,iCAAiC,KAAK;AAAA,MACzD,iBAAiB,QAAQ,QAAQ;AAAA,IAAA;AAAA,EAErC;AAEA,MAAI,CAAC,SAAS,IAAI;AAChB,UAAM,IAAI;AAAA,MACR,QAAQ,SAAS,MAAM,IAAI,SAAS,UAAU;AAAA,MAC9C,SAAS;AAAA,MACT,SAAS;AAAA,MACT;AAAA,MACA;AAAA,MACA,QAAQ;AAAA,MACR,QAAQ;AAAA,IAAA;AAAA,EAEZ;AAEA,SAAO;AAAA,IACL;AAAA,IACA,QAAQ,SAAS;AAAA,IACjB,YAAY,SAAS;AAAA,IACrB;AAAA,IACA,QAAQ,QAAQ;AAAA,IAChB,KAAK,QAAQ;AAAA,IACb,KAAK;AAAA,EAAA;AAET;AAEA,eAAe,YACb,OACA,YACA,cACkB;AAClB,MAAI,CAAC,aAAc,QAAO;AAE1B,MAAI,aAAa,aAAa;AAC5B,WAAO,MAAM,aAAa,YAAY,OAAO,UAAU;AAAA,EACzD;AAEA,MAAI,iBAAiB,WAAW;AAC9B,WAAO,aAAa,kBAAkB,SAAS,MAAM,MAAM,KAAK;AAAA,EAClE;AAEA,MAAI,iBAAiB,gBAAgB,MAAM,SAAS,aAAa;AAC/D,WAAO,aAAa,sBAAsB;AAAA,EAC5C;AAEA,SAAO;AACT;AAEA,SAAS,oBACP,SACA,cACQ;AACR,MAAI,CAAC,aAAc,QAAO;AAE1B,QAAM,YAAY,aAAa,cAAc;AAC7C,QAAM,gBAAgB,aAAa,iBAAiB;AACpD,QAAM,WAAW,aAAa,iBAAiB;AAE/C,QAAM,QAAQ,YAAY,KAAK,IAAI,eAAe,OAAO;AACzD,SAAO,KAAK,IAAI,OAAO,QAAQ;AACjC;AAEA,SAAS,aACP,OACsE;AACtE,SACG,UAAU,QACT,OAAO,UAAU,YACjB,MAAM,aAAa,SAAS,YAC9B,MAAM,QAAQ,KAAK,KAClB,UAAU,QACT,OAAO,UAAU,YACjB,YAAY,SACZ,OAAO,MAAM,WAAW;AAE9B;AAEA,SAAS,qBAAqB,QAAmC;AAC/D,QAAM,eAAe,IAAI,gBAAA;AAEzB,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,MAAM,GAAG;AACjD,QAAI,MAAM,QAAQ,KAAK,GAAG;AACxB,iBAAW,QAAQ,OAAO;AACxB,YAAI,SAAS,UAAa,SAAS,MAAM;AACvC,uBAAa,OAAO,KAAK,OAAO,IAAI,CAAC;AAAA,QACvC;AAAA,MACF;AAAA,IACF,WAAW,UAAU,UAAa,UAAU,MAAM;AAChD,mBAAa,OAAO,KAAK,OAAO,KAAK,CAAC;AAAA,IACxC;AAAA,EACF;AAEA,SAAO,aAAa,SAAA;AACtB;AAEA,SAAS,qBAAqB,MAG5B;AACA,MACE,OAAO,SAAS,YAChB,gBAAgB,YAChB,gBAAgB,mBAChB,gBAAgB,eAChB,gBAAgB,QAChB,gBAAgB,gBAChB;AACA,WAAO,EAAE,KAAA;AAAA,EACX;AAEA,MAAI,aAAa,IAAI,GAAG;AACtB,WAAO;AAAA,MACL,MAAM,KAAK,UAAU,IAAI;AAAA,MACzB,aAAa;AAAA,IAAA;AAAA,EAEjB;AAEA,MAAI,SAAS,QAAQ,SAAS,QAAW;AACvC,WAAO,EAAE,MAAM,GAAA;AAAA,EACjB;AAEA,SAAO,EAAE,MAAM,OAAO,IAAI,EAAA;AAC5B;AAEA,SAAS,mBAAmB,SAAiB,OAAwB;AACnE,SAAO,GAAG,OAAO,KAAK,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;AAC9E;AAEA,SAAS,MAAM,IAA2B;AACxC,SAAO,IAAI,QAAQ,CAAA,YAAW,WAAW,SAAS,EAAE,CAAC;AACvD;AAEA,SAAS,qBACP,eACA,eACA,SACa;AACb,MAAI,CAAC,iBAAiB,CAAC,eAAe;AACpC,WAAO,IAAI,kBAAkB;AAAA,EAC/B;AAEA,MAAI,eAAe,SAAS;AAC1B,WAAO;AAAA,EACT;AAEA,QAAM,qBAAqB,IAAI,gBAAA;AAE/B,QAAM,cAAc,MAAM;AACxB,cAAA;AACA,uBAAmB,MAAA;AAAA,EACrB;AAEA,iBAAe,iBAAiB,SAAS,WAAW;AACpD,iBAAe,iBAAiB,SAAS,WAAW;AAEpD,SAAO,mBAAmB;AAC5B;AAEA,SAAS,wBAAwB,OAAgB,SAAwB;AACvE,MAAI,iBAAiB,OAAO;AAC1B,WAAO;AAAA,EACT;AAEA,SAAO,IAAI,MAAM,GAAG,OAAO,KAAK,OAAO,KAAK,CAAC,EAAE;AACjD;AAEA,SAAS,aAAa,SAAiB,YAA4B;AACjE,MAAI,WAAW,WAAW,SAAS,KAAK,WAAW,WAAW,UAAU,GAAG;AACzE,WAAO;AAAA,EACT;AAEA,QAAM,aAAa,IAAI,IAAI,OAAO;AAClC,QAAM,WAAW,WAAW,SAAS,QAAQ,OAAO,EAAE;AACtD,QAAM,CAAC,MAAM,KAAK,IAAI,WAAW,MAAM,GAAG;AAE1C,MAAI,WAAW,WAAW,GAAG,GAAG;AAC9B,eAAW,WAAW,WAAW;AAAA,EACnC,WAAW,YAAY;AACrB,eAAW,WAAW,WAAW,MAAM;AAAA,EACzC;AAEA,MAAI,OAAO;AACT,eAAW,SAAS,WAAW,SAC3B,GAAG,WAAW,MAAM,IAAI,KAAK,KAC7B,IAAI,KAAK;AAAA,EACf;AAEA,SAAO,WAAW,SAAA;AACpB;ACtlBA,SAAS,iBAAiB,KAAuC;AAC/D,SACE,QAAQ,SACP,OAAO,QAAQ,YAAY,OAAO,QAAQ,eAC3C,eAAe,OACf,OAAO,IAAI,WAAW,MAAM,YAC5B,IAAI,WAAW,MAAM,QACrB,cAAc,IAAI,WAAW,KAC7B,OAAO,IAAI,WAAW,EAAE,aAAa,cACrC,aAAa,IAAI,WAAW,KAC5B,OAAO,IAAI,WAAW,EAAE,YAAY,YACpC,YAAY,IAAI,WAAW,KAC3B,OAAO,IAAI,WAAW,EAAE,WAAW;AAEvC;AAkDO,SAAS,wBAAyC;AACvD,SAAO;AAAA,IACL,SAAY,QAAmB,MAAkB;AAC/C,UAAI,CAAC,iBAAiB,MAAM,GAAG;AAC7B,cAAM,IAAI;AAAA,UACR;AAAA,UACA;AAAA,QAAA;AAAA,MAEJ;AAEA,YAAM,SAAS,OAAO,WAAW,EAAE,SAAS,IAAI;AAEhD,UAAI,kBAAkB,SAAS;AAC7B,cAAM,IAAI;AAAA,UACR;AAAA,UACA;AAAA,QAAA;AAAA,MAEJ;AAEA,UAAI,OAAO,QAAQ;AACjB,cAAM,IAAI;AAAA,UACR,KAAK,UAAU,OAAO,MAAM;AAAA,UAC5B;AAAA,UACA;AAAA,QAAA;AAAA,MAEJ;AAEA,aAAO,OAAO;AAAA,IAChB;AAAA,IAEA,SAAS,KAAuB;AAC9B,aAAO,iBAAiB,GAAG;AAAA,IAC7B;AAAA,EAAA;AAEJ;AC9FA,SAAS,4BAA4B,SAA0B;AAC7D,QAAM,cACJ,OAAO,WAAW,eAClB,OAAO,OAAO,aAAa,eAC3B,OAAO,SAAS,WAAW;AAE7B,MAAI,CAAC,SAAS;AAEZ,WAAO,cAAc,OAAO,SAAS,SAAS;AAAA,EAChD;AAEA,MAAI,QAAQ,WAAW,GAAG,GAAG;AAE3B,WAAO,cACH,IAAI,IAAI,SAAS,OAAO,SAAS,MAAM,EAAE,KAAK,QAAQ,OAAO,EAAE,IAC/D,QAAQ,QAAQ,OAAO,EAAE;AAAA,EAC/B;AAEA,MAAI;AACF,QAAI,IAAI,OAAO;AAAA,EACjB,QAAQ;AACN,UAAM,IAAI;AAAA,MACR,qBAAqB,OAAO;AAAA,MAC5B;AAAA,IAAA;AAAA,EAEJ;AAEA,SAAO,QAAQ,SAAS,GAAG,IAAI,QAAQ,MAAM,GAAG,EAAE,IAAI;AACxD;AAEA,SAAS,0BACP,SACwB;AACxB,QAAM,cAAc;AACpB,cAAY,OAAO,aAAa,MAAM,SAAS;AAC/C,SAAO;AACT;AAKA,SAAS,yBAMP,KACA,SACA,gBACA,iBAC+B;AAC/B,QAAM,cAAc;AAAA,IAClB;AAAA,IACA;AAAA,EAAA;AAGF,SAAO,OAAO,OAAO,aAAa;AAAA,IAChC,OACE,QAC2C;AAC3C,YAAM,mBAAmB,YAAY,KAAK,CAAA,aAAY;AACpD,YAAI;AACF,gBAAM,gBAAgB,gBAAgB;AAAA,YACpC;AAAA,YACA,SAAS;AAAA,UAAA;AAEX,iBAAO;AAAA,YACL,GAAG;AAAA,YACH,MAAM;AAAA,UAAA;AAAA,QAEV,SAAS,OAAO;AACd,gBAAM,IAAI;AAAA,YACR,6BACE,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CACvD;AAAA,YACA;AAAA,YACA,SAAS;AAAA,YACT,iBAAiB,QAAQ,QAAQ;AAAA,UAAA;AAAA,QAErC;AAAA,MACF,CAAC;AAED,aAAO,0BAA0B,gBAAgB;AAAA,IACnD;AAAA,IACA,MAAM,OAAO;AACX,cAAQ,MAAM,aAAa;AAAA,IAC7B;AAAA,EAAA,CACD;AACH;AAKO,SAAS,iBAAiB,SAA2B,IAAI;AAC9D,QAAM,kBAAkB;AAAA,IACtB,GAAG;AAAA,IACH,SAAS,4BAA4B,OAAO,OAAO;AAAA,EAAA;AAGrD,QAAM,iBAAiB,kBAAkB,eAAe;AACxD,QAAM,kBAAkB,OAAO,mBAAmB,sBAAA;AAElD,WAAS,IAIP,QACG,MAGH;AACA,WAAO;AAAA,MACL;AAAA,MACA;AAAA,QACE,GAAI,KAAK,CAAC,KAAK,CAAA;AAAA,QACf,QAAQ;AAAA,MAAA;AAAA,MAEV;AAAA,MACA;AAAA,IAAA;AAAA,EAEJ;AAEA,SAAO;AAAA,IACL;AAAA,IAEA,MAAM,CAKJ,KACA,SACG,SAIH;AAAA,MACE;AAAA,MACA;AAAA,QACE,GAAI,KAAK,CAAC,KAAK,CAAA;AAAA,QACf,QAAQ;AAAA,QACR;AAAA,MAAA;AAAA,MAEF;AAAA,MACA;AAAA,IAAA;AAAA,IAGJ,KAAK,CAKH,KACA,SACG,SAIH;AAAA,MACE;AAAA,MACA;AAAA,QACE,GAAI,KAAK,CAAC,KAAK,CAAA;AAAA,QACf,QAAQ;AAAA,QACR;AAAA,MAAA;AAAA,MAEF;AAAA,MACA;AAAA,IAAA;AAAA,IAGJ,OAAO,CAKL,KACA,SACG,SAIH;AAAA,MACE;AAAA,MACA;AAAA,QACE,GAAI,KAAK,CAAC,KAAK,CAAA;AAAA,QACf,QAAQ;AAAA,QACR;AAAA,MAAA;AAAA,MAEF;AAAA,MACA;AAAA,IAAA;AAAA,IAGJ,QAAQ,CAIN,QACG,SAIH;AAAA,MACE;AAAA,MACA;AAAA,QACE,GAAI,KAAK,CAAC,KAAK,CAAA;AAAA,QACf,QAAQ;AAAA,MAAA;AAAA,MAEV;AAAA,MACA;AAAA,IAAA;AAAA;AAAA;AAAA;AAAA,IAMJ,SAAS,CAKP,KACA,YAEA;AAAA,MACE;AAAA,MACA,WAAW,CAAA;AAAA,MACX;AAAA,MACA;AAAA,IAAA;AAAA,EACF;AAEN;AAEO,MAAM,OAAO,iBAAA;"}
|
|
1
|
+
{"version":3,"file":"index.es.js","sources":["../src/errors.ts","../src/utils/path.ts","../src/utils/streaming.ts","../src/core.ts","../src/schema.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 statusCategory =\n status >= 500\n ? 'Server Error'\n : status >= 400\n ? 'Client Error'\n : status >= 300\n ? 'Redirect'\n : 'Success'\n\n const dataString = data ? JSON.stringify(data) : 'No response data'\n const truncatedData =\n dataString.length > 500\n ? dataString.substring(0, 500) + '...'\n : dataString\n\n const enhancedMessage = `HTTP ${statusCategory} (${status}): ${message}\nRequest: ${method} ${url}\nData: ${truncatedData}`\n\n super(enhancedMessage, { cause })\n this.status = status\n this.statusText = statusText\n this.data = data\n this.response = response\n this.url = url\n this.method = method\n }\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 const enhancedMessage = `${message}\nURL Template: ${url}\nExpected: [${requiredParams.map(p => `\"${p}\"`).join(', ')}], Actual: [${providedParams.map(p => `\"${p}\"`).join(', ')}]`\n\n super(enhancedMessage, { cause })\n this.url = url\n this.requiredParams = requiredParams\n this.providedParams = providedParams\n }\n}\n\nexport class MiddlewareError extends Error implements HttpClientError {\n public readonly name = 'MiddlewareError'\n public readonly type: 'request' | 'response'\n public readonly url?: string\n public readonly method?: string\n public override readonly cause?: Error\n\n constructor(\n message: string,\n type: 'request' | 'response',\n url?: string,\n method?: string,\n cause?: Error\n ) {\n const requestInfo = url ? `Request: ${method || 'UNKNOWN'} ${url}` : ''\n const enhancedMessage = requestInfo ? `${message}\\n${requestInfo}` : message\n\n super(enhancedMessage, { cause })\n this.type = type\n this.url = url\n this.method = method\n }\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\nexport class InvalidSchemaError extends Error implements HttpClientError {\n public readonly name = 'InvalidSchemaError'\n public readonly schema: unknown\n public override readonly cause?: Error\n\n constructor(message: string, schema: unknown, cause?: Error) {\n super(message, { cause })\n this.schema = schema\n }\n}\n\nexport class AsyncSchemaValidationError\n extends Error\n implements HttpClientError\n{\n public readonly name = 'AsyncSchemaValidationError'\n public readonly schema: unknown\n public override readonly cause?: Error\n\n constructor(message: string, schema: unknown, cause?: Error) {\n super(message, { cause })\n this.schema = schema\n }\n}\n\nexport class InvalidBaseUrlError extends Error implements HttpClientError {\n public readonly name = 'InvalidBaseUrlError'\n public readonly baseUrl: string\n public override readonly cause?: Error\n\n constructor(message: string, baseUrl: string, cause?: Error) {\n const enhancedMessage = `${message}\nBase URL: ${baseUrl}`\n\n super(enhancedMessage, { cause })\n this.baseUrl = baseUrl\n }\n}\n","import { PathParameterError } from '../errors'\n\n/**\n * Strips protocol from URL (e.g., https://, http://)\n */\ntype StripProtocol<T extends string> = T extends `${string}://${infer After}`\n ? After\n : T\n\n/**\n * Strips host and optional port from URL, keeping only the path\n * Handles cases like \"localhost:3000/users\" -> \"/users\"\n */\ntype StripHost<T extends string> = T extends `${infer _Host}/${infer Path}`\n ? `/${Path}`\n : T\n\n/**\n * Strips query string from path (e.g., \"/users?x=1\" -> \"/users\")\n * Only strips ? that comes after the path, not ? that's part of path parameters\n */\ntype StripQuery<T extends string> = T extends `${infer Path}?${infer Query}`\n ? Query extends\n | `${string}=${string}`\n | `${string}&${string}`\n | `${string}=${string}&${string}`\n ? Path // Contains query parameters (has = or &)\n : Query extends `/${string}`\n ? T // It's another path segment, not a query\n : Query extends ``\n ? T // It's an optional param marker (?)\n : Path // Plain query params like ?param\n : T\n\n/**\n * Normalizes URL to path only, stripping protocol, host, port, and query\n */\ntype NormalizePath<T extends string> = StripQuery<StripHost<StripProtocol<T>>>\n\n/**\n * Removes optional suffix from param name (e.g., \":id?\" -> \"id\", \":id\" -> \"id\")\n */\ntype CleanParamName<S extends string> = S extends `:${infer Name}?`\n ? Name\n : S extends `:${infer Name}`\n ? Name\n : S\n\n/**\n * Extracts all path parameters from a route\n */\nexport type ExtractRouteParams<T extends string> =\n NormalizePath<T> extends `${infer _Before}:${infer AfterColon}`\n ? AfterColon extends `${infer Param}/${infer Rest}`\n ? CleanParamName<`:${Param}`> | ExtractRouteParams<`/${Rest}`>\n : CleanParamName<`:${AfterColon}`>\n : never\n\nexport type HasRequiredParams<T extends string> = [\n ExtractRouteParams<T>,\n] extends [never]\n ? false\n : true\n\n/**\n * PathParams type - extracts parameter names and their types\n */\nexport type PathParams<Path extends string> = {\n [K in ExtractRouteParams<Path>]: string | number\n}\n\n/**\n * RequirePathParams enforces pathParams when needed\n */\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(/:([^/\\s?#]+)\\??/g, (_match, paramName: string) => {\n // Validate parameter name\n if (!/^[a-zA-Z0-9_]+$/.test(paramName)) {\n throw new PathParameterError(\n `Invalid path parameter name: \"${paramName}\"`,\n path,\n [paramName],\n Object.keys(params)\n )\n }\n\n // Get and validate parameter value\n const paramValue = params[paramName as keyof PathParams<Path>]\n if (paramValue === undefined) {\n throw new PathParameterError(\n `Missing required path parameter: \"${paramName}\"`,\n path,\n [paramName],\n Object.keys(params)\n )\n }\n\n const stringValue = String(paramValue)\n if (stringValue.includes('/') || stringValue.includes('?')) {\n throw new PathParameterError(\n `Invalid path parameter value for \"${paramName}\": contains invalid characters`,\n path,\n [paramName],\n Object.keys(params)\n )\n }\n\n return stringValue\n })\n}\n","import type { DownloadStreamingEvent, UploadStreamingEvent } from '../types'\n\nfunction createStreamingStream(\n reader: ReadableStreamDefaultReader<Uint8Array>,\n onChunk: (\n chunk: Uint8Array,\n totalBytes: number | undefined,\n transferredBytes: number\n ) => void,\n totalBytes: number | undefined,\n signal?: AbortSignal\n): ReadableStream<Uint8Array> {\n let transferredBytes = 0\n let readerReleased = false\n let isAborted = false\n\n const releaseReader = () => {\n if (!readerReleased) {\n readerReleased = true\n try {\n reader.releaseLock()\n } catch {\n // Reader might already be released, ignore\n }\n }\n }\n\n // Handle abort signal\n const abortHandler = () => {\n isAborted = true\n releaseReader()\n }\n\n signal?.addEventListener('abort', abortHandler)\n\n return new ReadableStream({\n async start(controller) {\n try {\n while (!isAborted) {\n const { done, value } = await reader.read()\n if (done) break\n\n transferredBytes += value.length\n onChunk(value, totalBytes, transferredBytes)\n controller.enqueue(value)\n }\n\n if (!isAborted) {\n controller.close()\n }\n } catch (error) {\n if (!isAborted) {\n controller.error(error)\n }\n throw error\n } finally {\n signal?.removeEventListener('abort', abortHandler)\n releaseReader()\n }\n },\n cancel() {\n isAborted = true\n signal?.removeEventListener('abort', abortHandler)\n releaseReader()\n },\n })\n}\n\n/**\n * Creates a request with upload streaming tracking\n */\nexport async function toStreamableRequest(\n request: Request,\n onUploadStreaming?: (event: UploadStreamingEvent) => void\n): Promise<Request> {\n if (!onUploadStreaming || !request.body) {\n return request\n }\n\n if (!request.body.getReader) {\n return request\n }\n\n const reader = request.body.getReader()\n const totalBytes = request.headers.get('content-length')\n ? parseInt(request.headers.get('content-length') || '0', 10)\n : undefined\n\n const stream = createStreamingStream(\n reader,\n (chunk, totalBytes, transferredBytes) => {\n onUploadStreaming({\n chunk,\n totalBytes,\n transferredBytes,\n })\n },\n totalBytes,\n request.signal\n )\n\n return new Request(request.url, {\n method: request.method,\n headers: request.headers,\n body: stream,\n signal: request.signal,\n credentials: request.credentials,\n cache: request.cache,\n mode: request.mode,\n redirect: request.redirect,\n referrer: request.referrer,\n referrerPolicy: request.referrerPolicy,\n integrity: request.integrity,\n keepalive: request.keepalive,\n duplex: 'half',\n } as RequestInit)\n}\n\n/**\n * Creates a response with download streaming tracking\n */\nexport async function toStreamableResponse(\n response: Response,\n onDownloadStreaming?: (event: DownloadStreamingEvent) => void\n): Promise<Response> {\n if (!onDownloadStreaming || !response.body) {\n return response\n }\n\n if (!response.body.getReader) {\n return response\n }\n\n const reader = response.body.getReader()\n const totalBytes = response.headers.get('content-length')\n ? parseInt(response.headers.get('content-length') || '0', 10)\n : undefined\n\n const stream = createStreamingStream(\n reader,\n (chunk, totalBytes, transferredBytes) => {\n onDownloadStreaming({\n chunk,\n totalBytes,\n transferredBytes,\n })\n },\n totalBytes\n )\n\n return new Response(stream, {\n status: response.status,\n statusText: response.statusText,\n headers: response.headers,\n })\n}\n","import {\n HttpError,\n MiddlewareError,\n NetworkError,\n SerializationError,\n TimeoutError,\n} from './errors'\nimport type { SchemaValidator } from './schema'\nimport type {\n CustomFetch,\n DownloadStreamingEvent,\n ExtendedRequestInit,\n HttpHeaders,\n HttpMethod,\n RequestContext,\n RequestParamsType,\n ResponseType,\n RetryOptions,\n SerializeBody,\n SerializeParams,\n UploadStreamingEvent,\n} from './types'\nimport {\n generatePath,\n toStreamableRequest,\n toStreamableResponse,\n type PathParams,\n} from './utils'\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: 30_000,\n shouldRetry: () => true,\n}\n\nexport interface HttpRequestOptions<\n TBody = unknown,\n TParams extends RequestParamsType = RequestParamsType,\n> {\n method?: HttpMethod\n headers?: HttpHeaders\n /** Query parameters */\n params?: TParams\n /** Path parameters for URL template */\n pathParams?: Record<string, string | number>\n /** Request body */\n body?: TBody\n timeout?: number\n signal?: AbortSignal\n /** Fetch options */\n credentials?: RequestCredentials\n cache?: RequestCache\n mode?: RequestMode\n redirect?: RequestRedirect\n /** Upload streaming tracking for this specific request */\n onUploadStreaming?: (event: UploadStreamingEvent) => void\n /** Download streaming tracking for this specific request */\n onDownloadStreaming?: (event: DownloadStreamingEvent) => void\n /** Response type override */\n responseType?: 'json' | 'text' | 'blob' | 'arrayBuffer' | 'formData'\n retryOptions?: RetryOptions\n}\n\nexport interface HttpClientConfig {\n /** Base URL for all requests */\n baseUrl?: string\n /** Default headers */\n headers?: HttpHeaders\n /** Default timeout */\n timeout?: number\n /** Schema validator */\n schemaValidator?: SchemaValidator\n /** Default retry options */\n retryOptions?: RetryOptions\n /** Custom fetch implementation */\n fetch?: CustomFetch\n /** Custom body serializer */\n serializeBody?: SerializeBody\n /** Custom params serializer */\n serializeParams?: SerializeParams\n /** Request middleware - can modify request before sending */\n onRequestMiddleware?: <TBody = unknown>(\n context: RequestContext<TBody>\n ) => RequestContext<TBody> | Promise<RequestContext<TBody>>\n /** Response middleware - can modify response after receiving */\n onResponseMiddleware?: (\n response: ResponseType<unknown>\n ) => ResponseType<unknown> | Promise<ResponseType<unknown>>\n}\n\n/**\n * Creates an HTTP request handler with the given configuration.\n * This is the core function that handles all HTTP requests with retry logic,\n * interceptors, and streaming.\n */\nexport function createHttpRequest(config: HttpClientConfig = {}) {\n const {\n baseUrl = '',\n headers: defaultHeaders = {},\n timeout: defaultTimeout = 30_000,\n fetch: customFetch = fetch,\n serializeBody: customSerializeBody,\n serializeParams: customSerializeParams,\n onRequestMiddleware,\n onResponseMiddleware,\n } = config\n\n return async function fetcher<\n Path extends string = string,\n TResponse = unknown,\n TBody = unknown,\n TParams extends RequestParamsType = RequestParamsType,\n >(\n url: Path,\n options: HttpRequestOptions<TBody, TParams> = {}\n ): Promise<ResponseType<TResponse>> {\n const {\n method = 'GET',\n headers = {},\n params,\n pathParams,\n body,\n timeout = defaultTimeout,\n signal,\n credentials,\n cache,\n mode,\n redirect,\n onUploadStreaming,\n onDownloadStreaming,\n responseType,\n retryOptions: requestRetryOptions,\n } = options\n\n let urlObj: URL | undefined\n let resolvedUrl = generatePath(url, pathParams as PathParams<Path>)\n\n if (baseUrl || params) {\n if (baseUrl) {\n resolvedUrl = constructUrl(baseUrl, resolvedUrl)\n urlObj = new URL(resolvedUrl)\n } else {\n urlObj = new URL(resolvedUrl)\n }\n }\n\n const baseRequestContext: RequestContext<TBody> = {\n url: resolvedUrl,\n method,\n params,\n headers: new Headers({ ...defaultHeaders, ...headers }),\n body,\n signal,\n fetchOptions: { credentials, cache, mode, redirect },\n }\n\n let requestContext: RequestContext<TBody> = baseRequestContext\n\n if (onRequestMiddleware) {\n try {\n // prevent middleware from mutating the original context\n const contextCopy: RequestContext<TBody> = {\n ...baseRequestContext,\n headers: new Headers(baseRequestContext.headers),\n fetchOptions: { ...baseRequestContext.fetchOptions },\n }\n\n requestContext = await onRequestMiddleware(contextCopy)\n\n if (requestContext.url !== resolvedUrl) {\n urlObj = new URL(requestContext.url)\n }\n } catch (error) {\n throw new MiddlewareError(\n createErrorMessage('Request middleware failed', error),\n 'request',\n requestContext.url,\n requestContext.method,\n createStandardizedError(error, 'Request middleware')\n )\n }\n }\n\n if (requestContext.params) {\n if (!urlObj) {\n urlObj = new URL(requestContext.url)\n }\n\n const serializedParams = customSerializeParams\n ? customSerializeParams(requestContext.params)\n : serializeQueryParams(requestContext.params)\n\n if (serializedParams) {\n if (customSerializeParams) {\n const queryString = serializedParams.startsWith('?')\n ? serializedParams.slice(1)\n : serializedParams\n const separator = urlObj.search ? '&' : '?'\n urlObj.search += separator + queryString\n } else {\n const newSearchParams = new URLSearchParams(serializedParams)\n for (const [key, value] of newSearchParams) {\n urlObj.searchParams.append(key, value)\n }\n }\n requestContext.url = urlObj.toString()\n }\n }\n\n const requestInit: ExtendedRequestInit = {\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 let body: BodyInit\n let contentType: string | undefined\n\n if (customSerializeBody) {\n const serializedBody = customSerializeBody(requestContext.body)\n if (serializedBody == null) {\n body = ''\n } else {\n body = serializedBody\n\n if (\n isObjectLike(requestContext.body) &&\n typeof serializedBody === 'string' &&\n !requestContext.headers.has('content-type')\n ) {\n contentType = 'application/json'\n }\n }\n } else {\n const serialized = serializeRequestBody(requestContext.body)\n body = serialized.body\n contentType = serialized.contentType\n }\n\n requestInit.body = body\n\n if (contentType) {\n requestContext.headers.set('content-type', contentType)\n }\n\n requestInit.duplex = 'half'\n }\n\n const mergedRetryOptions = {\n ...DEFAULT_RETRY_OPTIONS,\n ...config.retryOptions,\n ...requestRetryOptions,\n }\n const maxRetries = mergedRetryOptions.maxRetries\n let lastError: Error | undefined\n\n for (let attempt = 0; attempt <= maxRetries; attempt += 1) {\n const controller = new AbortController()\n const timeoutId = setTimeout(() => controller.abort(), timeout)\n\n const finalSignal = createCombinedSignal(\n requestContext.signal,\n controller.signal,\n () => clearTimeout(timeoutId)\n )\n\n try {\n const request = new Request(requestContext.url, requestInit)\n const trackedRequest = onUploadStreaming\n ? await toStreamableRequest(request, onUploadStreaming)\n : request\n\n const response = await customFetch(trackedRequest.url, {\n method: trackedRequest.method,\n headers: trackedRequest.headers,\n body: trackedRequest.body,\n signal: finalSignal,\n ...requestContext.fetchOptions,\n ...(trackedRequest.body && { duplex: 'half' }),\n } satisfies ExtendedRequestInit)\n\n const trackedResponse = onDownloadStreaming\n ? await toStreamableResponse(response, onDownloadStreaming)\n : response\n\n const responseData = await processResponse<TResponse>(trackedResponse, {\n responseType,\n method,\n url: requestContext.url,\n })\n\n if (onResponseMiddleware) {\n try {\n const middlewareResult = await onResponseMiddleware(responseData)\n if (\n !middlewareResult ||\n typeof middlewareResult !== 'object' ||\n !('data' in middlewareResult)\n ) {\n throw new MiddlewareError(\n 'Response middleware must return a valid ResponseType object',\n 'response',\n requestContext.url,\n method\n )\n }\n return middlewareResult as ResponseType<TResponse>\n } catch (error) {\n throw new MiddlewareError(\n createErrorMessage('Response middleware failed', error),\n 'response',\n requestContext.url,\n method,\n createStandardizedError(error, 'Response middleware')\n )\n }\n }\n\n return responseData\n } catch (error) {\n clearTimeout(timeoutId)\n lastError = createStandardizedError(error, 'Request execution')\n\n if (lastError.name === 'AbortError') {\n lastError = new TimeoutError(\n `Request timeout after ${timeout}ms`,\n lastError\n )\n }\n\n if (\n attempt >= maxRetries ||\n !(await shouldRetry(lastError, attempt, mergedRetryOptions))\n ) {\n throw lastError\n }\n\n const delay = calculateRetryDelay(attempt, mergedRetryOptions)\n await sleep(delay)\n }\n }\n\n throw new Error('Retry loop terminated unexpectedly')\n }\n}\n\nasync function processResponse<T = unknown>(\n response: Response,\n options: {\n responseType?: 'json' | 'text' | 'blob' | 'arrayBuffer' | 'formData'\n method: HttpMethod\n url: string\n }\n): Promise<ResponseType<T>> {\n const headers = Object.fromEntries(response.headers.entries())\n\n let data: unknown\n try {\n const requestedType = options.responseType\n const contentType = response.headers.get('content-type') ?? ''\n\n const detectedType:\n | 'json'\n | 'text'\n | 'arrayBuffer'\n | 'formData'\n | undefined = contentType.includes('application/json')\n ? 'json'\n : contentType.includes('text/')\n ? 'text'\n : contentType.includes('application/octet-stream') ||\n contentType.includes('application/pdf') ||\n contentType.includes('image/') ||\n contentType.includes('video/') ||\n contentType.includes('audio/')\n ? 'arrayBuffer'\n : contentType.includes('multipart/form-data') ||\n contentType.includes('application/x-www-form-urlencoded')\n ? 'formData'\n : undefined\n\n const finalType:\n | 'json'\n | 'text'\n | 'arrayBuffer'\n | 'blob'\n | 'formData'\n | undefined = requestedType ?? detectedType\n\n if (finalType === 'json') {\n data = await response.json()\n } else if (finalType === 'text') {\n data = await response.text()\n } else if (finalType === 'blob') {\n data = await response.blob()\n } else if (finalType === 'arrayBuffer') {\n data = await response.arrayBuffer()\n } else if (finalType === 'formData') {\n data = await response.formData()\n } else {\n const responseClone = response.clone()\n try {\n data = await response.json()\n } catch {\n data = await responseClone.text()\n }\n }\n } catch (error) {\n throw new SerializationError(\n createErrorMessage('Failed to parse response body', error),\n error instanceof Error ? error : undefined\n )\n }\n\n if (!response.ok) {\n throw new HttpError(\n `HTTP ${response.status} ${response.statusText}`,\n response.status,\n response.statusText,\n data,\n response,\n options.url,\n options.method\n )\n }\n\n return {\n data: data as T,\n status: response.status,\n statusText: response.statusText,\n headers,\n method: options.method,\n url: options.url,\n raw: response,\n }\n}\n\nasync function shouldRetry(\n error: Error,\n retryCount: number,\n retryOptions?: RetryOptions\n): Promise<boolean> {\n if (!retryOptions) return false\n\n if (retryOptions.shouldRetry) {\n return await retryOptions.shouldRetry(error, retryCount)\n }\n\n if (error instanceof HttpError) {\n return retryOptions.retryStatusCodes?.includes(error.status) ?? false\n }\n\n if (error instanceof NetworkError || error.name === 'TypeError') {\n return retryOptions.retryNetworkErrors ?? false\n }\n\n return false\n}\n\nfunction calculateRetryDelay(\n attempt: number,\n retryOptions?: RetryOptions\n): number {\n if (!retryOptions) return 0\n\n const baseDelay = retryOptions.retryDelay ?? 300\n const backoffFactor = retryOptions.backoffFactor ?? 2\n const maxDelay = retryOptions.maxRetryDelay ?? 30_000\n\n const delay = baseDelay * Math.pow(backoffFactor, attempt)\n return Math.min(delay, maxDelay)\n}\n\nfunction isObjectLike(\n value: unknown\n): value is Record<string, unknown> | unknown[] | { toJSON(): unknown } {\n return (\n (value !== null &&\n typeof value === 'object' &&\n value.constructor?.name === 'Object') ||\n Array.isArray(value) ||\n (value !== null &&\n typeof value === 'object' &&\n 'toJSON' in value &&\n typeof value.toJSON === 'function')\n )\n}\n\nfunction serializeQueryParams(params: RequestParamsType): string {\n const searchParams = new URLSearchParams()\n\n for (const [key, value] of Object.entries(params)) {\n if (Array.isArray(value)) {\n for (const item of value) {\n if (item !== undefined && item !== null) {\n searchParams.append(key, String(item))\n }\n }\n } else if (value !== undefined && value !== null) {\n searchParams.append(key, String(value))\n }\n }\n\n return searchParams.toString()\n}\n\nfunction serializeRequestBody(body: unknown): {\n body: BodyInit\n contentType?: string\n} {\n if (\n typeof body === 'string' ||\n body instanceof FormData ||\n body instanceof URLSearchParams ||\n body instanceof ArrayBuffer ||\n body instanceof Blob ||\n body instanceof ReadableStream\n ) {\n return { body: body }\n }\n\n if (isObjectLike(body)) {\n return {\n body: JSON.stringify(body),\n contentType: 'application/json',\n }\n }\n\n if (body === null || body === undefined) {\n return { body: '' }\n }\n\n return { body: String(body) }\n}\n\nfunction createErrorMessage(context: string, error: unknown): string {\n return `${context}: ${error instanceof Error ? error.message : String(error)}`\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms))\n}\n\nfunction createCombinedSignal(\n requestSignal?: AbortSignal,\n timeoutSignal?: AbortSignal,\n cleanup?: () => void\n): AbortSignal {\n if (!requestSignal && !timeoutSignal) {\n return new AbortController().signal\n }\n\n if (requestSignal?.aborted) {\n return requestSignal\n }\n\n const combinedController = new AbortController()\n\n const handleAbort = () => {\n cleanup?.()\n combinedController.abort()\n }\n\n requestSignal?.addEventListener('abort', handleAbort)\n timeoutSignal?.addEventListener('abort', handleAbort)\n\n return combinedController.signal\n}\n\nfunction createStandardizedError(error: unknown, context: string): Error {\n if (error instanceof Error) {\n return error\n }\n\n return new Error(`${context}: ${String(error)}`)\n}\n\nfunction constructUrl(baseUrl: string, requestUrl: string): string {\n if (requestUrl.startsWith('http://') || requestUrl.startsWith('https://')) {\n return requestUrl\n }\n\n const baseUrlObj = new URL(baseUrl)\n const basePath = baseUrlObj.pathname.replace(/\\/$/, '')\n const [path, query] = requestUrl.split('?')\n\n if (requestUrl.startsWith('/')) {\n baseUrlObj.pathname = basePath + path\n } else if (requestUrl) {\n baseUrlObj.pathname = basePath + '/' + path\n }\n\n if (query) {\n baseUrlObj.search = baseUrlObj.search\n ? `${baseUrlObj.search}&${query}`\n : `?${query}`\n }\n\n return baseUrlObj.toString()\n}\n","import type { StandardSchemaV1 } from '@standard-schema/spec'\nimport {\n AsyncSchemaValidationError,\n InvalidSchemaError,\n SchemaValidationError,\n} from './errors'\nimport { Schema } from './types'\n\n/**\n * Type guard to check if an object conforms to the Standard Schema V1 specification\n */\nfunction isStandardSchema(obj: unknown): obj is StandardSchemaV1 {\n return (\n obj !== null &&\n (typeof obj === 'object' || typeof obj === 'function') &&\n '~standard' in obj &&\n typeof obj['~standard'] === 'object' &&\n obj['~standard'] !== null &&\n 'validate' in obj['~standard'] &&\n typeof obj['~standard'].validate === 'function' &&\n 'version' in obj['~standard'] &&\n typeof obj['~standard'].version === 'number' &&\n 'vendor' in obj['~standard'] &&\n typeof obj['~standard'].vendor === 'string'\n )\n}\n\n/**\n * Interface for schema validators that can validate data against schemas.\n *\n * This interface allows you to create custom schema validators that work\n * with different validation libraries (Zod, Valibot, Arktype, etc.).\n */\nexport interface SchemaValidator {\n /**\n * Validate data against a schema.\n *\n * @template T - The expected type after validation\n * @param schema - The schema to validate against\n * @param data - The data to validate\n * @returns The validated data with the correct type\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 InvalidSchemaError(\n 'Schema must implement the Standard Schema interface',\n schema\n )\n }\n\n const result = schema['~standard'].validate(data)\n\n if (result instanceof Promise) {\n throw new AsyncSchemaValidationError(\n 'Async Standard Schema validation is not supported in this context',\n schema\n )\n }\n\n if (result.issues) {\n throw new SchemaValidationError(\n JSON.stringify(result.issues),\n schema,\n data\n )\n }\n\n return result.value as T\n },\n\n isSchema(obj: unknown): boolean {\n return isStandardSchema(obj)\n },\n }\n}\n","import type { HttpClientConfig, HttpRequestOptions } from './core'\nimport { createHttpRequest } from './core'\nimport { InvalidBaseUrlError, SchemaValidationError } from './errors'\nimport { createSchemaValidator } from './schema'\nimport type {\n EnforcedPathParamsOptions,\n ExtractableResponse,\n InferSchemaOutput,\n RequestParamsType,\n ResponseType,\n Schema,\n SchemaableResponse,\n} from './types'\nimport type { HasRequiredParams } from './utils'\n\nfunction validateAndNormalizeBaseUrl(baseUrl?: string): string {\n const hasLocation =\n typeof window !== 'undefined' &&\n typeof window.location !== 'undefined' &&\n window.location.origin !== 'null'\n\n if (!baseUrl) {\n // In browser environment, default to location.origin for relative paths\n return hasLocation ? window.location.origin : ''\n }\n\n if (baseUrl.startsWith('/')) {\n // In Node.js or non-browser environments, relative paths are preserved as-is\n return hasLocation\n ? new URL(baseUrl, window.location.origin).href.replace(/\\/$/, '')\n : baseUrl.replace(/\\/$/, '')\n }\n\n try {\n new URL(baseUrl)\n } catch {\n throw new InvalidBaseUrlError(\n `Invalid baseUrl: \"${baseUrl}\". Must be a valid absolute URL or relative path starting with \"/\".`,\n baseUrl\n )\n }\n\n return baseUrl.endsWith('/') ? baseUrl.slice(0, -1) : baseUrl\n}\n\nfunction createExtractableResponse<T>(\n promise: Promise<ResponseType<T>>\n): ExtractableResponse<T> {\n const extractable = promise as ExtractableResponse<T>\n extractable.data = async () => (await promise).data\n extractable.void = async () => {\n await promise\n }\n return extractable\n}\n\n/**\n * Creates a chainable response that allows adding schema validation and extracting data\n */\nfunction createSchemaableResponse<\n Path extends string,\n TResponse,\n TBody,\n TParams extends RequestParamsType,\n>(\n url: Path,\n options: HttpRequestOptions<TBody, TParams>,\n requestHandler: ReturnType<typeof createHttpRequest>,\n schemaValidator: ReturnType<typeof createSchemaValidator>\n): SchemaableResponse<TResponse> {\n const basePromise = requestHandler<Path, TResponse, TBody, TParams>(\n url,\n options\n )\n\n return Object.assign(basePromise, {\n schema<S extends Schema>(\n schema: S\n ): ExtractableResponse<InferSchemaOutput<S>> {\n const validatedPromise = basePromise.then(response => {\n try {\n const validatedData = schemaValidator.validate(\n schema,\n response.data\n ) as InferSchemaOutput<S>\n return {\n ...response,\n data: validatedData,\n }\n } catch (error) {\n throw new SchemaValidationError(\n `Schema validation failed: ${\n error instanceof Error ? error.message : String(error)\n }`,\n schema,\n response.data,\n error instanceof Error ? error : undefined\n )\n }\n })\n\n return createExtractableResponse(validatedPromise)\n },\n async data() {\n return (await basePromise).data\n },\n async void() {\n await basePromise\n },\n })\n}\n\n/**\n * Creates a complete HTTP client with method builders\n */\nexport function createHttpClient(config: HttpClientConfig = {}) {\n const validatedConfig = {\n ...config,\n baseUrl: validateAndNormalizeBaseUrl(config.baseUrl),\n }\n\n const requestHandler = createHttpRequest(validatedConfig)\n const schemaValidator = config.schemaValidator ?? createSchemaValidator()\n\n function get<\n Path extends string = string,\n TParams extends RequestParamsType = RequestParamsType,\n >(\n url: Path,\n ...args: HasRequiredParams<Path> extends true\n ? [options: EnforcedPathParamsOptions<never, TParams, Path>]\n : [options?: EnforcedPathParamsOptions<never, TParams, Path>]\n ) {\n return createSchemaableResponse<Path, unknown, never, TParams>(\n url,\n {\n ...(args[0] ?? {}),\n method: 'GET',\n },\n requestHandler,\n schemaValidator\n )\n }\n\n return {\n get,\n\n post: <\n Path extends string = string,\n TBody = unknown,\n TParams extends RequestParamsType = RequestParamsType,\n >(\n url: Path,\n body?: TBody,\n ...args: HasRequiredParams<Path> extends true\n ? [options: EnforcedPathParamsOptions<TBody, TParams, Path>]\n : [options?: EnforcedPathParamsOptions<TBody, TParams, Path>]\n ) =>\n createSchemaableResponse<Path, unknown, TBody, TParams>(\n url,\n {\n ...(args[0] ?? {}),\n method: 'POST',\n body,\n },\n requestHandler,\n schemaValidator\n ),\n\n put: <\n Path extends string = string,\n TBody = unknown,\n TParams extends RequestParamsType = RequestParamsType,\n >(\n url: Path,\n body?: TBody,\n ...args: HasRequiredParams<Path> extends true\n ? [options: EnforcedPathParamsOptions<TBody, TParams, Path>]\n : [options?: EnforcedPathParamsOptions<TBody, TParams, Path>]\n ) =>\n createSchemaableResponse<Path, unknown, TBody, TParams>(\n url,\n {\n ...(args[0] ?? {}),\n method: 'PUT',\n body,\n },\n requestHandler,\n schemaValidator\n ),\n\n patch: <\n Path extends string = string,\n TBody = unknown,\n TParams extends RequestParamsType = RequestParamsType,\n >(\n url: Path,\n body?: TBody,\n ...args: HasRequiredParams<Path> extends true\n ? [options: EnforcedPathParamsOptions<TBody, TParams, Path>]\n : [options?: EnforcedPathParamsOptions<TBody, TParams, Path>]\n ) =>\n createSchemaableResponse<Path, unknown, TBody, TParams>(\n url,\n {\n ...(args[0] ?? {}),\n method: 'PATCH',\n body,\n },\n requestHandler,\n schemaValidator\n ),\n\n delete: <\n Path extends string = string,\n TParams extends RequestParamsType = RequestParamsType,\n >(\n url: Path,\n ...args: HasRequiredParams<Path> extends true\n ? [options: EnforcedPathParamsOptions<never, TParams, Path>]\n : [options?: EnforcedPathParamsOptions<never, TParams, Path>]\n ) =>\n createSchemaableResponse<Path, unknown, never, TParams>(\n url,\n {\n ...(args[0] ?? {}),\n method: 'DELETE',\n },\n requestHandler,\n schemaValidator\n ),\n\n /**\n * Generic request method for custom HTTP methods and full control\n */\n request: <\n Path extends string = string,\n TBody = unknown,\n TParams extends RequestParamsType = RequestParamsType,\n >(\n url: Path,\n options?: HttpRequestOptions<TBody, TParams>\n ) =>\n createSchemaableResponse<Path, unknown, TBody, TParams>(\n url,\n options ?? {},\n requestHandler,\n schemaValidator\n ),\n }\n}\n\nexport const http = createHttpClient()\n"],"names":["totalBytes","body"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "1000fetches",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"description": "A type-first HTTP client with compile-time path validation, schema validation, middleware, retries, and real-time streaming — 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",
|