fetchbasequery 0.1.2 → 0.2.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/README.md +10 -2
- package/package.json +1 -1
- package/src/baseQuery.js +15 -1
- package/src/fetchBaseQuery.js +2 -1
- package/src/helpers/abortable.js +13 -0
- package/types/index.d.ts +29 -29
package/README.md
CHANGED
|
@@ -27,13 +27,14 @@ const query = fetchBaseQuery({
|
|
|
27
27
|
// main options ...
|
|
28
28
|
baseUrl: 'https://api.example.org/v1'
|
|
29
29
|
baseQuery,
|
|
30
|
+
timeout: 10000, // in milliseconds
|
|
30
31
|
logErrors: true,
|
|
31
32
|
// add some defaults for `fetch()` ...
|
|
32
33
|
mode: 'cors',
|
|
33
34
|
credentials: 'include',
|
|
34
35
|
cache: 'reload',
|
|
35
36
|
// middlewares
|
|
36
|
-
|
|
37
|
+
middlewares: [
|
|
37
38
|
encodeBody(),
|
|
38
39
|
accessToken({
|
|
39
40
|
getAccessToken: () => localStorage.getItem('access_token'),
|
|
@@ -50,7 +51,7 @@ const query = fetchBaseQuery({
|
|
|
50
51
|
Now get easy to make queries:
|
|
51
52
|
|
|
52
53
|
```js
|
|
53
|
-
const response = await query({ url: '/users/me' }) // don't worry about catching errors
|
|
54
|
+
const response = await query({ url: '/users/me', timeout: 3000 }) // don't worry about catching errors
|
|
54
55
|
const { status, success, error } = response
|
|
55
56
|
if (success) {
|
|
56
57
|
setUser(response.data)
|
|
@@ -71,6 +72,13 @@ addEventListener('fetch', evt => {
|
|
|
71
72
|
})
|
|
72
73
|
```
|
|
73
74
|
|
|
75
|
+
Aborting query:
|
|
76
|
+
|
|
77
|
+
```js
|
|
78
|
+
const promise = query({ url: '/users/me' })
|
|
79
|
+
promise.abort()
|
|
80
|
+
```
|
|
81
|
+
|
|
74
82
|
It works fine both on frontend and backend sides. For backend side usage Node.js v18+ is required,
|
|
75
83
|
because the middleware `baseQuery` based on `Fetch API`. But it can be replaced with your own
|
|
76
84
|
implementation based on another API (e.g. based on `axios` etc).
|
package/package.json
CHANGED
package/src/baseQuery.js
CHANGED
|
@@ -4,7 +4,7 @@ import mergeHeaders from './helpers/mergeHeaders.js'
|
|
|
4
4
|
|
|
5
5
|
const moduleName = 'fetchBaseQuery/baseQuery'
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
const baseQuery = async ({ url: endpoint, request: subject, ...options } = {}) => {
|
|
8
8
|
const {
|
|
9
9
|
baseUrl,
|
|
10
10
|
logErrors,
|
|
@@ -64,3 +64,17 @@ export default async ({ url: endpoint, request: subject, ...options } = {}) => {
|
|
|
64
64
|
}
|
|
65
65
|
return response
|
|
66
66
|
}
|
|
67
|
+
|
|
68
|
+
export default ({ timeout, signal, ...options } = {}) => {
|
|
69
|
+
// construct abort signal
|
|
70
|
+
const abortController = new AbortController()
|
|
71
|
+
const abortSignal = AbortSignal.any([
|
|
72
|
+
abortController.signal,
|
|
73
|
+
...(timeout ? [ AbortSignal.timeout(timeout) ] : []),
|
|
74
|
+
...(signal ? [ signal ] : [])
|
|
75
|
+
])
|
|
76
|
+
// construct abortable promise
|
|
77
|
+
const promise = baseQuery({ ...options, signal: abortSignal })
|
|
78
|
+
promise.abort = () => abortController.abort()
|
|
79
|
+
return promise
|
|
80
|
+
}
|
package/src/fetchBaseQuery.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
// const pipeAsync = (...fns) => (input) => fns.reduce((chain, func) => chain.then(func), Promise.resolve(input))
|
|
2
|
+
import abortable from './helpers/abortable.js'
|
|
2
3
|
import pipe from './helpers/pipe.js'
|
|
3
4
|
import defaultBaseQuery from './baseQuery.js'
|
|
4
5
|
|
|
5
6
|
export default ({ baseQuery, middlewares, ...defaultOptions } = {}) => {
|
|
6
|
-
const pipedQuery = pipe(...(middlewares || []))(baseQuery || defaultBaseQuery)
|
|
7
|
+
const pipedQuery = pipe(...(middlewares || []).map(abortable))(baseQuery || defaultBaseQuery)
|
|
7
8
|
return options => pipedQuery({
|
|
8
9
|
...defaultOptions,
|
|
9
10
|
...options
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export default middleware => query => ({ signal, ...options } = {}) => {
|
|
2
|
+
const abortController = new AbortController()
|
|
3
|
+
const abortableQuery = (options) => query({
|
|
4
|
+
...options,
|
|
5
|
+
signal: AbortSignal.any([
|
|
6
|
+
abortController.signal,
|
|
7
|
+
...(signal ? [ signal ] : [])
|
|
8
|
+
])
|
|
9
|
+
})
|
|
10
|
+
const promise = middleware(abortableQuery)(options)
|
|
11
|
+
promise.abort = () => abortController.abort()
|
|
12
|
+
return promise
|
|
13
|
+
}
|
package/types/index.d.ts
CHANGED
|
@@ -1,18 +1,19 @@
|
|
|
1
1
|
export type DebuggingFlags = {
|
|
2
|
-
baseQuery
|
|
3
|
-
encodeBody
|
|
4
|
-
accessToken
|
|
5
|
-
jsonReply
|
|
6
|
-
commonReply
|
|
2
|
+
baseQuery?: boolean,
|
|
3
|
+
encodeBody?: boolean,
|
|
4
|
+
accessToken?: boolean,
|
|
5
|
+
jsonReply?: boolean,
|
|
6
|
+
commonReply?: boolean
|
|
7
7
|
};
|
|
8
8
|
|
|
9
9
|
export type FetchOptions = {
|
|
10
|
-
logErrors
|
|
11
|
-
url
|
|
12
|
-
request
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
10
|
+
logErrors?: boolean,
|
|
11
|
+
url?: URL | string,
|
|
12
|
+
request?: Request,
|
|
13
|
+
timeout?: number,
|
|
14
|
+
method?: string,
|
|
15
|
+
headers?: Headers | object,
|
|
16
|
+
body?: string
|
|
16
17
|
| object
|
|
17
18
|
| FormData
|
|
18
19
|
| Blob
|
|
@@ -28,28 +29,27 @@ export type FetchOptions = {
|
|
|
28
29
|
| Uint32Array
|
|
29
30
|
| BigInt64Array
|
|
30
31
|
| BigUint64Array
|
|
31
|
-
| URLSearchParams
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
debug: DebuggingFlags | undefined
|
|
32
|
+
| URLSearchParams,
|
|
33
|
+
mode?: string,
|
|
34
|
+
credentials?: string,
|
|
35
|
+
cache?: string,
|
|
36
|
+
redirect?: string,
|
|
37
|
+
referrer?: string,
|
|
38
|
+
referrerPolicy?: string,
|
|
39
|
+
integrity?: string,
|
|
40
|
+
keepalive?: boolean,
|
|
41
|
+
signal?: AbortSignal,
|
|
42
|
+
debug?: DebuggingFlags
|
|
43
43
|
};
|
|
44
44
|
|
|
45
|
-
export type baseQueryFn = (options
|
|
46
|
-
export type queryFn = (options
|
|
45
|
+
export type baseQueryFn = (options?: FetchOptions) => Promise<Response>;
|
|
46
|
+
export type queryFn = (options?: FetchOptions) => Promise<any>;
|
|
47
47
|
export type middlewareFn = (settings: any) => (query: queryFn) => queryFn;
|
|
48
48
|
|
|
49
49
|
export type FetchBaseQueryOptions = {
|
|
50
|
-
baseUrl
|
|
51
|
-
baseQuery
|
|
52
|
-
middlewares
|
|
50
|
+
baseUrl?: URL | string,
|
|
51
|
+
baseQuery?: baseQueryFn,
|
|
52
|
+
middlewares?: Array<middlewareFn>
|
|
53
53
|
};
|
|
54
54
|
|
|
55
55
|
export const baseQuery: baseQueryFn;
|
|
@@ -59,6 +59,6 @@ export const accessToken: middlewareFn;
|
|
|
59
59
|
export const jsonReply: middlewareFn;
|
|
60
60
|
export const commonReply: middlewareFn;
|
|
61
61
|
|
|
62
|
-
|
|
62
|
+
declare function fetchBaseQuery(options?: FetchBaseQueryOptions & FetchOptions): queryFn;
|
|
63
63
|
|
|
64
64
|
export default fetchBaseQuery;
|