fetchbasequery 0.0.2 → 0.1.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/README.md CHANGED
@@ -2,8 +2,21 @@
2
2
 
3
3
  Library for easily make HTTP queries without mass of boilerplate code.
4
4
 
5
- Usage
6
- -----
5
+ ## Installation
6
+
7
+ NPM:
8
+
9
+ ```sh
10
+ npm install fetchbasequery
11
+ ```
12
+
13
+ PNPM:
14
+
15
+ ```sh
16
+ pnpm add fetchbasequery
17
+ ```
18
+
19
+ ## Usage
7
20
 
8
21
  Build base query function:
9
22
 
@@ -11,14 +24,21 @@ Build base query function:
11
24
  import fetchBaseQuery, { baseQuery, encodeBody, accessToken, jsonReply, commonReply } from 'fetchbasequery'
12
25
 
13
26
  const query = fetchBaseQuery({
27
+ // main options ...
14
28
  baseUrl: 'https://api.example.org/v1'
15
29
  baseQuery,
16
30
  logErrors: true,
31
+ // add some defaults for `fetch()` ...
32
+ mode: 'cors',
33
+ credentials: 'include',
34
+ cache: 'reload',
35
+ // middlewares
17
36
  middleware: [
18
37
  encodeBody(),
19
38
  accessToken({
20
39
  getAccessToken: () => localStorage.getItem('access_token'),
21
40
  setAccessToken: (token) => localStorage.setItem('access_token', token),
41
+ removeAccessToken: (token) => localStorage.removeItem('access_token'),
22
42
  getUpdatedAccessToken: async (response) => response.headers.get('X-Access-Token')
23
43
  }),
24
44
  jsonReply(),
@@ -54,3 +74,7 @@ addEventListener('fetch', evt => {
54
74
  It works fine both on frontend and backend sides. For backend side usage Node.js v18+ is required,
55
75
  because the middleware `baseQuery` based on `Fetch API`. But it can be replaced with your own
56
76
  implementation based on another API (e.g. based on `axios` etc).
77
+
78
+ ## License
79
+
80
+ MIT
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fetchbasequery",
3
- "version": "0.0.2",
3
+ "version": "0.1.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",
package/src/baseQuery.js CHANGED
@@ -1,5 +1,6 @@
1
1
  import responseFromError from './helpers/responseFromError.js'
2
2
  import purge from './helpers/purge.js'
3
+ import mergeHeaders from './helpers/mergeHeaders.js'
3
4
 
4
5
  const moduleName = 'fetchBaseQuery/baseQuery'
5
6
 
@@ -16,12 +17,6 @@ export default async ({ url: endpoint, request: subject, ...options } = {}) => {
16
17
  : undefined,
17
18
  ...options
18
19
  }
19
- // default options for `fetch()`
20
- const defaultFetchOptions = {
21
- method: 'GET',
22
- cache: 'reload',
23
- credentials: 'include',
24
- }
25
20
  // extract options which are known by `fetch()`
26
21
  const { method, headers, body, mode, credentials, cache, redirect,
27
22
  referrer, referrerPolicy, integrity, keepalive, signal } = restOptions
@@ -50,11 +45,13 @@ export default async ({ url: endpoint, request: subject, ...options } = {}) => {
50
45
  )
51
46
  }
52
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 })
53
54
  }
54
- request = new Request(subject, {
55
- ...defaultFetchOptions,
56
- ...fetchOptions
57
- })
58
55
  response = await fetch(request)
59
56
  } catch (error) {
60
57
  if (logErrors) {
@@ -63,7 +60,7 @@ export default async ({ url: endpoint, request: subject, ...options } = {}) => {
63
60
  response = responseFromError(error)
64
61
  }
65
62
  if (debug?.baseQuery) {
66
- console.log(moduleName, response)
63
+ console.log(moduleName, { response })
67
64
  }
68
65
  return response
69
66
  }
@@ -0,0 +1,7 @@
1
+ export default (a, b) => {
2
+ const result = new Headers(a)
3
+ b = (b instanceof Headers ? b : new Headers(b))
4
+ b.entries().forEach(pair => result.delete(pair[0]))
5
+ b.entries().forEach(pair => result.append(pair[0], pair[1]))
6
+ return result
7
+ }
@@ -1,4 +1,16 @@
1
- export default object => Object.fromEntries(
1
+ const purgeObject = object => Object.fromEntries(
2
2
  Object.entries(object)
3
3
  .filter(entry => entry[1] !== undefined)
4
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 +1,6 @@
1
1
  import responseFromError from '../helpers/responseFromError.js'
2
2
  import purge from '../helpers/purge.js'
3
+ import mergeHeaders from '../helpers/mergeHeaders.js'
3
4
 
4
5
  const moduleName = 'fetchBaseQuery/middlewares/accessToken'
5
6
 
@@ -7,12 +8,14 @@ export default (settings = {}) => query => async ({ payload, headers, ...options
7
8
  const {
8
9
  getAccessToken,
9
10
  setAccessToken,
11
+ removeAccessToken,
10
12
  isUnauthorized,
11
13
  getUpdatedAccessToken,
12
14
  getAuthorizationHeaders
13
15
  } = {
14
16
  getAccessToken: (payload) => undefined,
15
17
  setAccessToken: (token) => {},
18
+ removeAccessToken: () => {},
16
19
  isUnauthorized: (response) => response.status === 401,
17
20
  getUpdatedAccessToken: async (response) => undefined,
18
21
  getAuthorizationHeaders: (accessToken) => (
@@ -26,10 +29,10 @@ export default (settings = {}) => query => async ({ payload, headers, ...options
26
29
  try {
27
30
  response = await query({
28
31
  ...options,
29
- headers: purge({
30
- ...(getAuthorizationHeaders(getAccessToken(payload))),
31
- ...(headers || {})
32
- })
32
+ headers: mergeHeaders(
33
+ purge(getAuthorizationHeaders(getAccessToken(payload))),
34
+ headers || {}
35
+ )
33
36
  })
34
37
  } catch (error) {
35
38
  if (options.logErrors) {
@@ -39,7 +42,7 @@ export default (settings = {}) => query => async ({ payload, headers, ...options
39
42
  }
40
43
  try {
41
44
  if (isUnauthorized(response)) {
42
- setAccessToken(null) // special case to remove access token from storage
45
+ removeAccessToken()
43
46
  } else {
44
47
  const updatedAccessToken = await getUpdatedAccessToken(response)
45
48
  if (updatedAccessToken) {
@@ -53,7 +56,7 @@ export default (settings = {}) => query => async ({ payload, headers, ...options
53
56
  response = responseFromError(error)
54
57
  }
55
58
  if (options.debug?.accessToken) {
56
- console.log(moduleName, response)
59
+ console.log(moduleName, { response })
57
60
  }
58
61
  return response
59
62
  }
@@ -17,7 +17,7 @@ export default () => query => async (options) => {
17
17
  reply = { status, headers }
18
18
  }
19
19
  if (options.debug?.commonReply) {
20
- console.log(moduleName, reply)
20
+ console.log(moduleName, { reply })
21
21
  }
22
22
  return reply
23
23
  }
@@ -1,6 +1,7 @@
1
1
  import purge from '../helpers/purge.js'
2
2
  import encodeJson from '../helpers/encodeJson.js'
3
3
  import responseFromError from '../helpers/responseFromError.js'
4
+ import mergeHeaders from '../helpers/mergeHeaders.js'
4
5
 
5
6
  const moduleName = 'fetchBaseQuery/middlewares/accessToken'
6
7
 
@@ -61,12 +62,14 @@ export default (settings = {}) => (query) => async ({ body, headers, ...options
61
62
  try {
62
63
  response = await query({
63
64
  ...options,
64
- headers: purge({
65
- 'Content-Type': contentType instanceof Function
66
- ? contentType({ body })
67
- : contentType,
68
- ...(headers || {})
69
- }),
65
+ headers: mergeHeaders(
66
+ purge({
67
+ 'Content-Type': contentType instanceof Function
68
+ ? contentType({ body })
69
+ : contentType
70
+ }),
71
+ headers || {}
72
+ ),
70
73
  body: encodeBody(body)
71
74
  })
72
75
  } catch (error) {
@@ -76,7 +79,7 @@ export default (settings = {}) => (query) => async ({ body, headers, ...options
76
79
  response = responseFromError(error)
77
80
  }
78
81
  if (options.debug?.encodeBody) {
79
- console.log(moduleName, response)
82
+ console.log(moduleName, { response })
80
83
  }
81
84
  return response
82
85
  }
@@ -29,7 +29,7 @@ export default (settings = {}) => query => async (options = {}) => {
29
29
  }
30
30
  }
31
31
  if (options.debug?.jsonReply) {
32
- console.log(moduleName, reply)
32
+ console.log(moduleName, { reply })
33
33
  }
34
34
  return reply
35
35
  }
package/types/index.d.ts CHANGED
@@ -11,7 +11,7 @@ export type FetchOptions = {
11
11
  url: URL | string | undefined,
12
12
  request: Request | undefined,
13
13
  method: string | undefined,
14
- headers: object | undefined,
14
+ headers: Headers | object | undefined,
15
15
  body: string
16
16
  | object
17
17
  | FormData