fetchbasequery 0.2.1 → 1.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/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2025 h41ku
3
+ Copyright (c) 2026 h41ku
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/README.md CHANGED
@@ -1,6 +1,13 @@
1
1
  # fetchBaseQuery
2
2
 
3
3
  Library for easily make HTTP queries without mass of boilerplate code.
4
+ It works fine in any environment that supports `Fetch API`.
5
+
6
+ ## Features
7
+
8
+ - Lightweight modular typescript ready code
9
+ - Supports middleware programming pattern
10
+ - Using only modern API, has no any legacy code
4
11
 
5
12
  ## Installation
6
13
 
@@ -18,70 +25,289 @@ pnpm add fetchbasequery
18
25
 
19
26
  ## Usage
20
27
 
21
- Build base query function:
28
+ ### Basic usage
29
+
30
+ Use a factory function, which enhance a bare `fetch()`:
22
31
 
23
32
  ```js
24
- import fetchBaseQuery, { baseQuery, encodeBody, accessToken, jsonReply, commonReply } from 'fetchbasequery'
33
+ import fetchBaseQuery from 'fetchbasequery'
25
34
 
26
35
  const query = fetchBaseQuery({
27
36
  // main options ...
28
- baseUrl: 'https://api.example.org/v1'
29
- baseQuery,
37
+ baseUrl: 'https://api.example.org/v1',
30
38
  timeout: 10000, // in milliseconds
31
- logErrors: true,
39
+ fetch: globalThis.fetch, // it is possible to use a custom `fetch()` here
32
40
  // add some defaults for `fetch()` ...
33
41
  mode: 'cors',
34
42
  credentials: 'include',
35
43
  cache: 'reload',
36
- // middlewares
37
- middlewares: [
38
- encodeBody(),
39
- accessToken({
40
- getAccessToken: () => localStorage.getItem('access_token'),
41
- setAccessToken: (token) => localStorage.setItem('access_token', token),
42
- removeAccessToken: (token) => localStorage.removeItem('access_token'),
43
- getUpdatedAccessToken: async (response) => response.headers.get('X-Access-Token')
44
+ // ... see `RequestInit` for more options ...
45
+ })
46
+ ```
47
+
48
+ Then use the returned function instead of bare `fetch()`:
49
+
50
+ ```js
51
+ const resource = `/users/${id}` // full or short URL
52
+ const options = { // define some options, see `RequestInit`
53
+ headers: { 'Authorization': '...' }
54
+ }
55
+ const response = await query(resource, options) // all options defined in `fetchBaseQuery()` will be passed into request
56
+ ```
57
+
58
+ Function returns an abortable promise described using type `AbortablePromise<T>`.
59
+ So it is possible to abort the request at any time.
60
+
61
+ ```js
62
+ const promise = query(...)
63
+ // ...
64
+ promise.abort('Component was unmounted...') // `reason` message is optional
65
+ ```
66
+
67
+ Options of factory function described by type `FetchBaseQueryOptions`:
68
+
69
+ ```ts
70
+ export type FetchBaseQueryOptions = RequestInit & {
71
+ baseUrl?: string, // origin or prefix, used for URLs without it
72
+ timeout?: number, // default timeout in milliseconds
73
+ fetch?: BaseFetchFunction, // by default this is reference to `globalThis.fetch()`
74
+ middlewares?: Middleware[] // list of middleware functions
75
+ };
76
+ ```
77
+
78
+ ### Using middlewares
79
+
80
+ ```js
81
+ import fetchBaseQuery from 'fetchbasequery'
82
+ import { retryOnError } from 'fetchbasequery/middlewares'
83
+
84
+ const query = fetchBaseQuery({
85
+ // ... options ...
86
+ middlewares: [ // add some middlewares
87
+ retryOnError({
88
+ maxNumAttempts: 5
44
89
  }),
45
- jsonReply(),
46
- commonReply()
90
+ // ...
47
91
  ]
48
92
  })
49
93
  ```
50
94
 
51
- Now get easy to make queries:
95
+ ### Using decorators
52
96
 
53
97
  ```js
54
- const response = await query({ url: '/users/me', timeout: 3000 }) // don't worry about catching errors
55
- const { status, success, error } = response
56
- if (success) {
57
- setUser(response.data)
58
- } else if (error) {
59
- setError(response.message)
60
- } else {
61
- setError(`Unexpected status code: ${status}`)
98
+ import fetchBaseQuery from 'fetchbasequery'
99
+ import { json } from 'fetchbasequery/decorators'
100
+
101
+ const query = json(fetchBaseQuery({
102
+ // ... options ...
103
+ }))
104
+
105
+ // Now `query()` accepts plain object as body and stringify it automatically.
106
+ // Also response has a `data` property, which contains parsed json returned by backend.
107
+ const { data } = await query('/articles', {
108
+ method: 'post',
109
+ body: {
110
+ title: '...',
111
+ poster: '...',
112
+ // ...
113
+ }
114
+ })
115
+ ```
116
+
117
+ ### Writing a custom middleware
118
+
119
+ Middleware described by type `Middleware`:
120
+
121
+ ```ts
122
+ export type Middleware = (request: Request, next: (request: Request) => Promise<Response>) => Promise<Response>;
123
+ ```
124
+
125
+ Every middleware follows the simple pattern. Get `request`, do something with request,
126
+ then call `next(request)` to get `response`, do something with response and return it.
127
+
128
+ Let's create simple middleware for example:
129
+
130
+ ```js
131
+ // Add to the request a CSRF-token as a custom header `X-CSRF-Token`
132
+ async function useCsrfToken(request, next) {
133
+ const token = await getCsrfToken() // an abstract function just for example
134
+ // modify the request
135
+ const headers = new Headers(request.headers)
136
+ headers.set('X-CSRF-Token', token)
137
+ const modifiedRequest = new Request(request, { headers })
138
+ // make a query using the modified request
139
+ const response = await next(modifiedRequest)
140
+ // it is possible to modify response too, but in this example we does not need it
141
+ return response // just return the response as is
62
142
  }
63
143
  ```
64
144
 
65
- Using instance of `Request`:
145
+ Usage:
66
146
 
67
147
  ```js
68
- // for example inside ServiceWorker
69
- addEventListener('fetch', evt => {
70
- const { request } = evt
71
- return evt.respondWith(query({ request }))
148
+ const query = fetchBaseQuery({
149
+ baseUrl: 'https://...', // an abstract
150
+ // ...
151
+ middlewares: [
152
+ // ...
153
+ useCsrfToken,
154
+ // ...
155
+ ]
156
+ })
157
+ // ...
158
+ const formData = getFormData() // an abstract
159
+ // post the form to the protected route
160
+ const response = await query('/articles', {
161
+ method: 'post',
162
+ body: formData
72
163
  })
73
164
  ```
74
165
 
75
- Aborting query:
166
+ ### Writing a custom decorators
76
167
 
77
- ```js
78
- const promise = query({ url: '/users/me' })
79
- promise.abort()
168
+ Decorators can extends logic and redefine types of request and response.
169
+
170
+ There are no restrictions for a decorator. It just a get original function and
171
+ return it's enhanced version. That's all.
172
+
173
+ Let's create a simple example:
174
+
175
+ ```ts
176
+ import type { FetchFunction, AbortablePromise } from 'fetchbasequery';
177
+ import fetchBaseQuery from 'fetchbasequery';
178
+
179
+ export type XmlResponse = Response & { document?: XMLDocument };
180
+
181
+ // Parses automatically XML documents provided by a raw response
182
+ export function withXmlParser(query: FetchFunction<Response>) {
183
+ const supportedTypes = [
184
+ 'application/xml',
185
+ 'text/xml',
186
+ ]
187
+ return function (
188
+ resource: string | Request,
189
+ { signal: initSignal, ...options }: RequestInit = {}
190
+ ): AbortablePromise<XmlResponse> {
191
+ const abortController = new AbortController()
192
+ const signal = AbortSignal.any([
193
+ abortController.signal,
194
+ ...(initSignal instanceof AbortSignal ? [ initSignal ] : [])
195
+ ])
196
+ const promise = (async () => {
197
+ const response = (await query(resource, { signal, ...options })) as XmlResponse
198
+ const contentType = String(response.headers.get('content-type')).split(';')[0]
199
+ if (supportedTypes.includes(contentType)) { // if the response contains XML document
200
+ // then parse content into special property `.document`
201
+ const parser = new DOMParser()
202
+ response.document = parser.parseFromString(await response.text(), 'application/xml')
203
+ }
204
+ return response
205
+ })() as AbortablePromise<XmlResponse>;
206
+ promise.abort = (reason) => { abortController.abort(reason) }
207
+ return promise
208
+ }
209
+ }
210
+ ```
211
+
212
+ Usage:
213
+
214
+ ```ts
215
+ const query = withXmlParser(fetchBaseQuery({
216
+ baseUrl: 'https://...', // an abstract
217
+ // ...
218
+ }))
219
+ const response = await query('/sitemap.xml')
220
+ console.log('Status:', response.status)
221
+ console.log('Content-Type:', response.headers.get('content-type'))
222
+ console.log('Document:', response.document)
223
+ ```
224
+
225
+ ## List of provided middlewares
226
+
227
+ ### `muteErrors()`
228
+
229
+ Catch any error thrown by `next()` mute it and returns `Response.error()`.
230
+ Typically usage: use conditional statements instead of using `try-catch` statements.
231
+
232
+ ### `retryOnError(options?: RetryOnErrorOptions)`
233
+
234
+ Retry to make a query when an error was thrown by `next()`.
235
+ Typically usage: repeat the request in case of a temporary loss of connection.
236
+
237
+ Options:
238
+
239
+ ```ts
240
+ export type RetryOnErrorOptions = {
241
+ maxNumAttempts?: number = 5, // the maximum number of attempts
242
+ backoffTime?: (attempt: number) => number, // delay time in milliseconds
243
+ };
80
244
  ```
81
245
 
82
- It works fine both on frontend and backend sides. For backend side usage Node.js v18+ is required,
83
- because the middleware `baseQuery` based on `Fetch API`. But it can be replaced with your own
84
- implementation based on another API (e.g. based on `axios` etc).
246
+ ### `retryOn429(options?: RetryOn429Options)`
247
+
248
+ Retry to make a query when server returns status `429 Too Many Requests`.
249
+ Typically usage: repeat the request in case when servers busy or when rate limit was reached.
250
+
251
+ Options:
252
+
253
+ ```ts
254
+ export type RetryOn429Options = {
255
+ maxNumAttempts?: number = 5, // the maximum number of attempts
256
+ maxBackoffTime?: number = Infinity, // the maximum permissible delay time
257
+ backoffTime?: (attempt: number, response: Response) => number, // delay time in milliseconds
258
+ };
259
+ ```
260
+
261
+ ## List of provided decorators
262
+
263
+ ### `json<T>(query: FetchFunction<Response>): JsonFetchFunction<JsonResponse<T>>`
264
+
265
+ Allows to pass a plain objects as `body` and automatically serialize plain objects into JSON.
266
+ It also automatically parse JSON documents provided by a raw response into special property `.data`.
267
+
268
+ Usage:
269
+ ```ts
270
+ import fetchBaseQuery from 'fetchbasequery'
271
+ import { json } from 'fetchbasequery/decorators'
272
+
273
+ const query = json(fetchBaseQuery({
274
+ // ...
275
+ }))
276
+ // ...
277
+ const response = await query('https://...', {
278
+ method: 'put',
279
+ body: { // decorator allows to pass a plain objects as body
280
+ title: '...',
281
+ // ...
282
+ }
283
+ })
284
+ console.log('Status:', response.status)
285
+ console.log('Data:', response.data) // decorator also parses body returned as json
286
+ ```
287
+
288
+ ## Testing
289
+
290
+ Running tests:
291
+
292
+ ```sh
293
+ npm run test
294
+ ```
295
+
296
+ ## TODO
297
+
298
+ - Chaining methods of `AbortablePromise<T>` (`.then()`, `.catch()` and `.finally()`)
299
+ must returns instance of `AbortablePromise<T>` not pure `Promise<T>`;
300
+ - Add static methods to `AbortablePromise<T>` (`.all()`, `.any()`, `.race()`, etc);
301
+ - Describe and export utility function `sleep()` - abortable sleep function;
302
+ - Add, describe and export utility function `mergeHeaders()` to helps to write a middleware;
303
+
304
+ ## References
305
+
306
+ - [Fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API)
307
+ - [Request](https://developer.mozilla.org/en-US/docs/Web/API/Request)
308
+ - [Response](https://developer.mozilla.org/en-US/docs/Web/API/Response)
309
+ - [RequestInit](https://developer.mozilla.org/en-US/docs/Web/API/RequestInit)
310
+ - [429 Too Many Requests](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status/429)
85
311
 
86
312
  ## License
87
313
 
package/jsconfig.json ADDED
@@ -0,0 +1,12 @@
1
+ {
2
+ "compilerOptions": {
3
+ "checkJs": true,
4
+ "noImplicitAny": false,
5
+ "strict": false,
6
+ "types": ["node"]
7
+ },
8
+ "exclude": [
9
+ "node_modules",
10
+ "**/node_modules/*"
11
+ ]
12
+ }
package/package.json CHANGED
@@ -1,19 +1,39 @@
1
1
  {
2
2
  "name": "fetchbasequery",
3
- "version": "0.2.1",
3
+ "version": "1.0.1",
4
4
  "description": "Library for easily make HTTP queries without mass of boilerplate code.",
5
5
  "type": "module",
6
6
  "main": "src/fetchBaseQuery.js",
7
- "types": "types/index.d.ts",
7
+ "types": "src/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./src/index.d.ts",
11
+ "import": "./src/index.js"
12
+ },
13
+ "./decorators": {
14
+ "types": "./src/decorators/index.d.ts",
15
+ "import": "./src/decorators/index.js"
16
+ },
17
+ "./middlewares": {
18
+ "types": "./src/middlewares/index.d.ts",
19
+ "import": "./src/middlewares/index.js"
20
+ }
21
+ },
8
22
  "scripts": {
23
+ "test": "node tests/index.js"
9
24
  },
10
25
  "keywords": [
11
- "fetch", "fetchBaseQuery"
26
+ "fetch",
27
+ "fetchBaseQuery",
28
+ "middleware",
29
+ "retry",
30
+ "retryOnError",
31
+ "retryOn429",
32
+ "muteErrors",
33
+ "json"
12
34
  ],
13
- "author": "h41ku <h41ku.c0de@ya.ru>",
14
35
  "license": "MIT",
15
- "dependencies": {
16
- },
17
36
  "devDependencies": {
37
+ "@types/node": "^26.6.5"
18
38
  }
19
39
  }
@@ -0,0 +1,10 @@
1
+ import type { AbortablePromise, FetchFunction } from "../index.d.ts";
2
+
3
+ type Override<T, U> = Omit<T, keyof U> & U;
4
+
5
+ export type PlainObject = Record<string, any>;
6
+ export type JsonRequestInit = Override<RequestInit, { body?: BodyInit | PlainObject }>;
7
+ export type JsonResponse<T> = Response & { data?: T };
8
+ export type JsonFetchFunction<T> = (resource: string | Request, options?: JsonRequestInit) => AbortablePromise<T>;
9
+
10
+ export declare function json<T>(query: FetchFunction<Response>): JsonFetchFunction<JsonResponse<T>>;
@@ -0,0 +1 @@
1
+ export { json } from './json.js'
@@ -0,0 +1,107 @@
1
+ /**
2
+ * @typedef {import('../index.d.ts').FetchFunction<T>} FetchFunction
3
+ * @template T
4
+ */
5
+
6
+ /**
7
+ * @typedef {import('./index.d.ts').JsonFetchFunction<T>} JsonFetchFunction
8
+ * @template T
9
+ */
10
+
11
+ /**
12
+ * @typedef {import('./index.d.ts').PlainObject} PlainObject
13
+ */
14
+
15
+ /**
16
+ * @typedef {import('./index.d.ts').JsonRequestInit} JsonRequestInit
17
+ */
18
+
19
+ /**
20
+ * @typedef {import('../index.d.ts').AbortablePromise<T>} AbortablePromise
21
+ * @template T
22
+ */
23
+
24
+ /**
25
+ * @typedef {import('./index.d.ts').JsonResponse<T>} JsonResponse
26
+ * @template T
27
+ */
28
+
29
+ /**
30
+ *
31
+ * @param {BodyInit | PlainObject} value
32
+ * @returns {value is PlainObject}
33
+ */
34
+ function isPlainObject(value) {
35
+ return (
36
+ typeof value === 'object'
37
+ // && value !== null
38
+ && !(value instanceof ArrayBuffer)
39
+ && !(value instanceof FormData)
40
+ && !(value instanceof Blob)
41
+ && !(value instanceof ReadableStream)
42
+ && !(value instanceof URLSearchParams)
43
+ )
44
+ }
45
+
46
+ /**
47
+ *
48
+ * @param {PlainObject} body
49
+ * @returns {string}
50
+ */
51
+ function modifyBody(body) {
52
+ return JSON.stringify(body, (key, value) => {
53
+ if (value instanceof Error) {
54
+ return value.stack.split(/\r?\n/g)
55
+ } else if (typeof value === 'bigint') {
56
+ return value.toString()
57
+ }
58
+ return value
59
+ })
60
+ }
61
+
62
+ /**
63
+ *
64
+ * @param {HeadersInit} headers
65
+ * @returns {Headers}
66
+ */
67
+ function modifyHeaders(headers) {
68
+ const result = new Headers(headers)
69
+ if (!result.has('content-type'))
70
+ result.set('content-type', 'application/json; charset=utf-8')
71
+ return result
72
+ }
73
+
74
+ /**
75
+ *
76
+ * @param {FetchFunction<Response>} query
77
+ * @returns {JsonFetchFunction<JsonResponse<T>>}
78
+ * @template T
79
+ */
80
+ export function json(query) {
81
+
82
+ /**
83
+ * @param {string | Request} resource
84
+ * @param {JsonRequestInit} [options = {}]
85
+ */
86
+ return (resource, { body: initBody, headers: initHeaders, signal: initSignal, ...options } = {}) => {
87
+ const abortController = new AbortController()
88
+ const signal = AbortSignal.any([
89
+ abortController.signal,
90
+ ...(initSignal instanceof AbortSignal ? [ initSignal ] : [])
91
+ ])
92
+ /**
93
+ * @type {AbortablePromise<JsonResponse<T>>}
94
+ */
95
+ const promise = (async () => {
96
+ const isJson = isPlainObject(initBody)
97
+ const body = isJson ? modifyBody(initBody) : initBody
98
+ const headers = isJson ? modifyHeaders(initHeaders) : initHeaders
99
+ const response = /** @type {JsonResponse<T>} */ (await query(resource, { body, headers, signal, ...options }))
100
+ if (/^application\/json(\;| |$)/.test(String(response.headers.get('content-type'))))
101
+ response.data = await (response.clone().json())
102
+ return response
103
+ })();
104
+ promise.abort = (reason) => { abortController.abort(reason) }
105
+ return promise
106
+ }
107
+ }
@@ -1,15 +1,102 @@
1
- // const pipeAsync = (...fns) => (input) => fns.reduce((chain, func) => chain.then(func), Promise.resolve(input))
2
- import abortable from './helpers/abortable.js'
3
- import pipe from './helpers/pipe.js'
4
- import defaultBaseQuery from './baseQuery.js'
5
-
6
- export default ({ baseQuery, middlewares, ...defaultOptions } = {}) => {
7
- const pipedQuery = pipe(...(middlewares || []).map(abortable))(baseQuery || defaultBaseQuery)
8
- return options => pipedQuery({
9
- ...defaultOptions,
10
- ...options
11
- })
12
- }
1
+ /**
2
+ * @typedef {import('./index.d.ts').FetchBaseQueryOptions} FetchBaseQueryOptions
3
+ */
4
+
5
+ /**
6
+ * @typedef {import('./index.d.ts').AbortablePromise<T>} AbortablePromise<T>
7
+ * @template T
8
+ */
9
+
10
+ /**
11
+ * @typedef {import('./index.d.ts').FetchFunction<T>} FetchFunction<T>
12
+ * @template T
13
+ */
14
+
15
+ /**
16
+ *
17
+ * @param {import('./index.d.ts').FetchBaseQueryOptions} options
18
+ * @returns {FetchFunction<T>}
19
+ * @template T
20
+ */
21
+ export function fetchBaseQuery({
22
+ baseUrl = '',
23
+ timeout = Number.MAX_SAFE_INTEGER,
24
+ fetch = globalThis.fetch,
25
+ middlewares = [],
26
+ ...baseOptions
27
+ } = {}) {
13
28
 
14
- export { defaultBaseQuery as baseQuery }
15
- export * from './middlewares/index.js'
29
+ const abortController = new AbortController()
30
+
31
+ /**
32
+ *
33
+ * @param {number} index
34
+ * @param {Request} request
35
+ * @returns {Promise<Response>}
36
+ */
37
+ const runChain = (index, request) => {
38
+ if (index === middlewares.length) {
39
+ return fetch(request)
40
+ }
41
+ /**
42
+ * @param {Request} request
43
+ * @returns {Promise<Response>}
44
+ */
45
+ const next = (request) => runChain(index + 1, request)
46
+ return middlewares[index](request, next)
47
+ }
48
+
49
+ /**
50
+ *
51
+ * @param {string} endpoint
52
+ * @returns {string}
53
+ */
54
+ const useBaseUrl = (endpoint) => {
55
+ let url, origin, prefix = '/'
56
+ if (baseUrl) {
57
+ const url = new URL(baseUrl)
58
+ origin = url.origin
59
+ prefix = url.pathname
60
+ }
61
+ try {
62
+ url = new URL(endpoint)
63
+ } catch (error) {
64
+ url = new URL(
65
+ /\/$/.test(prefix) && /^\//.test(endpoint)
66
+ ? prefix + endpoint.substring(1)
67
+ : prefix + endpoint,
68
+ origin
69
+ )
70
+ }
71
+ return url.toString()
72
+ }
73
+
74
+ /**
75
+ *
76
+ * @param {string | Request} resource
77
+ * @param {RequestInit} [options = {}]
78
+ * @returns {AbortablePromise<T>}
79
+ */
80
+ return (resource, options = {}) => {
81
+ const signalByTimeout = timeout !== Number.MAX_SAFE_INTEGER ? AbortSignal.timeout(timeout) : undefined
82
+ const signalFromRequest = resource instanceof Request ? resource.signal : undefined
83
+ const { signal: signalFromOptions, ...otherOptions } = options
84
+ const target = resource instanceof Request ? resource : useBaseUrl(resource)
85
+ const request = new Request(target, {
86
+ ...baseOptions,
87
+ signal: AbortSignal.any([
88
+ abortController.signal,
89
+ signalByTimeout,
90
+ signalFromRequest,
91
+ signalFromOptions
92
+ ].filter(signal => signal instanceof AbortSignal)),
93
+ ...otherOptions
94
+ })
95
+ const promise = /** @type {AbortablePromise<T>} */ (runChain(0, request))
96
+ /**
97
+ * @param {string} reason
98
+ */
99
+ promise.abort = (reason) => { abortController.abort(reason) }
100
+ return promise
101
+ }
102
+ }
package/src/index.d.ts ADDED
@@ -0,0 +1,19 @@
1
+ export type AbortablePromise<T> = Promise<T> & {
2
+ abort: (reason?: string) => void
3
+ };
4
+
5
+ export type Middleware = (request: Request, next: (request: Request) => Promise<Response>) => Promise<Response>;
6
+
7
+ export type BaseFetchFunction = (resource: string | Request, options?: RequestInit) => Promise<Response>;
8
+ export type FetchBaseQueryOptions = RequestInit & {
9
+ baseUrl?: string, // origin or prefix, used for URLs without it
10
+ timeout?: number, // default timeout in milliseconds
11
+ fetch?: BaseFetchFunction, // by default this is reference to `globalThis.fetch()`
12
+ middlewares?: Middleware[] // list of middleware functions
13
+ };
14
+
15
+ export type FetchFunction<T> = (resource: string | Request, options?: RequestInit) => AbortablePromise<T>;
16
+
17
+ export declare function fetchBaseQuery<T>(options?: FetchBaseQueryOptions): FetchFunction<T>;
18
+
19
+ export default fetchBaseQuery
package/src/index.js ADDED
@@ -0,0 +1,4 @@
1
+ import { fetchBaseQuery } from './fetchBaseQuery.js'
2
+ export { fetchBaseQuery }
3
+
4
+ export default fetchBaseQuery
@@ -0,0 +1,14 @@
1
+ export type RetryOnErrorOptions = {
2
+ maxNumAttempts?: number = 5, // the maximum number of attempts
3
+ backoffTime?: (attempt: number) => number, // delay time in milliseconds
4
+ };
5
+
6
+ export type RetryOn429Options = {
7
+ maxNumAttempts?: number = 5, // the maximum number of attempts
8
+ maxBackoffTime?: number = Infinity, // the maximum permissible delay time
9
+ backoffTime?: (attempt: number, response: Response) => number, // delay time in milliseconds
10
+ };
11
+
12
+ export declare function muteErrors(): Middleware;
13
+ export declare function retryOn429(options?: RetryOn429Options): Middleware;
14
+ export declare function retryOnError(options?: RetryOnErrorOptions): Middleware;