@hey-api/client-fetch
Advanced tools
Comparing version 0.4.4 to 0.5.0
@@ -109,6 +109,6 @@ type ArrayStyle = 'form' | 'spaceDelimited' | 'pipeDelimited'; | ||
} | ||
interface RequestOptionsBase<ThrowOnError extends boolean> extends Config<ThrowOnError> { | ||
interface RequestOptionsBase<ThrowOnError extends boolean, Url extends string = string> extends Config<ThrowOnError> { | ||
path?: Record<string, unknown>; | ||
query?: Record<string, unknown>; | ||
url: string; | ||
url: Url; | ||
} | ||
@@ -131,3 +131,9 @@ type RequestResult<Data = unknown, TError = unknown, ThrowOnError extends boolean = boolean> = ThrowOnError extends true ? Promise<{ | ||
type RequestFn = <Data = unknown, TError = unknown, ThrowOnError extends boolean = false>(options: Omit<RequestOptionsBase<ThrowOnError>, 'method'> & Pick<Required<RequestOptionsBase<ThrowOnError>>, 'method'>) => RequestResult<Data, TError, ThrowOnError>; | ||
interface Client<Req = Request, Res = Response, Err = unknown, Options = RequestOptions> { | ||
interface Client<Req = Request, Res = Response, Err = unknown, Opts = RequestOptions> { | ||
/** | ||
* Returns the final request URL. This method works only with experimental parser. | ||
*/ | ||
buildUrl: <T extends { | ||
url: string; | ||
}>(options: T & Options<T>) => string; | ||
connect: MethodFn; | ||
@@ -138,3 +144,3 @@ delete: MethodFn; | ||
head: MethodFn; | ||
interceptors: Middleware<Req, Res, Err, Options>; | ||
interceptors: Middleware<Req, Res, Err, Opts>; | ||
options: MethodFn; | ||
@@ -159,6 +165,17 @@ patch: MethodFn; | ||
}; | ||
type Options<T = unknown, ThrowOnError extends boolean = boolean> = T extends { | ||
type Options<T extends { | ||
url: string; | ||
} = { | ||
url: string; | ||
}, ThrowOnError extends boolean = boolean> = T extends { | ||
body?: any; | ||
} ? T extends { | ||
headers?: any; | ||
} ? OmitKeys<OptionsBase<ThrowOnError>, 'body' | 'headers'> & Omit<T, 'url'> : OmitKeys<OptionsBase<ThrowOnError>, 'body'> & Omit<T, 'url'> & Pick<OptionsBase<ThrowOnError>, 'headers'> : T extends { | ||
headers?: any; | ||
} ? OmitKeys<OptionsBase<ThrowOnError>, 'headers'> & Omit<T, 'url'> & Pick<OptionsBase<ThrowOnError>, 'body'> : OptionsBase<ThrowOnError> & Omit<T, 'url'>; | ||
type OptionsLegacyParser<T = unknown, ThrowOnError extends boolean = boolean> = T extends { | ||
body?: any; | ||
} ? T extends { | ||
headers?: any; | ||
} ? OmitKeys<OptionsBase<ThrowOnError>, 'body' | 'headers'> & T : OmitKeys<OptionsBase<ThrowOnError>, 'body'> & T & Pick<OptionsBase<ThrowOnError>, 'headers'> : T extends { | ||
@@ -170,2 +187,2 @@ headers?: any; | ||
export { type Client, type Config, type Options, type QuerySerializerOptions, type RequestOptionsBase, type RequestResult, createClient, createConfig, formDataBodySerializer, jsonBodySerializer, urlSearchParamsBodySerializer }; | ||
export { type Client, type Config, type Options, type OptionsLegacyParser, type QuerySerializerOptions, type RequestOptionsBase, type RequestResult, createClient, createConfig, formDataBodySerializer, jsonBodySerializer, urlSearchParamsBodySerializer }; |
@@ -1,5 +0,5 @@ | ||
var T=/\{[^{}]+\}/g,h=({allowReserved:i,name:n,value:e})=>{if(e==null)return "";if(typeof e=="object")throw new Error("Deeply-nested arrays/objects aren\u2019t supported. Provide your own `querySerializer()` to handle these.");return `${n}=${i?e:encodeURIComponent(e)}`},U=i=>{switch(i){case"label":return ".";case"matrix":return ";";case"simple":return ",";default:return "&"}},$=i=>{switch(i){case"form":return ",";case"pipeDelimited":return "|";case"spaceDelimited":return "%20";default:return ","}},D=i=>{switch(i){case"label":return ".";case"matrix":return ";";case"simple":return ",";default:return "&"}},j=({allowReserved:i,explode:n,name:e,style:a,value:o})=>{if(!n){let r=(i?o:o.map(c=>encodeURIComponent(c))).join($(a));switch(a){case"label":return `.${r}`;case"matrix":return `;${e}=${r}`;case"simple":return r;default:return `${e}=${r}`}}let s=U(a),t=o.map(r=>a==="label"||a==="simple"?i?r:encodeURIComponent(r):h({allowReserved:i,name:e,value:r})).join(s);return a==="label"||a==="matrix"?s+t:t},C=({allowReserved:i,explode:n,name:e,style:a,value:o})=>{if(o instanceof Date)return `${e}=${o.toISOString()}`;if(a!=="deepObject"&&!n){let r=[];Object.entries(o).forEach(([u,l])=>{r=[...r,u,i?l:encodeURIComponent(l)];});let c=r.join(",");switch(a){case"form":return `${e}=${c}`;case"label":return `.${c}`;case"matrix":return `;${e}=${c}`;default:return c}}let s=D(a),t=Object.entries(o).map(([r,c])=>h({allowReserved:i,name:a==="deepObject"?`${e}[${r}]`:r,value:c})).join(s);return a==="label"||a==="matrix"?s+t:t},_=({path:i,url:n})=>{let e=n,a=n.match(T);if(a)for(let o of a){let s=!1,t=o.substring(1,o.length-1),r="simple";t.endsWith("*")&&(s=!0,t=t.substring(0,t.length-1)),t.startsWith(".")?(t=t.substring(1),r="label"):t.startsWith(";")&&(t=t.substring(1),r="matrix");let c=i[t];if(c==null)continue;if(Array.isArray(c)){e=e.replace(o,j({explode:s,name:t,style:r,value:c}));continue}if(typeof c=="object"){e=e.replace(o,C({explode:s,name:t,style:r,value:c}));continue}if(r==="matrix"){e=e.replace(o,`;${h({name:t,value:c})}`);continue}let u=encodeURIComponent(r==="label"?`.${c}`:c);e=e.replace(o,u);}return e},b=({allowReserved:i,array:n,object:e}={})=>o=>{let s=[];if(o&&typeof o=="object")for(let t in o){let r=o[t];if(r!=null){if(Array.isArray(r)){s=[...s,j({allowReserved:i,explode:!0,name:t,style:"form",value:r,...n})];continue}if(typeof r=="object"){s=[...s,C({allowReserved:i,explode:!0,name:t,style:"deepObject",value:r,...e})];continue}s=[...s,h({allowReserved:i,name:t,value:r})];}}return s.join("&")},A=i=>{if(!i)return;let n=i.split(";")[0].trim();if(n.startsWith("application/json")||n.endsWith("+json"))return "json";if(n==="multipart/form-data")return "formData";if(["application/","audio/","image/","video/"].some(e=>n.startsWith(e)))return "blob";if(n.startsWith("text/"))return "text"},w=({baseUrl:i,path:n,query:e,querySerializer:a,url:o})=>{let s=o.startsWith("/")?o:`/${o}`,t=i+s;n&&(t=_({path:n,url:t}));let r=e?a(e):"";return r.startsWith("?")&&(r=r.substring(1)),r&&(t+=`?${r}`),t},R=(i,n)=>{let e={...i,...n};return e.baseUrl?.endsWith("/")&&(e.baseUrl=e.baseUrl.substring(0,e.baseUrl.length-1)),e.headers=O(i.headers,n.headers),e},O=(...i)=>{let n=new Headers;for(let e of i){if(!e||typeof e!="object")continue;let a=e instanceof Headers?e.entries():Object.entries(e);for(let[o,s]of a)if(s===null)n.delete(o);else if(Array.isArray(s))for(let t of s)n.append(o,t);else s!==void 0&&n.set(o,typeof s=="object"?JSON.stringify(s):s);}return n},y=class{_fns;constructor(){this._fns=[];}clear(){this._fns=[];}exists(n){return this._fns.indexOf(n)!==-1}eject(n){let e=this._fns.indexOf(n);e!==-1&&(this._fns=[...this._fns.slice(0,e),...this._fns.slice(e+1)]);}use(n){this._fns=[...this._fns,n];}},P=()=>({error:new y,request:new y,response:new y}),q=(i,n,e)=>{typeof e=="string"||e instanceof Blob?i.append(n,e):i.append(n,JSON.stringify(e));},k={bodySerializer:i=>{let n=new FormData;return Object.entries(i).forEach(([e,a])=>{a!=null&&(Array.isArray(a)?a.forEach(o=>q(n,e,o)):q(n,e,a));}),n}},E={bodySerializer:i=>JSON.stringify(i)},z=(i,n,e)=>{typeof e=="string"?i.append(n,e):i.append(n,JSON.stringify(e));},H={bodySerializer:i=>{let n=new URLSearchParams;return Object.entries(i).forEach(([e,a])=>{a!=null&&(Array.isArray(a)?a.forEach(o=>z(n,e,o)):z(n,e,a));}),n}},W=b({allowReserved:!1,array:{explode:!0,style:"form"},object:{explode:!0,style:"deepObject"}}),B={"Content-Type":"application/json"},x=(i={})=>({...E,baseUrl:"",fetch:globalThis.fetch,headers:B,parseAs:"auto",querySerializer:W,...i});var J=(i={})=>{let n=R(x(),i),e=()=>({...n}),a=t=>(n=R(n,t),e()),o=P(),s=async t=>{let r={...n,...t,headers:O(n.headers,t.headers)};r.body&&r.bodySerializer&&(r.body=r.bodySerializer(r.body)),r.body||r.headers.delete("Content-Type");let c=w({baseUrl:r.baseUrl??"",path:r.path,query:r.query,querySerializer:typeof r.querySerializer=="function"?r.querySerializer:b(r.querySerializer),url:r.url}),u={redirect:"follow",...r},l=new Request(c,u);for(let f of o.request._fns)l=await f(l,r);let I=r.fetch,p=await I(l);for(let f of o.response._fns)p=await f(p,l,r);let g={request:l,response:p};if(p.ok){if(p.status===204||p.headers.get("Content-Length")==="0")return {data:{},...g};if(r.parseAs==="stream")return {data:p.body,...g};let f=(r.parseAs==="auto"?A(p.headers.get("Content-Type")):r.parseAs)??"json",S=await p[f]();return f==="json"&&r.responseTransformer&&(S=await r.responseTransformer(S)),{data:S,...g}}let m=await p.text();try{m=JSON.parse(m);}catch{}let d=m;for(let f of o.error._fns)d=await f(m,p,l,r);if(d=d||{},r.throwOnError)throw d;return {error:d,...g}};return {connect:t=>s({...t,method:"CONNECT"}),delete:t=>s({...t,method:"DELETE"}),get:t=>s({...t,method:"GET"}),getConfig:e,head:t=>s({...t,method:"HEAD"}),interceptors:o,options:t=>s({...t,method:"OPTIONS"}),patch:t=>s({...t,method:"PATCH"}),post:t=>s({...t,method:"POST"}),put:t=>s({...t,method:"PUT"}),request:s,setConfig:a,trace:t=>s({...t,method:"TRACE"})}}; | ||
var U=/\{[^{}]+\}/g,S=({allowReserved:n,name:t,value:r})=>{if(r==null)return "";if(typeof r=="object")throw new Error("Deeply-nested arrays/objects aren\u2019t supported. Provide your own `querySerializer()` to handle these.");return `${t}=${n?r:encodeURIComponent(r)}`},$=n=>{switch(n){case"label":return ".";case"matrix":return ";";case"simple":return ",";default:return "&"}},D=n=>{switch(n){case"form":return ",";case"pipeDelimited":return "|";case"spaceDelimited":return "%20";default:return ","}},_=n=>{switch(n){case"label":return ".";case"matrix":return ";";case"simple":return ",";default:return "&"}},C=({allowReserved:n,explode:t,name:r,style:o,value:a})=>{if(!t){let e=(n?a:a.map(s=>encodeURIComponent(s))).join(D(o));switch(o){case"label":return `.${e}`;case"matrix":return `;${r}=${e}`;case"simple":return e;default:return `${r}=${e}`}}let c=$(o),i=a.map(e=>o==="label"||o==="simple"?n?e:encodeURIComponent(e):S({allowReserved:n,name:r,value:e})).join(c);return o==="label"||o==="matrix"?c+i:i},A=({allowReserved:n,explode:t,name:r,style:o,value:a})=>{if(a instanceof Date)return `${r}=${a.toISOString()}`;if(o!=="deepObject"&&!t){let e=[];Object.entries(a).forEach(([u,g])=>{e=[...e,u,n?g:encodeURIComponent(g)];});let s=e.join(",");switch(o){case"form":return `${r}=${s}`;case"label":return `.${s}`;case"matrix":return `;${r}=${s}`;default:return s}}let c=_(o),i=Object.entries(a).map(([e,s])=>S({allowReserved:n,name:o==="deepObject"?`${r}[${e}]`:e,value:s})).join(c);return o==="label"||o==="matrix"?c+i:i},k=({path:n,url:t})=>{let r=t,o=t.match(U);if(o)for(let a of o){let c=!1,i=a.substring(1,a.length-1),e="simple";i.endsWith("*")&&(c=!0,i=i.substring(0,i.length-1)),i.startsWith(".")?(i=i.substring(1),e="label"):i.startsWith(";")&&(i=i.substring(1),e="matrix");let s=n[i];if(s==null)continue;if(Array.isArray(s)){r=r.replace(a,C({explode:c,name:i,style:e,value:s}));continue}if(typeof s=="object"){r=r.replace(a,A({explode:c,name:i,style:e,value:s}));continue}if(e==="matrix"){r=r.replace(a,`;${S({name:i,value:s})}`);continue}let u=encodeURIComponent(e==="label"?`.${s}`:s);r=r.replace(a,u);}return r},R=({allowReserved:n,array:t,object:r}={})=>a=>{let c=[];if(a&&typeof a=="object")for(let i in a){let e=a[i];if(e!=null){if(Array.isArray(e)){c=[...c,C({allowReserved:n,explode:!0,name:i,style:"form",value:e,...t})];continue}if(typeof e=="object"){c=[...c,A({allowReserved:n,explode:!0,name:i,style:"deepObject",value:e,...r})];continue}c=[...c,S({allowReserved:n,name:i,value:e})];}}return c.join("&")},w=n=>{if(!n)return;let t=n.split(";")[0].trim();if(t.startsWith("application/json")||t.endsWith("+json"))return "json";if(t==="multipart/form-data")return "formData";if(["application/","audio/","image/","video/"].some(r=>t.startsWith(r)))return "blob";if(t.startsWith("text/"))return "text"},P=({baseUrl:n,path:t,query:r,querySerializer:o,url:a})=>{let c=a.startsWith("/")?a:`/${a}`,i=n+c;t&&(i=k({path:t,url:i}));let e=r?o(r):"";return e.startsWith("?")&&(e=e.substring(1)),e&&(i+=`?${e}`),i},O=(n,t)=>{let r={...n,...t};return r.baseUrl?.endsWith("/")&&(r.baseUrl=r.baseUrl.substring(0,r.baseUrl.length-1)),r.headers=x(n.headers,t.headers),r},x=(...n)=>{let t=new Headers;for(let r of n){if(!r||typeof r!="object")continue;let o=r instanceof Headers?r.entries():Object.entries(r);for(let[a,c]of o)if(c===null)t.delete(a);else if(Array.isArray(c))for(let i of c)t.append(a,i);else c!==void 0&&t.set(a,typeof c=="object"?JSON.stringify(c):c);}return t},y=class{_fns;constructor(){this._fns=[];}clear(){this._fns=[];}exists(t){return this._fns.indexOf(t)!==-1}eject(t){let r=this._fns.indexOf(t);r!==-1&&(this._fns=[...this._fns.slice(0,r),...this._fns.slice(r+1)]);}use(t){this._fns=[...this._fns,t];}},E=()=>({error:new y,request:new y,response:new y}),z=(n,t,r)=>{typeof r=="string"||r instanceof Blob?n.append(t,r):n.append(t,JSON.stringify(r));},H={bodySerializer:n=>{let t=new FormData;return Object.entries(n).forEach(([r,o])=>{o!=null&&(Array.isArray(o)?o.forEach(a=>z(t,r,a)):z(t,r,o));}),t}},I={bodySerializer:n=>JSON.stringify(n)},j=(n,t,r)=>{typeof r=="string"?n.append(t,r):n.append(t,JSON.stringify(r));},W={bodySerializer:n=>{let t=new URLSearchParams;return Object.entries(n).forEach(([r,o])=>{o!=null&&(Array.isArray(o)?o.forEach(a=>j(t,r,a)):j(t,r,o));}),t}},B=R({allowReserved:!1,array:{explode:!0,style:"form"},object:{explode:!0,style:"deepObject"}}),N={"Content-Type":"application/json"},q=(n={})=>({...I,baseUrl:"",fetch:globalThis.fetch,headers:N,parseAs:"auto",querySerializer:B,...n});var L=(n={})=>{let t=O(q(),n),r=()=>({...t}),o=e=>(t=O(t,e),r()),a=e=>P({baseUrl:e.baseUrl??"",path:e.path,query:e.query,querySerializer:typeof e.querySerializer=="function"?e.querySerializer:R(e.querySerializer),url:e.url}),c=E(),i=async e=>{let s={...t,...e,headers:x(t.headers,e.headers)};s.body&&s.bodySerializer&&(s.body=s.bodySerializer(s.body)),s.body||s.headers.delete("Content-Type");let u=a(s),g={redirect:"follow",...s},f=new Request(u,g);for(let p of c.request._fns)f=await p(f,s);let T=s.fetch,l=await T(f);for(let p of c.response._fns)l=await p(l,f,s);let m={request:f,response:l};if(l.ok){if(l.status===204||l.headers.get("Content-Length")==="0")return {data:{},...m};if(s.parseAs==="stream")return {data:l.body,...m};let p=(s.parseAs==="auto"?w(l.headers.get("Content-Type")):s.parseAs)??"json",b=await l[p]();return p==="json"&&s.responseTransformer&&(b=await s.responseTransformer(b)),{data:b,...m}}let h=await l.text();try{h=JSON.parse(h);}catch{}let d=h;for(let p of c.error._fns)d=await p(h,l,f,s);if(d=d||{},s.throwOnError)throw d;return {error:d,...m}};return {buildUrl:a,connect:e=>i({...e,method:"CONNECT"}),delete:e=>i({...e,method:"DELETE"}),get:e=>i({...e,method:"GET"}),getConfig:r,head:e=>i({...e,method:"HEAD"}),interceptors:c,options:e=>i({...e,method:"OPTIONS"}),patch:e=>i({...e,method:"PATCH"}),post:e=>i({...e,method:"POST"}),put:e=>i({...e,method:"PUT"}),request:i,setConfig:o,trace:e=>i({...e,method:"TRACE"})}}; | ||
export { J as createClient, x as createConfig, k as formDataBodySerializer, E as jsonBodySerializer, H as urlSearchParamsBodySerializer }; | ||
export { L as createClient, q as createConfig, H as formDataBodySerializer, I as jsonBodySerializer, W as urlSearchParamsBodySerializer }; | ||
//# sourceMappingURL=index.js.map | ||
//# sourceMappingURL=index.js.map |
{ | ||
"name": "@hey-api/client-fetch", | ||
"version": "0.4.4", | ||
"version": "0.5.0", | ||
"description": "🚀 Fetch API client for `@hey-api/openapi-ts` codegen.", | ||
@@ -5,0 +5,0 @@ "homepage": "https://heyapi.dev/", |
@@ -7,3 +7,3 @@ <div align="center"> | ||
[Live demo](https://stackblitz.com/edit/hey-api-client-fetch-example?file=openapi-ts.config.ts,src%2Fclient%2Fschemas.gen.ts,src%2Fclient%2Fservices.gen.ts,src%2Fclient%2Ftypes.gen.ts,src%2FApp.tsx) | ||
[Live demo](https://stackblitz.com/edit/hey-api-client-fetch-example?file=openapi-ts.config.ts,src%2Fclient%2Fschemas.gen.ts,src%2Fclient%2Fsdk.gen.ts,src%2Fclient%2Ftypes.gen.ts,src%2FApp.tsx) | ||
@@ -10,0 +10,0 @@ ## Features |
@@ -27,2 +27,16 @@ import type { Client, Config, RequestOptions } from './types'; | ||
const buildUrl: Client['buildUrl'] = (options) => { | ||
const url = getUrl({ | ||
baseUrl: options.baseUrl ?? '', | ||
path: options.path, | ||
query: options.query, | ||
querySerializer: | ||
typeof options.querySerializer === 'function' | ||
? options.querySerializer | ||
: createQuerySerializer(options.querySerializer), | ||
url: options.url, | ||
}); | ||
return url; | ||
}; | ||
const interceptors = createInterceptors< | ||
@@ -52,13 +66,3 @@ Request, | ||
const url = getUrl({ | ||
baseUrl: opts.baseUrl ?? '', | ||
path: opts.path, | ||
query: opts.query, | ||
querySerializer: | ||
typeof opts.querySerializer === 'function' | ||
? opts.querySerializer | ||
: createQuerySerializer(opts.querySerializer), | ||
url: opts.url, | ||
}); | ||
const url = buildUrl(opts); | ||
const requestInit: ReqInit = { | ||
@@ -148,2 +152,3 @@ redirect: 'follow', | ||
return { | ||
buildUrl, | ||
connect: (options) => request({ ...options, method: 'CONNECT' }), | ||
@@ -169,2 +174,3 @@ delete: (options) => request({ ...options, method: 'DELETE' }), | ||
Options, | ||
OptionsLegacyParser, | ||
RequestOptionsBase, | ||
@@ -171,0 +177,0 @@ RequestResult, |
@@ -101,7 +101,9 @@ import type { | ||
export interface RequestOptionsBase<ThrowOnError extends boolean> | ||
extends Config<ThrowOnError> { | ||
export interface RequestOptionsBase< | ||
ThrowOnError extends boolean, | ||
Url extends string = string, | ||
> extends Config<ThrowOnError> { | ||
path?: Record<string, unknown>; | ||
query?: Record<string, unknown>; | ||
url: string; | ||
url: Url; | ||
} | ||
@@ -150,4 +152,8 @@ | ||
Err = unknown, | ||
Options = RequestOptions, | ||
Opts = RequestOptions, | ||
> { | ||
/** | ||
* Returns the final request URL. This method works only with experimental parser. | ||
*/ | ||
buildUrl: <T extends { url: string }>(options: T & Options<T>) => string; | ||
connect: MethodFn; | ||
@@ -158,3 +164,3 @@ delete: MethodFn; | ||
head: MethodFn; | ||
interceptors: Middleware<Req, Res, Err, Options>; | ||
interceptors: Middleware<Req, Res, Err, Opts>; | ||
options: MethodFn; | ||
@@ -187,2 +193,17 @@ patch: MethodFn; | ||
export type Options< | ||
T extends { url: string } = { url: string }, | ||
ThrowOnError extends boolean = boolean, | ||
> = T extends { body?: any } | ||
? T extends { headers?: any } | ||
? OmitKeys<OptionsBase<ThrowOnError>, 'body' | 'headers'> & Omit<T, 'url'> | ||
: OmitKeys<OptionsBase<ThrowOnError>, 'body'> & | ||
Omit<T, 'url'> & | ||
Pick<OptionsBase<ThrowOnError>, 'headers'> | ||
: T extends { headers?: any } | ||
? OmitKeys<OptionsBase<ThrowOnError>, 'headers'> & | ||
Omit<T, 'url'> & | ||
Pick<OptionsBase<ThrowOnError>, 'body'> | ||
: OptionsBase<ThrowOnError> & Omit<T, 'url'>; | ||
export type OptionsLegacyParser< | ||
T = unknown, | ||
@@ -189,0 +210,0 @@ ThrowOnError extends boolean = boolean, |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
120750
1112