fetchbasequery 0.2.1 → 1.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/src/baseQuery.js DELETED
@@ -1,80 +0,0 @@
1
- import responseFromError from './helpers/responseFromError.js'
2
- import purge from './helpers/purge.js'
3
- import mergeHeaders from './helpers/mergeHeaders.js'
4
-
5
- const moduleName = 'fetchBaseQuery/baseQuery'
6
-
7
- const baseQuery = async ({ url: endpoint, request: subject, ...options } = {}) => {
8
- const {
9
- baseUrl,
10
- logErrors,
11
- debug,
12
- ...restOptions
13
- } = {
14
- logErrors: false,
15
- baseUrl: globalThis.location
16
- ? globalThis.location.origin
17
- : undefined,
18
- ...options
19
- }
20
- // extract options which are known by `fetch()`
21
- const { method, headers, body, mode, credentials, cache, redirect,
22
- referrer, referrerPolicy, integrity, keepalive, signal } = restOptions
23
- // combine extracted options and remove undefined properties
24
- const fetchOptions = purge({ method, headers, body, mode, credentials, cache, redirect,
25
- referrer, referrerPolicy, integrity, keepalive, signal })
26
- // do request
27
- let request
28
- let response
29
- try {
30
- if (endpoint !== undefined) {
31
- let url, origin, prefix = '/'
32
- if (baseUrl) {
33
- const url = new URL(baseUrl)
34
- origin = url.origin
35
- prefix = url.pathname
36
- }
37
- try {
38
- url = new URL(endpoint)
39
- } catch (error) {
40
- url = new URL(
41
- /\/$/.test(prefix) && /^\//.test(endpoint)
42
- ? prefix + endpoint.substring(1)
43
- : prefix + endpoint,
44
- origin
45
- )
46
- }
47
- subject = url
48
- } else if (fetchOptions.headers) {
49
- fetchOptions.headers = mergeHeaders(subject.headers, fetchOptions.headers)
50
- }
51
- request = new Request(subject, fetchOptions)
52
- if (debug?.baseQuery) {
53
- console.log(moduleName, { request })
54
- }
55
- response = await fetch(request)
56
- } catch (error) {
57
- if (logErrors) {
58
- console.error(moduleName, error)
59
- }
60
- response = responseFromError(error)
61
- }
62
- if (debug?.baseQuery) {
63
- console.log(moduleName, { response })
64
- }
65
- return response
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
- }
@@ -1,13 +0,0 @@
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
- }
@@ -1,8 +0,0 @@
1
- export default body => JSON.stringify(body, (key, value) => {
2
- if (value instanceof Error) {
3
- return value.stack.split(/\r?\n/g)
4
- } else if (typeof value === 'bigint') {
5
- return value.toString()
6
- }
7
- return value
8
- })
@@ -1,9 +0,0 @@
1
- export default (a, b) => {
2
- const result = new Headers(a)
3
- b = (b instanceof Headers ? b : new Headers(b))
4
- for (let pair of b.entries())
5
- result.delete(pair[0])
6
- for (let pair of b.entries())
7
- result.append(pair[0], pair[1])
8
- return result
9
- }
@@ -1 +0,0 @@
1
- export default (...fns) => (input) => fns.reduce((chain, f) => f(chain), input)
@@ -1,16 +0,0 @@
1
- const purgeObject = object => Object.fromEntries(
2
- Object.entries(object)
3
- .filter(entry => entry[1] !== undefined)
4
- )
5
-
6
- const purgeHeaders = headers => {
7
- headers.entities().forEach(([ name, value ]) => {
8
- if (value === '')
9
- headers.delete(name)
10
- })
11
- return headers
12
- }
13
-
14
- export default object => object instanceof Headers
15
- ? purgeHeaders(object)
16
- : purgeObject(object)
@@ -1,5 +0,0 @@
1
- export default (error) => {
2
- const response = Response.error()
3
- response.error = error
4
- return response
5
- }
@@ -1,62 +0,0 @@
1
- import responseFromError from '../helpers/responseFromError.js'
2
- import purge from '../helpers/purge.js'
3
- import mergeHeaders from '../helpers/mergeHeaders.js'
4
-
5
- const moduleName = 'fetchBaseQuery/middlewares/accessToken'
6
-
7
- export default (settings = {}) => query => async ({ payload, headers, ...options } = {}) => {
8
- const {
9
- getAccessToken,
10
- setAccessToken,
11
- removeAccessToken,
12
- isUnauthorized,
13
- getUpdatedAccessToken,
14
- getAuthorizationHeaders
15
- } = {
16
- getAccessToken: (payload) => undefined,
17
- setAccessToken: (token) => {},
18
- removeAccessToken: () => {},
19
- isUnauthorized: (response) => response.status === 401,
20
- getUpdatedAccessToken: async (response) => undefined,
21
- getAuthorizationHeaders: (accessToken) => (
22
- accessToken
23
- ? { Authorization: `bearer ${accessToken}` }
24
- : {}
25
- ),
26
- ...settings
27
- }
28
- let response
29
- try {
30
- response = await query({
31
- ...options,
32
- headers: mergeHeaders(
33
- purge(getAuthorizationHeaders(getAccessToken(payload))),
34
- headers || {}
35
- )
36
- })
37
- } catch (error) {
38
- if (options.logErrors) {
39
- console.error(moduleName, error)
40
- }
41
- response = responseFromError(error)
42
- }
43
- try {
44
- if (isUnauthorized(response)) {
45
- removeAccessToken()
46
- } else {
47
- const updatedAccessToken = await getUpdatedAccessToken(response)
48
- if (updatedAccessToken) {
49
- setAccessToken(updatedAccessToken)
50
- }
51
- }
52
- } catch (error) {
53
- if (options.logErrors) {
54
- console.error(moduleName, error)
55
- }
56
- response = responseFromError(error)
57
- }
58
- if (options.debug?.accessToken) {
59
- console.log(moduleName, { response })
60
- }
61
- return response
62
- }
@@ -1,23 +0,0 @@
1
- const moduleName = 'fetchBaseQuery/middlewares/commonReply'
2
-
3
- export default () => query => async (options) => {
4
- const { status, data, error, headers } = await query(options)
5
- let reply
6
- if (error) {
7
- reply = { status, error: true, message: error.message || error, headers }
8
- } else if (data) {
9
- if (data.success) {
10
- reply = { ...data, status, headers }
11
- } else if (data.error) {
12
- reply = { status, error: true, message: data.message, headers }
13
- } else {
14
- reply = { status, error: true, message: 'Unexpected format of common response body.', headers }
15
- }
16
- } else {
17
- reply = { status, headers }
18
- }
19
- if (options.debug?.commonReply) {
20
- console.log(moduleName, { reply })
21
- }
22
- return reply
23
- }
@@ -1,85 +0,0 @@
1
- import purge from '../helpers/purge.js'
2
- import encodeJson from '../helpers/encodeJson.js'
3
- import responseFromError from '../helpers/responseFromError.js'
4
- import mergeHeaders from '../helpers/mergeHeaders.js'
5
-
6
- const moduleName = 'fetchBaseQuery/middlewares/accessToken'
7
-
8
- const getEncodedBody = body => (
9
- typeof body === 'string'
10
- || body instanceof String
11
- || body instanceof FormData
12
- || body instanceof Blob
13
- || body instanceof ArrayBuffer
14
- || body instanceof DataView
15
- || body instanceof File
16
- || body instanceof ReadableStream
17
- || body instanceof Int8Array
18
- || body instanceof Uint8Array
19
- || body instanceof Int16Array
20
- || body instanceof Uint16Array
21
- || body instanceof Int32Array
22
- || body instanceof Uint32Array
23
- || body instanceof BigInt64Array
24
- || body instanceof BigUint64Array
25
- ? body // raw
26
- : (
27
- body instanceof URLSearchParams
28
- ? body.toString()
29
- : encodeJson(body) // default
30
- )
31
- )
32
-
33
- const detectContentType = ({ body }) => {
34
- if (body instanceof ArrayBuffer
35
- || body instanceof DataView
36
- || body instanceof ReadableStream
37
- || body instanceof Int8Array
38
- || body instanceof Uint8Array
39
- || body instanceof Int16Array
40
- || body instanceof Uint16Array
41
- || body instanceof Int32Array
42
- || body instanceof Uint32Array
43
- || body instanceof BigInt64Array
44
- || body instanceof BigUint64Array
45
- ) return 'application/octet-stream'
46
- if (body instanceof URLSearchParams) return 'application/x-www-form-urlencoded'
47
- if (body instanceof FormData) return 'multipart/form-data'
48
- if (body instanceof Object) return 'application/json; charset=utf-8'
49
- // return undefined
50
- }
51
-
52
- export default (settings = {}) => (query) => async ({ body, headers, ...options } = {}) => {
53
- const {
54
- contentType,
55
- encodeBody
56
- } = {
57
- contentType: detectContentType,
58
- encodeBody: getEncodedBody,
59
- ...settings
60
- }
61
- let response
62
- try {
63
- response = await query({
64
- ...options,
65
- headers: mergeHeaders(
66
- purge({
67
- 'Content-Type': contentType instanceof Function
68
- ? contentType({ body })
69
- : contentType
70
- }),
71
- headers || {}
72
- ),
73
- body: encodeBody(body)
74
- })
75
- } catch (error) {
76
- if (options.logErrors) {
77
- console.error(moduleName, error)
78
- }
79
- response = responseFromError(error)
80
- }
81
- if (options.debug?.encodeBody) {
82
- console.log(moduleName, { response })
83
- }
84
- return response
85
- }
@@ -1,35 +0,0 @@
1
- const moduleName = 'fetchBaseQuery/middlewares/jsonReply'
2
-
3
- export default (settings = {}) => query => async (options = {}) => {
4
- const {
5
- isJsonBody
6
- } = {
7
- isJsonBody: (response) => /^application\/json/i.test(response.headers.get('Content-Type')),
8
- ...settings
9
- }
10
- const response = await query(options)
11
- const { status, error, headers } = response
12
- let reply
13
- if (error) {
14
- reply = { status, error, headers }
15
- } else {
16
- let data
17
- try {
18
- if (isJsonBody(response)) {
19
- data = await response.json()
20
- reply = { status, data, headers }
21
- } else {
22
- reply = { status, headers }
23
- }
24
- } catch (error) {
25
- if (options.logErrors) {
26
- console.error(moduleName, error)
27
- }
28
- reply = { status, error, headers }
29
- }
30
- }
31
- if (options.debug?.jsonReply) {
32
- console.log(moduleName, { reply })
33
- }
34
- return reply
35
- }
package/types/index.d.ts DELETED
@@ -1,64 +0,0 @@
1
- export type DebuggingFlags = {
2
- baseQuery?: boolean,
3
- encodeBody?: boolean,
4
- accessToken?: boolean,
5
- jsonReply?: boolean,
6
- commonReply?: boolean
7
- };
8
-
9
- export type FetchOptions = {
10
- logErrors?: boolean,
11
- url?: URL | string,
12
- request?: Request,
13
- timeout?: number,
14
- method?: string,
15
- headers?: Headers | object,
16
- body?: string
17
- | object
18
- | FormData
19
- | Blob
20
- | ArrayBuffer
21
- | DataView
22
- | File
23
- | ReadableStream
24
- | Int8Array
25
- | Uint8Array
26
- | Int16Array
27
- | Uint16Array
28
- | Int32Array
29
- | Uint32Array
30
- | BigInt64Array
31
- | BigUint64Array
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
- };
44
-
45
- export type baseQueryFn = (options?: FetchOptions) => Promise<Response>;
46
- export type queryFn = (options?: FetchOptions) => Promise<any>;
47
- export type middlewareFn = (settings: any) => (query: queryFn) => queryFn;
48
-
49
- export type FetchBaseQueryOptions = {
50
- baseUrl?: URL | string,
51
- baseQuery?: baseQueryFn,
52
- middlewares?: Array<middlewareFn>
53
- };
54
-
55
- export const baseQuery: baseQueryFn;
56
-
57
- export const encodeBody: middlewareFn;
58
- export const accessToken: middlewareFn;
59
- export const jsonReply: middlewareFn;
60
- export const commonReply: middlewareFn;
61
-
62
- declare function fetchBaseQuery(options?: FetchBaseQueryOptions & FetchOptions): queryFn;
63
-
64
- export default fetchBaseQuery;