fch 5.1.5 → 6.0.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/index.d.ts CHANGED
@@ -1,142 +1,70 @@
1
1
  type Store = {
2
- get: (key: string) => Promise<any>;
3
- set: (key: string, value: any, options: { EX: number }) => Promise<null>;
4
- del: (key: string) => Promise<null>;
5
- keys: () => Promise<string[]>;
6
- exists: (key: string) => Promise<boolean>;
7
- flushAll: () => Promise<any>;
2
+ get: (key: string) => Promise<any>;
3
+ set: (key: string, value: any, options?: any) => Promise<any>;
4
+ del: (key: string) => Promise<any>;
5
+ has?: (key: string) => Promise<boolean>;
6
+ clear?: () => Promise<any>;
8
7
  };
9
-
10
- type Cache =
11
- | boolean
12
- | number
13
- | string
14
- | {
15
- expire?: number | string;
16
- store?: Store;
17
- shouldCache?: (request) => boolean;
18
- createKey?: (request) => string;
19
- };
20
-
21
- type Headers = { [name: string]: string };
22
- type Query = { [name: string]: string };
23
-
24
- type Methods = "get" | "head" | "post" | "patch" | "put" | "delete";
25
-
8
+ type Headers = {
9
+ [name: string]: string;
10
+ };
11
+ type Query = {
12
+ [name: string]: string;
13
+ };
14
+ type Methods = "get" | "head" | "post" | "patch" | "put" | "delete" | "GET" | "HEAD" | "POST" | "PATCH" | "PUT" | "DELETE";
15
+ type Body = string | any[] | {
16
+ [key: string]: any;
17
+ } | FormData | HTMLFormElement | SubmitEvent | ReadableStream;
26
18
  type Options = {
27
- url?: string;
28
- method?: Methods;
29
- query?: Query;
30
- headers?: Headers;
31
- baseUrl?: string;
32
- baseURL?: string;
33
- cache?: Cache;
34
- output?: string;
35
- credentials?: string;
36
- before?: (req: any) => any;
37
- after?: (res: any) => any;
38
- error?: (error: Error) => any;
39
- signal?: AbortSignal;
40
- [key: string]: any;
19
+ url?: string;
20
+ method?: Methods;
21
+ query?: Query;
22
+ headers?: Headers;
23
+ baseUrl?: string;
24
+ baseURL?: string;
25
+ cache?: Store;
26
+ output?: string;
27
+ credentials?: string;
28
+ before?: (req: any) => any;
29
+ after?: (res: any) => any;
30
+ error?: (error: Error) => any;
31
+ signal?: AbortSignal;
32
+ [key: string]: any;
41
33
  };
42
-
43
- type FullOptions = Options & { url: "string" };
44
-
45
- type Body =
46
- | string
47
- | any[]
48
- | { [key: string]: any }
49
- | FormData
50
- | HTMLFormElement
51
- | SubmitEvent
52
- | ReadableStream;
53
-
54
- declare function fch(url: string, options?: Options): Promise<any>;
55
-
56
- declare module fch {
57
- var url: string;
58
- var method: Methods;
59
- var query: Query;
60
- var headers: Headers;
61
- var baseUrl: string;
62
- var baseURL: string;
63
- var cache: Cache;
64
- var output: string;
65
- var credentials: string;
66
- var before: (req: any) => any;
67
- var after: (res: any) => any;
68
- var error: (error: Error) => any;
69
- var signal: AbortSignal;
70
-
71
- /**
72
- * Creates an instance of fch with the given options, perfect for custom APIs:
73
- *
74
- * ```js
75
- * const api = fch.create({
76
- * baseUrl: 'https://api.myapi.com/',
77
- * headers: { apiVersion: 2 }
78
- * })
79
- * ```
80
- */
81
- function create(options?: FullOptions): typeof fch;
82
-
83
- /**
84
- * Make a GET request to the given endpoint:
85
- *
86
- * ```js
87
- * const data = await fch.get('/path')
88
- * const data = await fch.get('/path', options)
89
- */
90
- function get(url: string, options?: Options): Promise<any>;
91
-
92
- /**
93
- * Make a HEAD request to the given endpoint:
94
- *
95
- * ```js
96
- * const data = await fch.head('/path')
97
- * const data = await fch.head('/path', options)
98
- */
99
- function head(url: string, options?: Options): Promise<any>;
100
-
101
- /**
102
- * Make a POST request to the given endpoint:
103
- *
104
- * ```js
105
- * const data = await fch.post('/path', body)
106
- * const data = await fch.post('/path', body, options)
107
- * ```
108
- */
109
- function post(url: string, body?: Body, options?: Options): Promise<any>;
110
-
111
- /**
112
- * Make a PATCH request to the given endpoint:
113
- *
114
- * ```js
115
- * const data = await fch.patch('/path', body)
116
- * const data = await fch.patch('/path', body, options)
117
- * ```
118
- */
119
- function put(url: string, body?: Body, options?: Options): Promise<any>;
120
-
121
- /**
122
- * Make a PUT request to the given endpoint:
123
- *
124
- * ```js
125
- * const data = await fch.put('/path', body)
126
- * const data = await fch.put('/path', body, options)
127
- * ```
128
- */
129
- function patch(url: string, body?: Body, options?: Options): Promise<any>;
130
-
131
- /**
132
- * Make a DELETE request to the given endpoint:
133
- *
134
- * ```js
135
- * const data = await fch.del('/patd)
136
- * const data = await fch.del('/patd, options)
137
- * ```
138
- */
139
- function del(url: string, body?: Body, options?: Options): Promise<any>;
34
+ interface FchInstance {
35
+ (url?: string, options?: Options): Promise<any>;
36
+ create: (options?: Options) => FchInstance;
37
+ get: (url: string, options?: Options) => Promise<any>;
38
+ head: (url: string, options?: Options) => Promise<any>;
39
+ post: (url: string, body?: Body, options?: Options) => Promise<any>;
40
+ patch: (url: string, body?: Body, options?: Options) => Promise<any>;
41
+ put: (url: string, body?: Body, options?: Options) => Promise<any>;
42
+ delete: (url: string, options?: Options) => Promise<any>;
43
+ del: (url: string, options?: Options) => Promise<any>;
44
+ text: () => Promise<string>;
45
+ json: () => Promise<any>;
46
+ blob: () => Promise<Blob>;
47
+ stream: () => ReadableStream | null;
48
+ arrayBuffer: () => Promise<ArrayBuffer>;
49
+ formData: () => Promise<FormData>;
50
+ body: () => Promise<any>;
51
+ clone: () => Response;
52
+ raw: () => Response;
53
+ response: () => Promise<any>;
54
+ url: string;
55
+ method: Methods;
56
+ query: Query;
57
+ headers: Headers;
58
+ baseUrl: string | null;
59
+ baseURL: string | null;
60
+ cache: Store | null;
61
+ output: string;
62
+ credentials: string;
63
+ before?: (req: any) => any;
64
+ after?: (res: any) => any;
65
+ error?: (error: Error) => any;
140
66
  }
141
-
142
- export default fch;
67
+ declare function create(defaults?: Options): FchInstance;
68
+ export { create };
69
+ declare const _default: FchInstance;
70
+ export default _default;
package/index.min.js CHANGED
@@ -1,2 +1 @@
1
- var d=async e=>(e=await e,Array.isArray(e)?await Promise.all(e.map(d)):e),y=(e,n)=>(...a)=>(r=>r instanceof RegExp?r.test.bind(r):r)(e).call(n,...a),L=(e,n)=>async(a,r,t)=>({value:a,extra:await y(e,n)(a,r,t)}),T=({extra:e})=>e,D=({value:e})=>e,F={every:async(e,n,a)=>{for(let r=0;r<e.length;r++)if(!await y(n,a)(e[r],r,e))return!1;return!0},filter:async(e,n,a)=>(await d(e.map(L(n,a)))).filter(T).map(D),find:async(e,n,a)=>{for(let r=0;r<e.length;r++)if(await y(n,a)(e[r],r,e))return e[r]},findIndex:async(e,n,a)=>{for(let r=0;r<e.length;r++)if(await y(n,a)(e[r],r,e))return r;return-1},forEach:async(e,n,a)=>(await d(e.map(L(n,a))),e),reduce:async(e,n,a)=>{let r=a!==void 0;r||(a=e[0]);for(let t=r?0:1;t<e.length;t++)a=await y(n)(a,e[t],t,e);return a},reduceRight:async(e,n,a)=>{let r=a!==void 0;r||(a=e[e.length-1]);for(let t=e.length-(r?1:2);t>=0;t--)a=await y(n)(a,e[t],t,e);return a},some:async(e,n,a)=>{for(let r=0;r<e.length;r++)if(await y(n,a)(e[r],r,e))return!0;return!1}},U=(e,n)=>(a,r)=>r==="then"?(...t)=>d(e).then(...t):r==="catch"?(...t)=>p(d(e).catch(...t)):h(d(e).then(t=>typeof r=="symbol"?t[r]:r in n?h((...o)=>n[r](t,...o),n):typeof t=="number"&&r in n.number?h((...o)=>n.number[r](t,...o),n):typeof t=="string"&&r in n.string?h((...o)=>n.string[r](t,...o),n):Array.isArray(t)&&r in n.array?h((...o)=>n.array[r](t,...o),n):t[r]&&t[r].bind?h(t[r].bind(t),n):h(t[r],n)),n),M=(e,n)=>(a,r,t)=>h(d(e).then(o=>{return typeof o!="function"?(c=`You tried to call "${JSON.stringify(o)}" (${typeof o}) as a function, but it is not.`,Promise.reject(new Error(c))):o(...t);var c}),n),h=(e,n)=>new Proxy(()=>{},{get:U(e,n),apply:M(e,n)});function p(e,{number:n,string:a,array:r,...t}={}){return typeof e=="function"?(...o)=>p(Promise.all(o).then(c=>e(...c)),{number:n,string:a,array:r,...t}):new Proxy({},{get:U(e,{number:{...n},string:{...a},array:{...F,...r},...t})})}function w(e){e.expire||(e.expire=0);let n=new Map,a=async r=>{if(!n.has(r))return!1;let{time:t,expire:o}=n.get(r);return!(!o||new Date().getTime()-t>o*1e3)};return{get:async r=>{if(!await a(r))return null;let{data:o}=n.get(r);return o},set:async(r,t,o={})=>{let c=new Date().getTime(),f=o.EX||o.expire||e.expire;return n.set(r,{time:c,expire:f,data:t})},keys:async()=>[...n.keys()],del:async r=>n.delete(r),exists:a,flushAll:()=>n.clear()}}var j=/(-?(?:\d+\.?\d*|\d*\.?\d+)(?:e[-+]?\d+)?)\s*([\p{L}]*)/iu;s.millisecond=s.ms=1;s.second=s.sec=s.s=s[""]=s.ms*1e3;s.minute=s.min=s.m=s.s*60;s.hour=s.hr=s.h=s.m*60;s.day=s.d=s.h*24;s.week=s.wk=s.w=s.d*7;s.year=s.yr=s.y=s.d*365.25;s.month=s.b=s.y/12;function s(e=""){if(!e)return 0;if(e===!0)return 60*60*1e3;if(typeof e=="number")return e;e=e.toLowerCase().replace(/[,_]/g,"");let[n,a,r]=j.exec(e)||[];r=s[r]||s[r.replace(/s$/,"")]||1e3;let t=r*parseFloat(a,10);return Math.abs(Math.round(t))}var O=e=>!e||e instanceof FormData||typeof(e.pipe||e.pipeTo)=="function"?!1:typeof e=="object"||Array.isArray(e),b=e=>{if(typeof e!="object")return e;for(let n in e)e[n]===void 0&&delete e[n];return e},g=class extends Error{constructor(n){let a="Error "+n.status;super(a),this.response=n,this.message=a}},B=(e,n,a)=>{let[r,t={}]=e.split("?"),o=new URLSearchParams(Object.fromEntries([...new URLSearchParams(b(n)),...new URLSearchParams(b(t))])).toString();return o&&(r=r+"?"+o),a?new URL(r.replace(/^\//,""),a).href:r},J=e=>{let n={};for(let[a,r]of Object.entries(e))n[a.toLowerCase()]=r;return n},v=async e=>{let n=e.headers.get("content-type"),a=n&&n.includes("application/json"),r=await e.clone().text();return a?JSON.parse(r):r},S=async e=>{let n={status:e.status,statusText:e.statusText,headers:{}};for(let a of e.headers.keys())n.headers[a.toLowerCase()]=e.headers.get(a);if(!e.ok)throw new g(e);return n.body=await v(e),n},k=(e,{ref:n,after:a,error:r,output:t})=>fetch(e.url,e).then(async o=>{if(n.res=o,o.ok&&t==="stream")return o.body;if(o.ok&&o[t]&&typeof o[t]=="function")return o[t]();let c=a(await S(o));if(t==="body")return c.body;if(t==="response")return c;if(t==="raw")return o.clone();throw new Error(`Invalid option output="${t}"`)}).catch(r),$=e=>e.method==="get",q=e=>e.method+":"+e.url,H=({store:e,...n}={},a)=>{let r={store:e?p(e):w({expire:s(n.expire)}),shouldCache:$,createKey:q,...n};return r.clear=()=>Promise.resolve(r.store).then(t=>t?.flushAll()),a&&(r.shouldCache=()=>!1),r};function x(e={}){let n={},a={},t=p(async(o="/",c={})=>{let{output:f,before:P,after:E,error:C,cache:K,...i}={...t,...c},l={...t.cache},A=u=>["number","string","boolean"].includes(typeof u);if(l.expire=s([c.cache?.expire,c.cache,l?.expire,l].find(A)),i.url=B(o,{...t.query,...c.query},i.baseUrl??i.baseURL),i.method=i.method.toLowerCase()||"GET",i.headers=J({...t.headers,...c.headers}),typeof SubmitEvent<"u"&&i.body instanceof SubmitEvent&&(i.body=new FormData(i.body.target)),typeof HTMLFormElement<"u"&&i.body instanceof HTMLFormElement&&(i.body=new FormData(i.body)),O(i.body)&&(i.body=JSON.stringify(b(i.body)),i.headers["content-type"]="application/json"),i=P(i),l.shouldCache(i)&&l.expire){let u=l.createKey(i);if(l.store?.then){let R=await l.store;l.store=R}if(await l.store.exists(u))return l.store.get(u);if(n[u])return n[u];let m;try{n[u]=k(i,{ref:a,cache:l,output:f,error:C,after:E}),m=await n[u]}finally{delete n[u]}return await l.store.set(u,m,{EX:l.expire}),m}return k(i,{ref:a,output:f,error:C,after:E})},{text:()=>a.res.text(),json:()=>a.res.json(),blob:()=>a.res.blob(),stream:()=>a.res.body,arrayBuffer:()=>a.res.arrayBuffer(),formData:()=>a.res.formData(),body:()=>v(a.res),clone:()=>a.res.clone(),raw:()=>a.res.clone(),response:()=>S(a.res.clone())});return t.url=e.url??"/",t.method=e.method??"get",t.query=e.query??{},t.headers=e.headers??{},t.baseUrl=e.baseUrl??e.baseURL??null,["number","string","boolean"].includes(typeof e.cache)&&(e.cache={expire:e.cache}),t.cache=H(e.cache,e.cache?.expire===!1||e.cache?.expire===0),t.output=e.output??"body",t.credentials=e.credentials??"include",t.before=e.before??(o=>o),t.after=e.after??(o=>o),t.error=e.error??(o=>Promise.reject(o)),t.get=(o,c)=>t(o,{method:"get",...c}),t.head=(o,c)=>t(o,{method:"head",...c}),t.post=(o,c,f)=>t(o,{method:"post",body:c,...f}),t.patch=(o,c,f)=>t(o,{method:"patch",body:c,...f}),t.put=(o,c,f)=>t(o,{method:"put",body:c,...f}),t.delete=(o,c)=>t(o,{method:"delete",...c}),t.del=t.delete,t.create=x,t}typeof window<"u"&&(window.fch=x());var G=x();export{x as create,G as default,s as parse};
2
- //# sourceMappingURL=index.min.js.map
1
+ var S=async(i)=>(i=await i,Array.isArray(i)?await Promise.all(i.map(S)):i),N=(i,w)=>(...x)=>((n)=>n instanceof RegExp?n.test.bind(n):n)(i).call(w,...x),O=(i,w)=>async(x,n,m)=>({value:x,extra:await N(i,w)(x,n,m)}),_=({extra:i})=>i,D=({value:i})=>i,Q={every:async(i,w,x)=>{for(let n=0;n<i.length;n++)if(!await N(w,x)(i[n],n,i))return!1;return!0},filter:async(i,w,x)=>(await S(i.map(O(w,x)))).filter(_).map(D),find:async(i,w,x)=>{for(let n=0;n<i.length;n++)if(await N(w,x)(i[n],n,i))return i[n]},findIndex:async(i,w,x)=>{for(let n=0;n<i.length;n++)if(await N(w,x)(i[n],n,i))return n;return-1},forEach:async(i,w,x)=>(await S(i.map(O(w,x))),i),reduce:async(i,w,x)=>{let n=x!==void 0;n||(x=i[0]);for(let m=n?0:1;m<i.length;m++)x=await N(w)(x,i[m],m,i);return x},reduceRight:async(i,w,x)=>{let n=x!==void 0;n||(x=i[i.length-1]);for(let m=i.length-(n?1:2);m>=0;m--)x=await N(w)(x,i[m],m,i);return x},some:async(i,w,x)=>{for(let n=0;n<i.length;n++)if(await N(w,x)(i[n],n,i))return!0;return!1}},T=(i,w)=>(x,n)=>n==="then"?(...m)=>S(i).then(...m):n==="catch"?(...m)=>Y(S(i).catch(...m)):v(S(i).then((m)=>typeof n=="symbol"?m[n]:(n in w)?v((...P)=>w[n](m,...P),w):typeof m=="number"&&(n in w.number)?v((...P)=>w.number[n](m,...P),w):typeof m=="string"&&(n in w.string)?v((...P)=>w.string[n](m,...P),w):Array.isArray(m)&&(n in w.array)?v((...P)=>w.array[n](m,...P),w):m[n]&&m[n].bind?v(m[n].bind(m),w):v(m[n],w)),w),F=(i,w)=>(x,n,m)=>v(S(i).then((P)=>{return typeof P!="function"?(g=`You tried to call "${JSON.stringify(P)}" (${typeof P}) as a function, but it is not.`,Promise.reject(Error(g))):P(...m);var g}),w),v=(i,w)=>new Proxy(()=>{},{get:T(i,w),apply:F(i,w)});function Y(i,{number:w,string:x,array:n,...m}={}){return typeof i=="function"?(...P)=>Y(Promise.all(P).then((g)=>i(...g)),{number:w,string:x,array:n,...m}):new Proxy({},{get:T(i,{number:{...w},string:{...x},array:{...Q,...n},...m})})}var H=(i)=>{if(!i)return!1;if(i instanceof FormData)return!1;if(typeof(i.pipe||i.pipeTo)==="function")return!1;return typeof i==="object"||Array.isArray(i)},G=(i)=>{if(typeof i!=="object")return i;for(let w in i)if(i[w]===void 0)delete i[w];return i};class W extends Error{response;constructor(i){let w="Error "+i.status;super(w);this.response=i,this.message=w}}var R=(i,w,x)=>{let[n,m=""]=i.split("?"),P=new URLSearchParams(Object.fromEntries([...new URLSearchParams(G(w)),...new URLSearchParams(G(m))])).toString();if(P)n=n+"?"+P;if(!x)return n;return new URL(n.replace(/^\//,""),x).href},B=(i)=>{let w={};for(let[x,n]of Object.entries(i))w[x.toLowerCase()]=n;return w},X=async(i)=>{let w=i.headers.get("content-type"),x=w&&w.includes("application/json"),n=await i.clone().text();return x?JSON.parse(n):n},Z=async(i)=>{let w={status:i.status,statusText:i.statusText,headers:{},body:void 0};if(i.headers.forEach((x,n)=>{w.headers[n.toLowerCase()]=x}),!i.ok)throw new W(i);return w.body=await X(i),w},V=(i,{ref:w,after:x,error:n,output:m})=>{return fetch(i.url,i).then(async(P)=>{if(w.res=P,P.ok&&m==="stream")return P.body;if(P.ok&&P[m]&&typeof P[m]==="function")return P[m]();let g=x(await Z(P));if(m==="body")return g.body;else if(m==="response")return g;else if(m==="raw")return P.clone();else throw Error(`Invalid option output="${m}"`)}).catch(n)};function I(i={}){let w={},x={},m=Y(async(P="/",g={})=>{let{output:$,before:J,after:K,error:L,cache:z,...A}={...m,...g};if(A.url=R(P,{...m.query,...g.query},A.baseUrl??A.baseURL),A.method=(A.method||"get").toLowerCase(),A.headers=B({...m.headers,...g.headers}),typeof SubmitEvent<"u"&&A.body instanceof SubmitEvent||typeof HTMLFormElement<"u"&&A.body instanceof HTMLFormElement)A.body=new FormData(A.body);if(H(A.body))A.body=JSON.stringify(G(A.body)),A.headers["content-type"]="application/json";if(A=J?J(A):A,!z||A.method!=="get")return V(A,{ref:x,output:$,error:L,after:K});let E=A.method+":"+A.url,M=await z.get(E);if(M)return M;if(w[E])return w[E];let C;try{w[E]=V(A,{ref:x,output:$,error:L,after:K}),C=await w[E]}finally{delete w[E]}return await z.set(E,C),C},{text:()=>x.res.clone().text(),json:()=>x.res.clone().json(),blob:()=>x.res.clone().blob(),stream:()=>x.res.clone().body,arrayBuffer:()=>x.res.clone().arrayBuffer(),formData:()=>x.res.clone().formData(),body:()=>X(x.res.clone()),clone:()=>x.res.clone(),raw:()=>x.res.clone(),response:()=>Z(x.res.clone())});return m.url=i.url??"/",m.method=i.method??"get",m.query=i.query??{},m.headers=i.headers??{},m.baseUrl=i.baseUrl??i.baseURL??null,m.baseURL=i.baseUrl??i.baseURL??null,m.cache=i.cache??null,m.output=i.output??"body",m.credentials=i.credentials??"include",m.before=i.before??((P)=>P),m.after=i.after??((P)=>P),m.error=i.error??((P)=>Promise.reject(P)),m.get=(P,g)=>m(P,{method:"get",...g}),m.head=(P,g)=>m(P,{method:"head",...g}),m.post=(P,g,$)=>m(P,{method:"post",body:g,...$}),m.patch=(P,g,$)=>m(P,{method:"patch",body:g,...$}),m.put=(P,g,$)=>m(P,{method:"put",body:g,...$}),m.delete=(P,g)=>m(P,{method:"delete",...g}),m.del=m.delete,m.create=I,m}if(typeof window<"u")window.fch=I();var j=I();export{j as default,I as create};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fch",
3
- "version": "5.1.5",
3
+ "version": "6.0.1",
4
4
  "description": "Fetch interface with better promises, deduplication, defaults, etc.",
5
5
  "homepage": "https://github.com/franciscop/fetch",
6
6
  "repository": "https://github.com/franciscop/fetch.git",
@@ -9,10 +9,13 @@
9
9
  "author": "Francisco Presencia <public@francisco.io> (https://francisco.io/)",
10
10
  "license": "MIT",
11
11
  "scripts": {
12
- "build": "esbuild src/index.js --bundle --minify --sourcemap --outfile=index.min.js --format=esm",
12
+ "build": "npm run build:bundle && npm run build:types",
13
+ "build:bundle": "bun build src/index.ts --outfile=index.min.js --minify --format=esm",
14
+ "build:types": "tsc --emitDeclarationOnly --outDir .",
15
+ "typecheck": "tsc --noEmit src/**/*.ts",
13
16
  "size": "echo $(gzip -c index.min.js | wc -c) bytes",
14
- "start": "node --experimental-vm-modules node_modules/jest/bin/jest.js --watch --coverage --detectOpenHandles",
15
- "test": "node --experimental-vm-modules node_modules/jest/bin/jest.js --coverage --detectOpenHandles && check-dts"
17
+ "start": "bun test --watch",
18
+ "test": "npm run typecheck && bun test"
16
19
  },
17
20
  "keywords": [
18
21
  "fetch",
@@ -25,8 +28,7 @@
25
28
  "main": "index.min.js",
26
29
  "files": [
27
30
  "index.min.js",
28
- "index.d.ts",
29
- "index.min.js.map"
31
+ "index.d.ts"
30
32
  ],
31
33
  "types": "index.d.ts",
32
34
  "type": "module",
@@ -34,20 +36,10 @@
34
36
  "node": ">=18.0.0"
35
37
  },
36
38
  "devDependencies": {
37
- "check-dts": "^0.7.2",
38
- "dotenv": "^16.3.1",
39
- "esbuild": "^0.19.2",
40
- "jest": "^28.1.0",
41
- "jest-environment-jsdom": "^28.1.0",
42
- "jest-fetch-mock": "^3.0.3",
43
- "redis": "^4.6.10",
44
- "swear": "^1.1.2"
45
- },
46
- "jest": {
47
- "testEnvironment": "jest-environment-node",
48
- "transform": {},
49
- "setupFiles": [
50
- "./test/setup.js"
51
- ]
39
+ "@types/bun": "^1.3.11",
40
+ "@types/node": "^25.5.0",
41
+ "polystore": "^0.19.0",
42
+ "swear": "^1.1.2",
43
+ "typescript": "^5.7.3"
52
44
  }
53
45
  }
package/readme.md CHANGED
@@ -1,4 +1,4 @@
1
- # Fch [![npm install fch](https://img.shields.io/badge/npm%20install-fch-blue.svg)](https://www.npmjs.com/package/fch) [![test badge](https://github.com/franciscop/fetch/workflows/tests/badge.svg "test badge")](https://github.com/franciscop/fetch/blob/master/.github/workflows/tests.yml) [![gzip size](https://img.badgesize.io/franciscop/fetch/master/index.min.js.svg?compression=gzip)](https://github.com/franciscop/fetch/blob/master/index.min.js)
1
+ # Fch [![npm install fch](https://img.shields.io/badge/npm%20install-fch-blue.svg)](https://www.npmjs.com/package/fch) [![test badge](https://github.com/franciscop/fetch/workflows/tests/badge.svg "test badge")](https://github.com/franciscop/fetch/actions) [![gzip size](https://img.badgesize.io/franciscop/fetch/master/index.min.js.svg?compression=gzip)](https://bundlephobia.com/package/fch)
2
2
 
3
3
  A tiny library to make API calls easier. Similar to Axios, but tiny size and simpler API:
4
4
 
@@ -17,7 +17,7 @@ await api.patch("/pokemon/150", { type: "psychic" });
17
17
  - Create instances with shared options across requests.
18
18
  - Configurable **cache** that works in-memory, with redis, or others.
19
19
  - Automatically encode and decode JSON bodies.
20
- - Await/Async Promises; `>= 400 and <= 100` will throw an error.
20
+ - Await/Async Promises; non-OK responses (status < 200 or >= 300) will throw an error.
21
21
  - Credentials: "include" by default
22
22
  - Interceptors: `before` the request, `after` the response and catch with `error`.
23
23
  - Designed for both Node.js and the browser through its extensible cache system.
@@ -46,7 +46,7 @@ api.del(url, { headers, ...options });
46
46
  | [`query`](#query) | `{}` | Add query parameters to the URL |
47
47
  | [`headers`](#headers) | `{}` | Shared headers across all requests |
48
48
  | [`output`](#output) | `"body"` | The return value of the API call |
49
- | [`cache`](#cache) | `{ expire: 0 }` | How long to reuse the response body |
49
+ | [`cache`](#cache) | `false` | How long to reuse the response body |
50
50
  | [`before`](#interceptors) | `req => req` | Process the request before sending it |
51
51
  | [`after`](#interceptors) | `res => res` | Process the response before returning it |
52
52
  | [`error`](#interceptors) | `err => throw err` | Process errors before returning them |
@@ -92,7 +92,7 @@ api.headers = {}; // Merged with the headers on a per-request basis
92
92
 
93
93
  // Control simple variables
94
94
  api.output = "body"; // Return the parsed body; use 'response' or 'stream' otherwise
95
- api.cache = { expires: 0 }; // Avoid sending GET requests that were already sent recently
95
+ api.cache = false; // Avoid sending GET requests that were already sent recently
96
96
 
97
97
  // Interceptors
98
98
  api.before = (req) => req;
@@ -126,8 +126,8 @@ api.get(...);
126
126
  api.GET(...);
127
127
 
128
128
  // Both of these are valid:
129
- api({ method; 'GET' })
130
- api({ method; 'get'})
129
+ api({ method: 'GET' })
130
+ api({ method: 'get'})
131
131
  ```
132
132
 
133
133
  Example: adding a new cat and fixing a typo:
@@ -156,9 +156,9 @@ It can be either absolute or relative, in which case it'll use the local one in
156
156
 
157
157
  ```js
158
158
  import api from "fch";
159
- api.baseUrl = "https//api.filemon.io/";
159
+ api.baseUrl = "https://api.filemon.io/";
160
160
  api.get("/hello");
161
- // Called https//api.filemon.io/hello
161
+ // Called https://api.filemon.io/hello
162
162
  ```
163
163
 
164
164
  > Note: with Node.js you need to either set an absolute baseUrl or make the URL absolute
@@ -170,10 +170,10 @@ api.get("/hello");
170
170
  The `body` can be a string, a plain object|array, a FormData instance, a ReadableStream, a SubmitEvent or a HTMLFormElement. If it's a plain array or object, it'll be stringified and the header `application/json` will be added:
171
171
 
172
172
  ```js
173
- import api from "api";
173
+ import fch from "fch";
174
174
 
175
175
  // Sending plain text
176
- await api.post("/houses", "plain text");
176
+ await fch.post("/houses", "plain text");
177
177
 
178
178
  // Will JSON.stringify it internally and add the JSON headers
179
179
  await api.post("/houses", { id: 1, name: "Cute Cottage" });
@@ -182,12 +182,12 @@ await api.post("/houses", { id: 1, name: "Cute Cottage" });
182
182
  form.onsubmit = (e) => api.post("/houses", new FormData(e.target));
183
183
 
184
184
  // We have some helpers so you can just pass the Event or <form> itself!
185
- form.onsubmit = (e) => api.post("/houses", e); // does not work with jquery BTW
185
+ form.onsubmit = (e) => api.post("/houses", e);
186
186
  form.onsubmit = (e) => api.post("/houses", e.target);
187
187
  form.onsubmit = (e) => api.post("/houses", new FormData(e.target));
188
188
  ```
189
189
 
190
- The methods `GET`, `HEAD` and `DELETE` do not accept a body and it'll be ignored if you try to force it into the options.
190
+ The methods `GET` and `HEAD` do not accept a body. For `DELETE`, while not common, you can pass a body via the options parameter if needed: `fch.delete('/resource', { body: {...} })`.
191
191
 
192
192
  ### Query
193
193
 
@@ -226,7 +226,7 @@ You can define headers in 4 ways:
226
226
  - Globally, in which case they'll be added to every request
227
227
  - On an instance, so they are added every time you use that instance
228
228
  - Per-request, so that they are only added to the current request.
229
- - In the `before` interceptor, which again can be globa, on an instance, or per-request
229
+ - In the `before` interceptor, which again can be global, on an instance, or per-request
230
230
 
231
231
  ```js
232
232
  import fch from "fch";
@@ -295,7 +295,7 @@ There are few options that can be specified:
295
295
  - `output: "response"`: return the full response with the properties `body`, `headers`, `status`. The body will be parsed as JSON or plain TEXT depending on the headers. If you want the raw `response`, use `raw` or `clone` instead (see below in "raw" or "clone").
296
296
  - `output: "stream"`: return a [web ReadableStream](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream) of the body as the result of the promise.
297
297
  - `output: "arrayBuffer"`\*: returns an arrayBuffer of the response body.
298
- - `output: "blob"`\*: returns an arrayBuffer of the response body.
298
+ - `output: "blob"`\*: returns a Blob of the response body.
299
299
  - `output: "clone"`\*: returns the raw Response, with the raw body. See also `raw` below.
300
300
  - `output: "formData"`\* (might be unavailable): returns an instance of FormData with all the parsed data.
301
301
  - `output: "json"`\*: attempts to parse the response as JSON.
@@ -326,131 +326,93 @@ stream.pipeTo(...);
326
326
 
327
327
  ### Cache
328
328
 
329
- The cache (disabled by default) is a great method to reduce the number of API requests we make. While it's possible to modify the global fch to add a cache, we recommend to always use it per-instance or per-request. Options:
329
+ > We use **[polystore](https://polystore.dev/)** for Cache management.
330
+
331
+ The cache (disabled by default) is a great method to reduce the number of API requests we make. Provide a [polystore](https://polystore.dev/) Store instance directly to `fch.create()` (or per request) and fch will cache GET responses using whatever persistence that store offers. Set `cache` to `null` on a call to skip caching entirely. Legacy cache helpers such as `shouldCache`, `generateKey`, or expiry options have been removed; fch now relies purely on the semantics of the Polystore Store you pass in.
332
+
330
333
 
331
- - `expire`: the amount of time the cached data will be valid for, it can be a number (seconds) or a string such as `1hour`, `1week`, etc. (based on [parse-duration](https://github.com/jkroso/parse-duration))
332
- - `store`: the store where the cached data will be stored.
333
- - `shouldCache`: a function that returns a boolean to determine whether the current data should go through the cache process.
334
- - `createKey`: a function that takes the request and generates a unique key for that request, which will be the same for the next time that same request is made. Defaults to method+url.
335
334
 
336
- > Note: cache should only be used through `fch.create({ cache: ... })`, not through the global instance.
335
+ While a GET request is in flight, fch keeps an internal map of ongoing requests so additional calls reuse the same promise instead of triggering duplicate fetches. As soon as the request resolves, the result is written to your store (if available) and the entry is removed from the in-flight map.
337
336
 
338
- To activate the cache, we just need to set a time as such:
337
+ To activate the cache, create a polystore store and pass it to fch:
339
338
 
340
339
  ```js
341
- // This API has 1h by default:
340
+ import kv from "polystore";
341
+
342
+ // This API reuses responses using an in-memory Map:
343
+ const cache = kv(new Map());
342
344
  const api = fch.create({
343
- baseUrl: 'https://api.myweb.com/'
344
- cache: '1h'
345
+ cache,
346
+ baseUrl: "https://api.myweb.com/",
345
347
  });
346
348
 
347
- // This specific call will be cached for 20s
348
- api.get('/somedata', { cache: '20s' });
349
+ // Provide a different store per request if needed
350
+ const shortCache = kv(new Map());
351
+ api.get("/somedata", { cache: shortCache });
349
352
  ```
350
353
 
351
- Your cache will have a `store`; by default we create an in-memory store, but you can also use `redis` and it's fully compatible. Note now `cache` is now an object:
354
+ For more control, you can use **polystore** to create a custom cache store with different backends (in-memory, Redis, localStorage, etc.):
352
355
 
353
356
  ```js
354
357
  import fch from "fch";
355
- import { createClient } from "redis";
358
+ import kv from "polystore";
356
359
 
357
- // You can either pass the store instance, or a promise that will
358
- // return the instance. In this case we are doing the latter
359
- const store = createClient().connect();
360
+ // In-memory cache backed by a Map
361
+ const cache = kv(new Map());
360
362
 
361
363
  const api = fch.create({
362
- cache: {
363
- store: store,
364
- expire: "1h",
365
- },
364
+ baseUrl: "https://api.myweb.com/",
365
+ cache,
366
366
  });
367
367
  ```
368
368
 
369
- That's the basic usage, but "invalidating cache" is not one of the complex topics in CS for no reason. Let's dig deeper. To clear the cache, you can call `cache.clear()` at any time:
370
-
371
- ```js
372
- const api = fch.create({ cache: "1h" });
373
-
374
- // Remove them all
375
- await api.cache.clear();
376
- ```
377
-
378
- You can always access the store of the instance through `api.cache.store`, so we can do low-level operations on the store as such if needed:
369
+ Polystore supports multiple backends. For example, with Redis:
379
370
 
380
371
  ```js
381
372
  import fch from "fch";
373
+ import kv from "polystore";
382
374
  import { createClient } from "redis";
383
375
 
384
- // Initialize it straight away
385
- const api = fch.create({
386
- cache: {
387
- store: createClient().connect(),
388
- expire: "1h",
389
- },
390
- });
391
-
392
- // Later on, maybe in a different place
393
- await api.cache.store.flushDB();
394
- ```
395
-
396
- Finally, the other two bits that are relevant for cache are `shouldCache` and `createKey`. For the most basic examples the default probably works, but you might want more advanced configuration:
376
+ // Redis-backed cache store
377
+ const redis = await createClient().connect();
378
+ const cache = kv(redis);
397
379
 
398
- ```js
399
380
  const api = fch.create({
400
- cache: {
401
- // Default shouldCache; Note the lowercase
402
- shouldCache: (request) => request.method === "get",
403
-
404
- // Default createKey;
405
- createKey: (request) => request.method + ":" + request.url,
406
- },
381
+ cache,
407
382
  });
408
383
  ```
409
384
 
410
- For example, if you want to differentiate the auth requests from the non-auth requests, you can do it so:
385
+ That's the basic usage, but "invalidating cache" is not one of the complex topics in CS for no reason. Let's dig deeper. To clear the cache, you can call `cache.clear()` at any time:
411
386
 
412
387
  ```js
413
- import api from "./api";
388
+ import kv from "polystore";
414
389
 
415
- const onLogin = (user) => {
416
- // ... Do some other stuff
390
+ const cache = kv(new Map());
391
+ const api = fch.create({ cache });
417
392
 
418
- // Remove the old requests since we were not auth'ed yet
419
- api.cache.clear();
420
-
421
- // Create a key unique for this user
422
- api.cache.createKey = (req) => user.id + ":" + req.method + ":" + req.url;
423
- };
393
+ // Remove them all
394
+ await cache.clear();
424
395
  ```
425
396
 
426
- Or maybe you just want to NOT cache any of the requests that have an `Authorization` header, you can do so:
397
+ You can also access the underlying store directly through the polystore instance to perform low-level operations:
427
398
 
428
399
  ```js
429
- const api = fch.create({
430
- cache: {
431
- expire: "1week",
400
+ import fch from "fch";
401
+ import kv from "polystore";
402
+ import { createClient } from "redis";
432
403
 
433
- // Note the lowercase in both! we normalize them to be lowercase
434
- shouldCache: (req) => req.method === "get" && !req.headers.authorization,
435
- },
436
- });
437
- ```
404
+ const redis = await createClient().connect();
405
+ const cache = kv(redis);
438
406
 
439
- It is this flexible since you can use fch both in the front-end and back-end, so usually in each of them you might want to follow a slightly different strategy.
407
+ const api = fch.create({ cache });
440
408
 
441
- #### Creating a store.
409
+ // Later on, you can access the underlying Redis client
410
+ await redis.flushDB();
411
+ ```
442
412
 
443
- You might want to create a custom store. Please have a look at `src/store.js`, but basically you need an object that implements these methods:
413
+ #### Creating a custom store
444
414
 
445
- ```js
446
- type Store = {
447
- get: (key: string) => Promise<any>,
448
- set: (key: string, value: any, options?: { EX: number }) => Promise<null>,
449
- del: (key: string) => Promise<null>,
450
- exists: (key: string) => Promise<boolean>,
451
- flushAll: () => Promise<any>,
452
- };
453
- ```
415
+ You can create a custom store that works with fch by implementing the polystore-compatible interface. See the [polystore documentation](https://polystore.dev/) for details on creating custom stores and adapters.
454
416
 
455
417
  ### Interceptors
456
418
 
@@ -460,8 +422,6 @@ You can also add the interceptors `before`, `after` and `error`:
460
422
  - `after`: Called just after the response is created and if there was no error, but before parsing anything else.
461
423
  - `error`: When the response is not okay, if possible it'll include the `response` object.
462
424
 
463
- > Note: interceptors are never deduped/cached and always execute once per call, even if the main async fetch() has been deduped.
464
-
465
425
  ```js
466
426
  // Perform an action or request transformation before the request is sent
467
427
  fch.before = async req => {
@@ -571,8 +531,9 @@ import fch from "fch";
571
531
  // All the requests will add the Authorization header when the token is
572
532
  // in localStorage
573
533
  fch.before = (req) => {
574
- if (localStorage.get("token")) {
575
- req.headers.Authorization = "bearer " + localStorage.get("token");
534
+ const token = localStorage.getItem("token");
535
+ if (token) {
536
+ req.headers.Authorization = "bearer " + token;
576
537
  }
577
538
  return req;
578
539
  };
@@ -666,7 +627,7 @@ You can also [create an instance](#create-an-instance) that will have the same o
666
627
 
667
628
  First, we use the native Node.js' fetch() and the browser's native fetch(), so any difference between those also applies to this library. For example, if you were to call `"/"` in the browser it'd refer to the current URL, while in Node.js it'd fail since you need to specify the full URL. Some other places where you might find differences: CORS, cache, etc.
668
629
 
669
- In the library itself there's nothing different between the browser and Node.js, but it might be interesting to note that (if/when implemented) things like cache, etc. in Node.js are normally long-lived and shared, while in a browser request it'd bound to the request itself.
630
+ In the library itself there's nothing different between the browser and Node.js, but it might be interesting to note that things like ephemeral cache in Node.js are normally long-lived and shared, while in a browser request it'd bound to the browser runtime.
670
631
 
671
632
  ### Differences with Axios
672
633
 
@@ -686,23 +647,9 @@ axios.interceptors.request.use(fn);
686
647
  fch.before = fn;
687
648
  ```
688
649
 
689
- API size is also strikingly different, with **7.8kb** for Axios and **1.1kb** for fch.
650
+ API size is also strikingly different, with **7.8kb** for Axios and **2.1kb** for fch (gzipped).
690
651
 
691
652
  As disadvantages, I can think of two major ones for `fch`:
692
653
 
693
654
  - Requires Node.js 18+, which is the version that includes `fetch()` by default.
694
655
  - Does not support many of the more advanced options, like `onUploadProgress` nor `onDownloadProgress`.
695
-
696
- ## Releases
697
-
698
- ### V4
699
-
700
- Breaking changes:
701
-
702
- - Only ESM exports. Meaning, if you use it in a browser you'll need the `<script type="module">`.
703
- - The method `fch.del()` (and derivates with fch.create()) have been renamed to `fch.delete()`.
704
-
705
- Changes:
706
-
707
- - Added `output` options: `raw`, `stream`, `arrayBuffer`, `blob`, `clone`, `formData`, `json`, `text`
708
- - Gone from 1.2kb down to 1.0kb
package/index.min.js.map DELETED
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["node_modules/swear/index.min.js", "src/store.js", "src/index.js"],
4
- "sourcesContent": ["const t=async r=>(r=await r,Array.isArray(r)?await Promise.all(r.map(t)):r),r=(t,r)=>(...n)=>(t=>t instanceof RegExp?t.test.bind(t):t)(t).call(r,...n),n=(t,n)=>async(e,a,i)=>({value:e,extra:await r(t,n)(e,a,i)}),e=({extra:t})=>t,a=({value:t})=>t,i={every:async(t,n,e)=>{for(let a=0;a<t.length;a++){if(!await r(n,e)(t[a],a,t))return!1}return!0},filter:async(r,i,o)=>(await t(r.map(n(i,o)))).filter(e).map(a),find:async(t,n,e)=>{for(let a=0;a<t.length;a++){if(await r(n,e)(t[a],a,t))return t[a]}},findIndex:async(t,n,e)=>{for(let a=0;a<t.length;a++){if(await r(n,e)(t[a],a,t))return a}return-1},forEach:async(r,e,a)=>(await t(r.map(n(e,a))),r),reduce:async(t,n,e)=>{const a=void 0!==e;a||(e=t[0]);for(let i=a?0:1;i<t.length;i++)e=await r(n)(e,t[i],i,t);return e},reduceRight:async(t,n,e)=>{const a=void 0!==e;a||(e=t[t.length-1]);for(let i=t.length-(a?1:2);i>=0;i--)e=await r(n)(e,t[i],i,t);return e},some:async(t,n,e)=>{for(let a=0;a<t.length;a++){if(await r(n,e)(t[a],a,t))return!0}return!1}},o=(r,n)=>(e,a)=>\"then\"===a?(...n)=>t(r).then(...n):\"catch\"===a?(...n)=>c(t(r).catch(...n)):y(t(r).then((t=>\"symbol\"==typeof a?t[a]:a in n?y(((...r)=>n[a](t,...r)),n):\"number\"==typeof t&&a in n.number?y(((...r)=>n.number[a](t,...r)),n):\"string\"==typeof t&&a in n.string?y(((...r)=>n.string[a](t,...r)),n):Array.isArray(t)&&a in n.array?y(((...r)=>n.array[a](t,...r)),n):t[a]&&t[a].bind?y(t[a].bind(t),n):y(t[a],n))),n),s=(r,n)=>(e,a,i)=>y(t(r).then((t=>{return\"function\"!=typeof t?(r=`You tried to call \"${JSON.stringify(t)}\" (${typeof t}) as a function, but it is not.`,Promise.reject(new Error(r))):t(...i);var r})),n),y=(t,r)=>new Proxy((()=>{}),{get:o(t,r),apply:s(t,r)});export default function c(t,{number:r,string:n,array:e,...a}={}){return\"function\"==typeof t?(...i)=>c(Promise.all(i).then((r=>t(...r))),{number:r,string:n,array:e,...a}):new Proxy({},{get:o(t,{number:{...r},string:{...n},array:{...i,...e},...a})})}", "export default function createCache(options) {\n // no cache by default\n if (!options.expire) {\n options.expire = 0;\n }\n\n const cache = new Map();\n const exists = async (key) => {\n if (!cache.has(key)) return false;\n const { time, expire } = cache.get(key);\n if (!expire) return false;\n if (new Date().getTime() - time > expire * 1000) return false;\n return true;\n };\n return {\n get: async (key) => {\n const keyExists = await exists(key);\n if (!keyExists) return null;\n const { data } = cache.get(key);\n return data;\n },\n set: async (key, data, opts = {}) => {\n const time = new Date().getTime();\n const expire = opts.EX || opts.expire || options.expire;\n return cache.set(key, { time, expire, data });\n },\n keys: async () => [...cache.keys()],\n del: async (key) => {\n return cache.delete(key);\n },\n exists,\n flushAll: () => cache.clear(),\n };\n}\n", "import swear from \"swear\";\n\nimport createCacheStore from \"./store\";\n\nconst times = /(-?(?:\\d+\\.?\\d*|\\d*\\.?\\d+)(?:e[-+]?\\d+)?)\\s*([\\p{L}]*)/iu;\n\nparse.millisecond = parse.ms = 1;\nparse.second = parse.sec = parse.s = parse[\"\"] = parse.ms * 1000;\nparse.minute = parse.min = parse.m = parse.s * 60;\nparse.hour = parse.hr = parse.h = parse.m * 60;\nparse.day = parse.d = parse.h * 24;\nparse.week = parse.wk = parse.w = parse.d * 7;\nparse.year = parse.yr = parse.y = parse.d * 365.25;\nparse.month = parse.b = parse.y / 12;\n\nexport function parse(str = \"\") {\n if (!str) return 0;\n if (str === true) return 60 * 60 * 1000;\n if (typeof str === \"number\") return str;\n // ignore commas/placeholders\n str = str.toLowerCase().replace(/[,_]/g, \"\");\n let [_, value, units] = times.exec(str) || [];\n units = parse[units] || parse[units.replace(/s$/, \"\")] || 1000;\n const result = units * parseFloat(value, 10);\n return Math.abs(Math.round(result));\n}\n\n// Check if the body is an object/array, and if so return true so that it can be\n// properly JSON.stringify() + adding the proper ContentType\nconst hasObjectBody = (body) => {\n if (!body) return false;\n if (body instanceof FormData) return false;\n if (typeof (body.pipe || body.pipeTo) === \"function\") return false;\n return typeof body === \"object\" || Array.isArray(body);\n};\n\nconst noUndefined = (obj) => {\n if (typeof obj !== \"object\") return obj;\n for (let key in obj) {\n if (obj[key] === undefined) delete obj[key];\n }\n return obj;\n};\n\nclass ResponseError extends Error {\n constructor(response) {\n const message = \"Error \" + response.status;\n super(message);\n this.response = response;\n this.message = message;\n }\n}\n\nconst createUrl = (url, query, base) => {\n let [path, urlQuery = {}] = url.split(\"?\");\n\n // Merge global params with passed params with url params\n const entries = new URLSearchParams(\n Object.fromEntries([\n ...new URLSearchParams(noUndefined(query)),\n ...new URLSearchParams(noUndefined(urlQuery)),\n ])\n ).toString();\n if (entries) {\n path = path + \"?\" + entries;\n }\n\n if (!base) return path;\n const fullUrl = new URL(path.replace(/^\\//, \"\"), base);\n return fullUrl.href;\n};\n\nconst createHeaders = (raw) => {\n // User-set headers overwrite the base headers\n const headers = {};\n\n // Make the headers lowercase\n for (let [key, value] of Object.entries(raw)) {\n headers[key.toLowerCase()] = value;\n }\n\n return headers;\n};\n\nconst getBody = async (res) => {\n // Automatically parse the response\n const type = res.headers.get(\"content-type\");\n const isJson = type && type.includes(\"application/json\");\n const text = await res.clone().text();\n return isJson ? JSON.parse(text) : text;\n};\n\nconst parseResponse = async (res) => {\n // Need to manually create it to set some things like the proper response\n let response = {\n status: res.status,\n statusText: res.statusText,\n headers: {},\n };\n\n // Lowercase all of the response headers and put them into a plain object\n for (let key of res.headers.keys()) {\n response.headers[key.toLowerCase()] = res.headers.get(key);\n }\n\n // Oops, throw it\n if (!res.ok) {\n throw new ResponseError(res);\n }\n\n response.body = await getBody(res);\n\n return response;\n};\n\nconst createFetch = (request, { ref, after, error, output }) => {\n return fetch(request.url, request)\n .then(async (res) => {\n ref.res = res;\n\n // In this case, do not process anything else just return the ReadableStream\n if (res.ok && output === \"stream\") {\n return res.body;\n }\n\n // Raw methods requested\n if (res.ok && res[output] && typeof res[output] === \"function\") {\n return res[output]();\n }\n\n // Hijack the response and modify it, earlier than the manual body changes\n const response = after(await parseResponse(res));\n\n if (output === \"body\") {\n return response.body;\n } else if (output === \"response\") {\n return response;\n } else if (output === \"raw\") {\n return res.clone();\n } else {\n throw new Error(`Invalid option output=\"${output}\"`);\n }\n })\n .catch(error);\n};\n\nconst defaultShouldCache = (request) => request.method === \"get\";\nconst defaultCreateKey = (request) => request.method + \":\" + request.url;\n\nconst createCache = ({ store, ...options } = {}, noCache) => {\n const cache = {\n store: store\n ? swear(store)\n : createCacheStore({ expire: parse(options.expire) }),\n shouldCache: defaultShouldCache,\n createKey: defaultCreateKey,\n ...options,\n };\n\n cache.clear = () =>\n Promise.resolve(cache.store).then((store) => store?.flushAll());\n\n // If we REALLY don't want any cache (false + undef|falsy, or any + false)\n if (noCache) {\n cache.shouldCache = () => false;\n }\n\n return cache;\n};\n\nfunction create(defaults = {}) {\n const ongoing = {};\n const ref = {};\n const extraMethods = {\n text: () => ref.res.text(),\n json: () => ref.res.json(),\n blob: () => ref.res.blob(),\n stream: () => ref.res.body,\n arrayBuffer: () => ref.res.arrayBuffer(),\n formData: () => ref.res.formData(),\n body: () => getBody(ref.res),\n clone: () => ref.res.clone(),\n raw: () => ref.res.clone(),\n response: () => parseResponse(ref.res.clone()),\n };\n\n const fch = swear(async (url = \"/\", options = {}) => {\n // Exctract the options\n let {\n output,\n\n // Interceptors can also be passed as parameters\n before,\n after,\n error,\n\n cache: _lostCache,\n\n ...request\n } = { ...fch, ...options }; // Local option OR global value (including defaults)\n\n const cache = { ...fch.cache };\n const isValid = (v) => [\"number\", \"string\", \"boolean\"].includes(typeof v);\n cache.expire = parse(\n [options.cache?.expire, options.cache, cache?.expire, cache].find(isValid)\n );\n\n // Absolute URL if possible; Default method; merge the default headers\n request.url = createUrl(\n url,\n { ...fch.query, ...options.query },\n request.baseUrl ?? request.baseURL\n );\n request.method = request.method.toLowerCase() || \"GET\";\n request.headers = createHeaders({ ...fch.headers, ...options.headers });\n\n // Has the event or form, transform it to a FormData\n if (\n typeof SubmitEvent !== \"undefined\" &&\n request.body instanceof SubmitEvent\n ) {\n request.body = new FormData(request.body.target);\n }\n if (\n typeof HTMLFormElement !== \"undefined\" &&\n request.body instanceof HTMLFormElement\n ) {\n request.body = new FormData(request.body);\n }\n\n // JSON-encode plain objects\n if (hasObjectBody(request.body)) {\n request.body = JSON.stringify(noUndefined(request.body));\n // Note: already defaults to utf-8\n request.headers[\"content-type\"] = \"application/json\";\n }\n\n // Hijack the requeset and modify it\n request = before(request);\n\n if (cache.shouldCache(request) && cache.expire) {\n const key = cache.createKey(request);\n\n // Allow to receive async cache stores\n if (cache.store?.then) {\n const out = await cache.store;\n cache.store = out;\n }\n\n // Already cached, return the previous request\n if (await cache.store.exists(key)) {\n return cache.store.get(key);\n }\n\n // Ongoing, return the instance\n if (ongoing[key]) return ongoing[key];\n\n let res;\n try {\n // Otherwise generate a request, save it, and return it\n ongoing[key] = createFetch(request, {\n ref,\n cache,\n output,\n error,\n after,\n });\n res = await ongoing[key];\n } finally {\n delete ongoing[key];\n }\n // Note: failing the request will throw and thus never cache\n await cache.store.set(key, res, { EX: cache.expire });\n return res;\n }\n\n // PUT, POST, etc should never dedupe and just return the plain request\n return createFetch(request, { ref, output, error, after });\n }, extraMethods);\n\n // Default values\n fch.url = defaults.url ?? \"/\";\n fch.method = defaults.method ?? \"get\";\n fch.query = defaults.query ?? {};\n fch.headers = defaults.headers ?? {};\n fch.baseUrl = defaults.baseUrl ?? defaults.baseURL ?? null;\n\n // Accept a simple \"false\"ache = { expire: parse(defaults.cache) };\n if ([\"number\", \"string\", \"boolean\"].includes(typeof defaults.cache)) {\n defaults.cache = { expire: defaults.cache };\n }\n fch.cache = createCache(\n defaults.cache,\n defaults.cache?.expire === false || defaults.cache?.expire === 0\n );\n\n // Default options\n fch.output = defaults.output ?? \"body\";\n fch.credentials = defaults.credentials ?? \"include\";\n\n // Interceptors\n fch.before = defaults.before ?? ((req) => req);\n fch.after = defaults.after ?? ((res) => res);\n fch.error = defaults.error ?? ((err) => Promise.reject(err));\n\n fch.get = (url, opts) => fch(url, { method: \"get\", ...opts });\n fch.head = (url, opts) => fch(url, { method: \"head\", ...opts });\n fch.post = (url, body, opts) => fch(url, { method: \"post\", body, ...opts });\n fch.patch = (url, body, opts) => fch(url, { method: \"patch\", body, ...opts });\n fch.put = (url, body, opts) => fch(url, { method: \"put\", body, ...opts });\n fch.delete = (url, opts) => fch(url, { method: \"delete\", ...opts });\n fch.del = fch.delete;\n\n fch.create = create;\n\n return fch;\n}\n\nif (typeof window !== \"undefined\") {\n window.fch = create();\n}\n\nexport { create };\nexport default create();\n"],
5
- "mappings": "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",
6
- "names": ["t", "r", "n", "e", "a", "i", "o", "c", "y", "s", "createCache", "options", "cache", "exists", "key", "time", "expire", "data", "opts", "times", "parse", "str", "_", "value", "units", "result", "hasObjectBody", "body", "noUndefined", "obj", "key", "ResponseError", "response", "message", "createUrl", "url", "query", "base", "path", "urlQuery", "entries", "createHeaders", "raw", "headers", "getBody", "res", "type", "isJson", "text", "parseResponse", "createFetch", "request", "ref", "after", "error", "output", "defaultShouldCache", "defaultCreateKey", "createCache", "store", "options", "noCache", "cache", "c", "create", "defaults", "ongoing", "fch", "before", "_lostCache", "isValid", "v", "out", "req", "err", "opts", "src_default", "create"]
7
- }