fetchache 0.1.2 → 0.1.4

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.
Files changed (4) hide show
  1. package/index.d.ts +2 -2
  2. package/index.js +46 -30
  3. package/index.mjs +46 -30
  4. package/package.json +1 -1
package/index.d.ts CHANGED
@@ -3,14 +3,14 @@ export interface FetchacheCacheEntry {
3
3
  policy: CachePolicy.CachePolicyObject;
4
4
  body: string;
5
5
  }
6
- declare type FetchFn = WindowOrWorkerGlobalScope['fetch'];
6
+ declare type FetchFn = (input: URL | RequestInfo, init: RequestInit, ...rest: any[]) => Promise<Response>;
7
7
  export interface FetchacheOptions {
8
8
  fetch: FetchFn;
9
9
  Request: typeof Request;
10
10
  Response: typeof Response;
11
11
  cache: KeyValueCache<FetchacheCacheEntry>;
12
12
  }
13
- export declare function fetchFactory({ fetch, Request, Response, cache }: FetchacheOptions): FetchFn;
13
+ export declare function fetchFactory({ fetch, Response, cache }: FetchacheOptions): FetchFn;
14
14
  export interface KeyValueCacheSetOptions {
15
15
  /**
16
16
  * Specified in **seconds**, the time-to-live (TTL) value limits the lifespan
package/index.js CHANGED
@@ -6,20 +6,29 @@ function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'defau
6
6
 
7
7
  const CachePolicy = _interopDefault(require('http-cache-semantics'));
8
8
 
9
- function fetchFactory({ fetch, Request, Response, cache }) {
10
- return async (input, init) => {
11
- let request;
12
- if (input instanceof Request) {
13
- request = input;
9
+ function fetchFactory({ fetch, Response, cache }) {
10
+ return async (input, init, ...rest) => {
11
+ let url;
12
+ let method = 'GET';
13
+ let headers = {};
14
+ if (typeof input === 'object' && 'json' in input) {
15
+ url = input.url;
16
+ method = input.method;
17
+ headers = input.headers;
14
18
  }
15
19
  else {
16
- request = new Request(input, init);
20
+ url = input.toString();
21
+ if (init != null) {
22
+ method = init.method || method;
23
+ headers = init.headers || headers;
24
+ }
17
25
  }
18
- const cacheKey = request.url;
26
+ const cacheKey = url;
19
27
  const entry = await cache.get(cacheKey);
28
+ const policyRequest = policyRequestFrom(url, method, headers);
20
29
  if (!entry) {
21
- const response = await fetch(request);
22
- const policy = new CachePolicy(policyRequestFrom(request), policyResponseFrom(response));
30
+ const response = await fetch(input, init, ...rest);
31
+ const policy = new CachePolicy(policyRequest, policyResponseFrom(response));
23
32
  return storeResponseAndReturnClone(cache, response, policy, cacheKey);
24
33
  }
25
34
  const { policy: policyRaw, bytes } = typeof entry === 'string' ? JSON.parse(entry) : entry;
@@ -27,7 +36,7 @@ function fetchFactory({ fetch, Request, Response, cache }) {
27
36
  // Remove url from the policy, because otherwise it would never match a request with a custom cache key
28
37
  policy._url = undefined;
29
38
  const bodyInit = new Uint8Array(bytes);
30
- if (policy.satisfiesWithoutRevalidation(policyRequestFrom(request))) {
39
+ if (policy.satisfiesWithoutRevalidation(policyRequest)) {
31
40
  const headers = policy.responseHeaders();
32
41
  return new Response(bodyInit, {
33
42
  url: policy._url,
@@ -36,12 +45,17 @@ function fetchFactory({ fetch, Request, Response, cache }) {
36
45
  });
37
46
  }
38
47
  else {
39
- const revalidationHeaders = policy.revalidationHeaders(policyRequestFrom(request));
40
- const revalidationRequest = new Request(request, {
41
- headers: revalidationHeaders,
42
- });
43
- const revalidationResponse = await fetch(revalidationRequest);
44
- const { policy: revalidatedPolicy, modified } = policy.revalidatedPolicy(policyRequestFrom(revalidationRequest), policyResponseFrom(revalidationResponse));
48
+ const revalidationHeaders = policy.revalidationHeaders(policyRequest);
49
+ const revalidationResponse = await fetch(url, {
50
+ ...init,
51
+ method,
52
+ headers: {
53
+ ...headers,
54
+ ...revalidationHeaders,
55
+ },
56
+ }, ...rest);
57
+ const revalidationPolicyRequest = policyRequestFrom(url, method, revalidationHeaders);
58
+ const { policy: revalidatedPolicy, modified } = policy.revalidatedPolicy(revalidationPolicyRequest, policyResponseFrom(revalidationResponse));
45
59
  const newArrayBuffer = await revalidationResponse.arrayBuffer();
46
60
  const newBody = modified ? newArrayBuffer : bodyInit;
47
61
  return storeResponseAndReturnClone(cache, new Response(newBody, {
@@ -64,7 +78,7 @@ function fetchFactory({ fetch, Request, Response, cache }) {
64
78
  const uint8array = new Uint8Array(arrayBuffer);
65
79
  const entry = {
66
80
  policy: policy.toObject(),
67
- bytes: [...uint8array],
81
+ bytes: Array.from(uint8array),
68
82
  };
69
83
  await cache.set(cacheKey, entry, {
70
84
  ttl,
@@ -73,22 +87,17 @@ function fetchFactory({ fetch, Request, Response, cache }) {
73
87
  // body can only be used once.
74
88
  // To avoid https://github.com/bitinn/node-fetch/issues/151, we don't use
75
89
  // response.clone() but create a new response from the consumed body
76
- return new Response(uint8array, {
77
- url: response.url,
78
- status: response.status,
79
- statusText: response.statusText,
80
- headers: response.headers,
81
- });
90
+ return new Response(uint8array, response);
82
91
  }
83
92
  }
84
93
  function canBeRevalidated(response) {
85
94
  return response.headers.has('ETag');
86
95
  }
87
- function policyRequestFrom(request) {
96
+ function policyRequestFrom(url, method, headers) {
88
97
  return {
89
- url: request.url,
90
- method: request.method,
91
- headers: headersToObject(request.headers),
98
+ url,
99
+ method,
100
+ headers: headersToObject(headers),
92
101
  };
93
102
  }
94
103
  function policyResponseFrom(response) {
@@ -99,9 +108,16 @@ function policyResponseFrom(response) {
99
108
  }
100
109
  function headersToObject(headers) {
101
110
  const object = Object.create(null);
102
- headers === null || headers === void 0 ? void 0 : headers.forEach((val, key) => {
103
- object[key] = val;
104
- });
111
+ if (headers != null) {
112
+ if ('forEach' in headers && typeof headers.forEach === 'function') {
113
+ headers === null || headers === void 0 ? void 0 : headers.forEach((val, key) => {
114
+ object[key] = val;
115
+ });
116
+ }
117
+ else {
118
+ return headers;
119
+ }
120
+ }
105
121
  return object;
106
122
  }
107
123
 
package/index.mjs CHANGED
@@ -1,19 +1,28 @@
1
1
  import CachePolicy from 'http-cache-semantics';
2
2
 
3
- function fetchFactory({ fetch, Request, Response, cache }) {
4
- return async (input, init) => {
5
- let request;
6
- if (input instanceof Request) {
7
- request = input;
3
+ function fetchFactory({ fetch, Response, cache }) {
4
+ return async (input, init, ...rest) => {
5
+ let url;
6
+ let method = 'GET';
7
+ let headers = {};
8
+ if (typeof input === 'object' && 'json' in input) {
9
+ url = input.url;
10
+ method = input.method;
11
+ headers = input.headers;
8
12
  }
9
13
  else {
10
- request = new Request(input, init);
14
+ url = input.toString();
15
+ if (init != null) {
16
+ method = init.method || method;
17
+ headers = init.headers || headers;
18
+ }
11
19
  }
12
- const cacheKey = request.url;
20
+ const cacheKey = url;
13
21
  const entry = await cache.get(cacheKey);
22
+ const policyRequest = policyRequestFrom(url, method, headers);
14
23
  if (!entry) {
15
- const response = await fetch(request);
16
- const policy = new CachePolicy(policyRequestFrom(request), policyResponseFrom(response));
24
+ const response = await fetch(input, init, ...rest);
25
+ const policy = new CachePolicy(policyRequest, policyResponseFrom(response));
17
26
  return storeResponseAndReturnClone(cache, response, policy, cacheKey);
18
27
  }
19
28
  const { policy: policyRaw, bytes } = typeof entry === 'string' ? JSON.parse(entry) : entry;
@@ -21,7 +30,7 @@ function fetchFactory({ fetch, Request, Response, cache }) {
21
30
  // Remove url from the policy, because otherwise it would never match a request with a custom cache key
22
31
  policy._url = undefined;
23
32
  const bodyInit = new Uint8Array(bytes);
24
- if (policy.satisfiesWithoutRevalidation(policyRequestFrom(request))) {
33
+ if (policy.satisfiesWithoutRevalidation(policyRequest)) {
25
34
  const headers = policy.responseHeaders();
26
35
  return new Response(bodyInit, {
27
36
  url: policy._url,
@@ -30,12 +39,17 @@ function fetchFactory({ fetch, Request, Response, cache }) {
30
39
  });
31
40
  }
32
41
  else {
33
- const revalidationHeaders = policy.revalidationHeaders(policyRequestFrom(request));
34
- const revalidationRequest = new Request(request, {
35
- headers: revalidationHeaders,
36
- });
37
- const revalidationResponse = await fetch(revalidationRequest);
38
- const { policy: revalidatedPolicy, modified } = policy.revalidatedPolicy(policyRequestFrom(revalidationRequest), policyResponseFrom(revalidationResponse));
42
+ const revalidationHeaders = policy.revalidationHeaders(policyRequest);
43
+ const revalidationResponse = await fetch(url, {
44
+ ...init,
45
+ method,
46
+ headers: {
47
+ ...headers,
48
+ ...revalidationHeaders,
49
+ },
50
+ }, ...rest);
51
+ const revalidationPolicyRequest = policyRequestFrom(url, method, revalidationHeaders);
52
+ const { policy: revalidatedPolicy, modified } = policy.revalidatedPolicy(revalidationPolicyRequest, policyResponseFrom(revalidationResponse));
39
53
  const newArrayBuffer = await revalidationResponse.arrayBuffer();
40
54
  const newBody = modified ? newArrayBuffer : bodyInit;
41
55
  return storeResponseAndReturnClone(cache, new Response(newBody, {
@@ -58,7 +72,7 @@ function fetchFactory({ fetch, Request, Response, cache }) {
58
72
  const uint8array = new Uint8Array(arrayBuffer);
59
73
  const entry = {
60
74
  policy: policy.toObject(),
61
- bytes: [...uint8array],
75
+ bytes: Array.from(uint8array),
62
76
  };
63
77
  await cache.set(cacheKey, entry, {
64
78
  ttl,
@@ -67,22 +81,17 @@ function fetchFactory({ fetch, Request, Response, cache }) {
67
81
  // body can only be used once.
68
82
  // To avoid https://github.com/bitinn/node-fetch/issues/151, we don't use
69
83
  // response.clone() but create a new response from the consumed body
70
- return new Response(uint8array, {
71
- url: response.url,
72
- status: response.status,
73
- statusText: response.statusText,
74
- headers: response.headers,
75
- });
84
+ return new Response(uint8array, response);
76
85
  }
77
86
  }
78
87
  function canBeRevalidated(response) {
79
88
  return response.headers.has('ETag');
80
89
  }
81
- function policyRequestFrom(request) {
90
+ function policyRequestFrom(url, method, headers) {
82
91
  return {
83
- url: request.url,
84
- method: request.method,
85
- headers: headersToObject(request.headers),
92
+ url,
93
+ method,
94
+ headers: headersToObject(headers),
86
95
  };
87
96
  }
88
97
  function policyResponseFrom(response) {
@@ -93,9 +102,16 @@ function policyResponseFrom(response) {
93
102
  }
94
103
  function headersToObject(headers) {
95
104
  const object = Object.create(null);
96
- headers === null || headers === void 0 ? void 0 : headers.forEach((val, key) => {
97
- object[key] = val;
98
- });
105
+ if (headers != null) {
106
+ if ('forEach' in headers && typeof headers.forEach === 'function') {
107
+ headers === null || headers === void 0 ? void 0 : headers.forEach((val, key) => {
108
+ object[key] = val;
109
+ });
110
+ }
111
+ else {
112
+ return headers;
113
+ }
114
+ }
99
115
  return object;
100
116
  }
101
117
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fetchache",
3
- "version": "0.1.2",
3
+ "version": "0.1.4",
4
4
  "description": "Cross Platform Fetch Wrapper with Key Value Cache support",
5
5
  "sideEffects": false,
6
6
  "dependencies": {