fch 5.1.5 → 6.0.0
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 +71 -137
- package/index.min.js +1 -2
- package/package.json +13 -21
- package/readme.md +69 -73
- package/index.min.js.map +0 -7
package/index.d.ts
CHANGED
|
@@ -1,142 +1,76 @@
|
|
|
1
1
|
type Store = {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
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
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
type
|
|
22
|
-
type
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
8
|
+
type Cache = boolean | number | string | Store | {
|
|
9
|
+
expire?: number | string;
|
|
10
|
+
store?: Store;
|
|
11
|
+
shouldCache?: (request: any) => boolean;
|
|
12
|
+
createKey?: (request: any) => string;
|
|
13
|
+
};
|
|
14
|
+
type Headers = {
|
|
15
|
+
[name: string]: string;
|
|
16
|
+
};
|
|
17
|
+
type Query = {
|
|
18
|
+
[name: string]: string;
|
|
19
|
+
};
|
|
20
|
+
type Methods = "get" | "head" | "post" | "patch" | "put" | "delete" | "GET" | "HEAD" | "POST" | "PATCH" | "PUT" | "DELETE";
|
|
21
|
+
type Body = string | any[] | {
|
|
22
|
+
[key: string]: any;
|
|
23
|
+
} | FormData | HTMLFormElement | SubmitEvent | ReadableStream;
|
|
26
24
|
type Options = {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
25
|
+
url?: string;
|
|
26
|
+
method?: Methods;
|
|
27
|
+
query?: Query;
|
|
28
|
+
headers?: Headers;
|
|
29
|
+
baseUrl?: string;
|
|
30
|
+
baseURL?: string;
|
|
31
|
+
cache?: Cache;
|
|
32
|
+
output?: string;
|
|
33
|
+
credentials?: string;
|
|
34
|
+
before?: (req: any) => any;
|
|
35
|
+
after?: (res: any) => any;
|
|
36
|
+
error?: (error: Error) => any;
|
|
37
|
+
signal?: AbortSignal;
|
|
38
|
+
[key: string]: any;
|
|
41
39
|
};
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
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>;
|
|
40
|
+
interface FchInstance {
|
|
41
|
+
(url?: string, options?: Options): Promise<any>;
|
|
42
|
+
create: (options?: Options) => FchInstance;
|
|
43
|
+
get: (url: string, options?: Options) => Promise<any>;
|
|
44
|
+
head: (url: string, options?: Options) => Promise<any>;
|
|
45
|
+
post: (url: string, body?: Body, options?: Options) => Promise<any>;
|
|
46
|
+
patch: (url: string, body?: Body, options?: Options) => Promise<any>;
|
|
47
|
+
put: (url: string, body?: Body, options?: Options) => Promise<any>;
|
|
48
|
+
delete: (url: string, options?: Options) => Promise<any>;
|
|
49
|
+
del: (url: string, options?: Options) => Promise<any>;
|
|
50
|
+
text: () => Promise<string>;
|
|
51
|
+
json: () => Promise<any>;
|
|
52
|
+
blob: () => Promise<Blob>;
|
|
53
|
+
stream: () => ReadableStream | null;
|
|
54
|
+
arrayBuffer: () => Promise<ArrayBuffer>;
|
|
55
|
+
formData: () => Promise<FormData>;
|
|
56
|
+
body: () => Promise<any>;
|
|
57
|
+
clone: () => Response;
|
|
58
|
+
raw: () => Response;
|
|
59
|
+
response: () => Promise<any>;
|
|
60
|
+
url: string;
|
|
61
|
+
method: Methods;
|
|
62
|
+
query: Query;
|
|
63
|
+
headers: Headers;
|
|
64
|
+
baseUrl: string | null;
|
|
65
|
+
baseURL: string | null;
|
|
66
|
+
cache: any;
|
|
67
|
+
output: string;
|
|
68
|
+
credentials: string;
|
|
69
|
+
before?: (req: any) => any;
|
|
70
|
+
after?: (res: any) => any;
|
|
71
|
+
error?: (error: Error) => any;
|
|
140
72
|
}
|
|
141
|
-
|
|
142
|
-
export
|
|
73
|
+
declare function create(defaults?: Options): FchInstance;
|
|
74
|
+
export { create };
|
|
75
|
+
declare const _default: FchInstance;
|
|
76
|
+
export default _default;
|
package/index.min.js
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
|
-
var
|
|
2
|
-
//# sourceMappingURL=index.min.js.map
|
|
1
|
+
var z=async(i)=>(i=await i,Array.isArray(i)?await Promise.all(i.map(z)):i),Y=(i,n)=>(...x)=>((w)=>w instanceof RegExp?w.test.bind(w):w)(i).call(n,...x),T=(i,n)=>async(x,w,m)=>({value:x,extra:await Y(i,n)(x,w,m)}),D=({extra:i})=>i,K=({value:i})=>i,Q={every:async(i,n,x)=>{for(let w=0;w<i.length;w++)if(!await Y(n,x)(i[w],w,i))return!1;return!0},filter:async(i,n,x)=>(await z(i.map(T(n,x)))).filter(D).map(K),find:async(i,n,x)=>{for(let w=0;w<i.length;w++)if(await Y(n,x)(i[w],w,i))return i[w]},findIndex:async(i,n,x)=>{for(let w=0;w<i.length;w++)if(await Y(n,x)(i[w],w,i))return w;return-1},forEach:async(i,n,x)=>(await z(i.map(T(n,x))),i),reduce:async(i,n,x)=>{let w=x!==void 0;w||(x=i[0]);for(let m=w?0:1;m<i.length;m++)x=await Y(n)(x,i[m],m,i);return x},reduceRight:async(i,n,x)=>{let w=x!==void 0;w||(x=i[i.length-1]);for(let m=i.length-(w?1:2);m>=0;m--)x=await Y(n)(x,i[m],m,i);return x},some:async(i,n,x)=>{for(let w=0;w<i.length;w++)if(await Y(n,x)(i[w],w,i))return!0;return!1}},V=(i,n)=>(x,w)=>w==="then"?(...m)=>z(i).then(...m):w==="catch"?(...m)=>G(z(i).catch(...m)):E(z(i).then((m)=>typeof w=="symbol"?m[w]:(w in n)?E((...P)=>n[w](m,...P),n):typeof m=="number"&&(w in n.number)?E((...P)=>n.number[w](m,...P),n):typeof m=="string"&&(w in n.string)?E((...P)=>n.string[w](m,...P),n):Array.isArray(m)&&(w in n.array)?E((...P)=>n.array[w](m,...P),n):m[w]&&m[w].bind?E(m[w].bind(m),n):E(m[w],n)),n),F=(i,n)=>(x,w,m)=>E(z(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}),n),E=(i,n)=>new Proxy(()=>{},{get:V(i,n),apply:F(i,n)});function G(i,{number:n,string:x,array:w,...m}={}){return typeof i=="function"?(...P)=>G(Promise.all(P).then((g)=>i(...g)),{number:n,string:x,array:w,...m}):new Proxy({},{get:V(i,{number:{...n},string:{...x},array:{...Q,...w},...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)},J=(i)=>{if(typeof i!=="object")return i;for(let n in i)if(i[n]===void 0)delete i[n];return i};class X extends Error{response;constructor(i){let n="Error "+i.status;super(n);this.response=i,this.message=n}}var R=(i,n,x)=>{let[w,m=""]=i.split("?"),P=new URLSearchParams(Object.fromEntries([...new URLSearchParams(J(n)),...new URLSearchParams(J(m))])).toString();if(P)w=w+"?"+P;if(!x)return w;return new URL(w.replace(/^\//,""),x).href},B=(i)=>{let n={};for(let[x,w]of Object.entries(i))n[x.toLowerCase()]=w;return n},Z=async(i)=>{let n=i.headers.get("content-type"),x=n&&n.includes("application/json"),w=await i.clone().text();return x?JSON.parse(w):w},_=async(i)=>{let n={status:i.status,statusText:i.statusText,headers:{},body:void 0};if(i.headers.forEach((x,w)=>{n.headers[w.toLowerCase()]=x}),!i.ok)throw new X(i);return n.body=await Z(i),n},W=(i,{ref:n,after:x,error:w,output:m})=>{return fetch(i.url,i).then(async(P)=>{if(n.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 _(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(w)},C=(i)=>i.method==="get",U=(i)=>i.method+":"+i.url,y=(i)=>{let n={store:i??null,shouldCache:C,createKey:U,clear:()=>Promise.resolve(n.store).then((x)=>x?.clear?x.clear():Promise.resolve())};return n};function L(i={}){let n={},x={},m=G(async(P="/",g={})=>{let{output:v,before:M,after:O,error:S,cache:j,...A}={...m,...g},N={...m.cache};if(A.url=R(P,{...m.query,...g.query},A.baseUrl??A.baseURL),A.method=A.method.toLowerCase()||"GET",A.headers=B({...m.headers,...g.headers}),typeof SubmitEvent<"u"&&A.body instanceof SubmitEvent)A.body=new FormData(A.body.target);if(typeof HTMLFormElement<"u"&&A.body instanceof HTMLFormElement)A.body=new FormData(A.body);if(H(A.body))A.body=JSON.stringify(J(A.body)),A.headers["content-type"]="application/json";if(A=M?M(A):A,N.shouldCache(A)&&N.store){let $=N.createKey(A);if(await N.store.has($))return N.store.get($);if(n[$])return n[$];let I;try{n[$]=W(A,{ref:x,cache:N,output:v,error:S,after:O}),I=await n[$]}finally{delete n[$]}return await N.store.set($,I),I}return W(A,{ref:x,output:v,error:S,after:O})},{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:()=>Z(x.res.clone()),clone:()=>x.res.clone(),raw:()=>x.res.clone(),response:()=>_(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=y(i.cache),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,v)=>m(P,{method:"post",body:g,...v}),m.patch=(P,g,v)=>m(P,{method:"patch",body:g,...v}),m.put=(P,g,v)=>m(P,{method:"put",body:g,...v}),m.delete=(P,g)=>m(P,{method:"delete",...g}),m.del=m.delete,m.create=L,m}if(typeof window<"u")window.fch=L();var b=L();export{b as default,L as create};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fch",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "6.0.0",
|
|
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": "
|
|
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": "
|
|
15
|
-
"test": "
|
|
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
|
-
"
|
|
38
|
-
"
|
|
39
|
-
"
|
|
40
|
-
"
|
|
41
|
-
"
|
|
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
|
@@ -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) | `
|
|
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 =
|
|
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
|
|
130
|
-
api({ method
|
|
129
|
+
api({ method: 'GET' })
|
|
130
|
+
api({ method: 'get'})
|
|
131
131
|
```
|
|
132
132
|
|
|
133
133
|
Example: adding a new cat and fixing a typo:
|
|
@@ -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
|
|
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";
|
|
@@ -326,21 +326,16 @@ 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.
|
|
330
|
-
|
|
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.
|
|
329
|
+
The cache (disabled by default) is a great method to reduce the number of API requests we make. We use [polystore](https://polystore.dev/) for cache storage, which provides a unified interface for multiple storage backends.
|
|
335
330
|
|
|
336
331
|
> Note: cache should only be used through `fch.create({ cache: ... })`, not through the global instance.
|
|
337
332
|
|
|
338
|
-
To activate the cache,
|
|
333
|
+
To activate the cache, you can pass a time string or number (seconds), and an in-memory store will be created automatically:
|
|
339
334
|
|
|
340
335
|
```js
|
|
341
|
-
// This API has 1h by default:
|
|
336
|
+
// This API has 1h cache by default (uses in-memory Map):
|
|
342
337
|
const api = fch.create({
|
|
343
|
-
baseUrl: 'https://api.myweb.com/'
|
|
338
|
+
baseUrl: 'https://api.myweb.com/',
|
|
344
339
|
cache: '1h'
|
|
345
340
|
});
|
|
346
341
|
|
|
@@ -348,56 +343,75 @@ const api = fch.create({
|
|
|
348
343
|
api.get('/somedata', { cache: '20s' });
|
|
349
344
|
```
|
|
350
345
|
|
|
351
|
-
|
|
346
|
+
For more control, you can use **polystore** to create a custom cache store with different backends (in-memory, Redis, localStorage, etc.):
|
|
352
347
|
|
|
353
348
|
```js
|
|
354
349
|
import fch from "fch";
|
|
350
|
+
import kv from "polystore";
|
|
351
|
+
|
|
352
|
+
// In-memory cache with 1 hour expiration
|
|
353
|
+
const cache = kv(new Map()).expires("1h");
|
|
354
|
+
|
|
355
|
+
const api = fch.create({
|
|
356
|
+
baseUrl: 'https://api.myweb.com/',
|
|
357
|
+
cache: cache
|
|
358
|
+
});
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
Polystore supports multiple backends. For example, with Redis:
|
|
362
|
+
|
|
363
|
+
```js
|
|
364
|
+
import fch from "fch";
|
|
365
|
+
import kv from "polystore";
|
|
355
366
|
import { createClient } from "redis";
|
|
356
367
|
|
|
357
|
-
//
|
|
358
|
-
|
|
359
|
-
const
|
|
368
|
+
// Redis cache with 1 hour expiration
|
|
369
|
+
const redis = await createClient().connect();
|
|
370
|
+
const cache = kv(redis).expires("1h");
|
|
360
371
|
|
|
361
372
|
const api = fch.create({
|
|
362
|
-
cache:
|
|
363
|
-
store: store,
|
|
364
|
-
expire: "1h",
|
|
365
|
-
},
|
|
373
|
+
cache: cache
|
|
366
374
|
});
|
|
367
375
|
```
|
|
368
376
|
|
|
369
377
|
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
378
|
|
|
371
379
|
```js
|
|
372
|
-
|
|
380
|
+
import kv from "polystore";
|
|
381
|
+
|
|
382
|
+
const cache = kv(new Map()).expires("1h");
|
|
383
|
+
const api = fch.create({ cache });
|
|
373
384
|
|
|
374
385
|
// Remove them all
|
|
375
|
-
await
|
|
386
|
+
await cache.clear();
|
|
376
387
|
```
|
|
377
388
|
|
|
378
|
-
You can
|
|
389
|
+
You can also access the underlying store directly through the polystore instance to perform low-level operations:
|
|
379
390
|
|
|
380
391
|
```js
|
|
381
392
|
import fch from "fch";
|
|
393
|
+
import kv from "polystore";
|
|
382
394
|
import { createClient } from "redis";
|
|
383
395
|
|
|
384
|
-
|
|
385
|
-
const
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
expire: "1h",
|
|
389
|
-
},
|
|
390
|
-
});
|
|
396
|
+
const redis = await createClient().connect();
|
|
397
|
+
const cache = kv(redis).expires("1h");
|
|
398
|
+
|
|
399
|
+
const api = fch.create({ cache });
|
|
391
400
|
|
|
392
|
-
// Later on,
|
|
393
|
-
await
|
|
401
|
+
// Later on, you can access the underlying Redis client
|
|
402
|
+
await redis.flushDB();
|
|
394
403
|
```
|
|
395
404
|
|
|
396
|
-
|
|
405
|
+
For advanced cache configuration, you can pass an object with additional options like `shouldCache` and `createKey`:
|
|
397
406
|
|
|
398
407
|
```js
|
|
408
|
+
import kv from "polystore";
|
|
409
|
+
|
|
410
|
+
const cache = kv(new Map()).expires("1h");
|
|
411
|
+
|
|
399
412
|
const api = fch.create({
|
|
400
413
|
cache: {
|
|
414
|
+
store: cache,
|
|
401
415
|
// Default shouldCache; Note the lowercase
|
|
402
416
|
shouldCache: (request) => request.method === "get",
|
|
403
417
|
|
|
@@ -410,26 +424,34 @@ const api = fch.create({
|
|
|
410
424
|
For example, if you want to differentiate the auth requests from the non-auth requests, you can do it so:
|
|
411
425
|
|
|
412
426
|
```js
|
|
413
|
-
import
|
|
427
|
+
import kv from "polystore";
|
|
414
428
|
|
|
415
|
-
const
|
|
416
|
-
// ... Do some other stuff
|
|
429
|
+
const cache = kv(new Map()).expires("1h");
|
|
417
430
|
|
|
418
|
-
|
|
419
|
-
|
|
431
|
+
const api = fch.create({
|
|
432
|
+
cache: {
|
|
433
|
+
store: cache,
|
|
434
|
+
// Create a key unique for each user
|
|
435
|
+
createKey: (req) => user.id + ":" + req.method + ":" + req.url,
|
|
436
|
+
}
|
|
437
|
+
});
|
|
420
438
|
|
|
421
|
-
|
|
422
|
-
|
|
439
|
+
const onLogin = (user) => {
|
|
440
|
+
// Remove the old requests since we were not auth'ed yet
|
|
441
|
+
cache.clear();
|
|
423
442
|
};
|
|
424
443
|
```
|
|
425
444
|
|
|
426
445
|
Or maybe you just want to NOT cache any of the requests that have an `Authorization` header, you can do so:
|
|
427
446
|
|
|
428
447
|
```js
|
|
448
|
+
import kv from "polystore";
|
|
449
|
+
|
|
450
|
+
const cache = kv(new Map()).expires("1week");
|
|
451
|
+
|
|
429
452
|
const api = fch.create({
|
|
430
453
|
cache: {
|
|
431
|
-
|
|
432
|
-
|
|
454
|
+
store: cache,
|
|
433
455
|
// Note the lowercase in both! we normalize them to be lowercase
|
|
434
456
|
shouldCache: (req) => req.method === "get" && !req.headers.authorization,
|
|
435
457
|
},
|
|
@@ -438,19 +460,9 @@ const api = fch.create({
|
|
|
438
460
|
|
|
439
461
|
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.
|
|
440
462
|
|
|
441
|
-
#### Creating a store
|
|
463
|
+
#### Creating a custom store
|
|
442
464
|
|
|
443
|
-
You
|
|
444
|
-
|
|
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
|
-
```
|
|
465
|
+
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
466
|
|
|
455
467
|
### Interceptors
|
|
456
468
|
|
|
@@ -460,8 +472,6 @@ You can also add the interceptors `before`, `after` and `error`:
|
|
|
460
472
|
- `after`: Called just after the response is created and if there was no error, but before parsing anything else.
|
|
461
473
|
- `error`: When the response is not okay, if possible it'll include the `response` object.
|
|
462
474
|
|
|
463
|
-
> Note: interceptors are never deduped/cached and always execute once per call, even if the main async fetch() has been deduped.
|
|
464
|
-
|
|
465
475
|
```js
|
|
466
476
|
// Perform an action or request transformation before the request is sent
|
|
467
477
|
fch.before = async req => {
|
|
@@ -666,7 +676,7 @@ You can also [create an instance](#create-an-instance) that will have the same o
|
|
|
666
676
|
|
|
667
677
|
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
678
|
|
|
669
|
-
In the library itself there's nothing different between the browser and Node.js, but it might be interesting to note that
|
|
679
|
+
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
680
|
|
|
671
681
|
### Differences with Axios
|
|
672
682
|
|
|
@@ -692,17 +702,3 @@ As disadvantages, I can think of two major ones for `fch`:
|
|
|
692
702
|
|
|
693
703
|
- Requires Node.js 18+, which is the version that includes `fetch()` by default.
|
|
694
704
|
- 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
|
-
}
|