@alwatr/fetch 0.16.0 → 0.18.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/CHANGELOG.md +26 -2
- package/README.md +63 -10
- package/fetch.d.ts +66 -22
- package/fetch.d.ts.map +1 -1
- package/fetch.js +172 -59
- package/fetch.js.map +1 -1
- package/package.json +6 -4
package/CHANGELOG.md
CHANGED
|
@@ -3,13 +3,37 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
-
# [0.
|
|
6
|
+
# [0.18.0](https://github.com/AliMD/alwatr/compare/v0.17.0...v0.18.0) (2022-10-22)
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
### Bug Fixes
|
|
9
|
+
|
|
10
|
+
- **fetch:** update cache on network_first ([54b59cd](https://github.com/AliMD/alwatr/commit/54b59cdc64a543a0afcd09d2ec78d20661f3a06d))
|
|
11
|
+
|
|
12
|
+
### Features
|
|
13
|
+
|
|
14
|
+
- **fetch:** cache strategy ([106eabd](https://github.com/AliMD/alwatr/commit/106eabdd10574b24f9919049d0b509ae40168a9a))
|
|
15
|
+
- **fetch:** optional cacheStorageName ([f2bd8f2](https://github.com/AliMD/alwatr/commit/f2bd8f2a899466628417294cb269fd569b87e17a))
|
|
16
|
+
- **fetch:** stale_while_revalidate cache strategy ([f758f49](https://github.com/AliMD/alwatr/commit/f758f495efb42ce7441e8f2058c1b67de0615a8c))
|
|
17
|
+
|
|
18
|
+
# [0.17.0](https://github.com/AliMD/alwatr/compare/v0.16.1...v0.17.0) (2022-10-21)
|
|
9
19
|
|
|
20
|
+
### Bug Fixes
|
|
21
|
+
|
|
22
|
+
- **fetch:** not ok retry condition ([0da1edd](https://github.com/AliMD/alwatr/commit/0da1edda64ec5abf70a83361d159e207691e368e))
|
|
23
|
+
|
|
24
|
+
### Features
|
|
10
25
|
|
|
26
|
+
- **fetch:** docs & pattern ([459ad1c](https://github.com/AliMD/alwatr/commit/459ad1c5996f851769306639136d79c0f7270770))
|
|
27
|
+
- **fetch:** logger & jsdocs ([36f652d](https://github.com/AliMD/alwatr/commit/36f652d5dad23b2aeb824af77d1b0e442119c6e8))
|
|
28
|
+
- **fetch:** retry pattern ([5350d1a](https://github.com/AliMD/alwatr/commit/5350d1a81b9134d598f46006a1baa880b280ea98))
|
|
11
29
|
|
|
30
|
+
### Performance Improvements
|
|
12
31
|
|
|
32
|
+
- **fetch:** syntax ([1fdd02e](https://github.com/AliMD/alwatr/commit/1fdd02ec8b52e32a124b8d7c1d1c7fd7c993e3af))
|
|
33
|
+
|
|
34
|
+
# [0.16.0](https://github.com/AliMD/alwatr/compare/v0.15.0...v0.16.0) (2022-09-08)
|
|
35
|
+
|
|
36
|
+
**Note:** Version bump only for package @alwatr/fetch
|
|
13
37
|
|
|
14
38
|
# [0.15.0](https://github.com/AliMD/alwatr/compare/v0.14.0...v0.15.0) (2022-09-01)
|
|
15
39
|
|
package/README.md
CHANGED
|
@@ -1,20 +1,73 @@
|
|
|
1
1
|
# @alwatr/fetch
|
|
2
2
|
|
|
3
|
-
Enhanced fetch API with
|
|
3
|
+
Enhanced fetch API with cache strategy, retry pattern, timeout, helper methods and enhanced types written in tiny TypeScript, ES module.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Example usage
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
```ts
|
|
8
|
+
import {getJson} from 'https://esm.run/@alwatr/fetch';
|
|
8
9
|
|
|
9
|
-
|
|
10
|
+
interface ProductInterface {
|
|
11
|
+
_id: string;
|
|
12
|
+
name: string;
|
|
13
|
+
description: string;
|
|
14
|
+
image: string;
|
|
15
|
+
}
|
|
10
16
|
|
|
11
|
-
|
|
12
|
-
|
|
17
|
+
const productList = await getJson<Record<string, ProductInterface>>({
|
|
18
|
+
url: '/api/products',
|
|
19
|
+
queryParameters: {limit: 10},
|
|
20
|
+
timeout: 5_000,
|
|
21
|
+
retry: 3,
|
|
22
|
+
cacheStrategy: 'stale_while_revalidate',
|
|
23
|
+
});
|
|
24
|
+
```
|
|
13
25
|
|
|
14
|
-
##
|
|
26
|
+
## Fetch Options
|
|
15
27
|
|
|
16
|
-
|
|
17
|
-
|
|
28
|
+
`FetchOptions` inherited from the [fetch standard parameters](https://developer.mozilla.org/en-US/docs/Web/API/fetch#parameters) and some other...
|
|
29
|
+
|
|
30
|
+
- `url`: Request URL.
|
|
31
|
+
- `bodyJson`: Body as JS Object.
|
|
32
|
+
- `queryParameters`: URL Query Parameters as JS Object.
|
|
33
|
+
- `timeout`: A timeout in ms for the fetch request (default `5000`ms).
|
|
34
|
+
- `retry`: If fetch response not acceptable or timed out, it will retry the request (default `3`).
|
|
35
|
+
- `cacheStorageName`: Cache storage name (default `alwatr_fetch_cache`).
|
|
36
|
+
- `cacheStrategy`: Strategies for caching, (default `network_only`).
|
|
37
|
+
- `network_only`: Only network request without any cache.
|
|
38
|
+
- `network_first`: Network first, falling back to cache.
|
|
39
|
+
- `cache_only`: Cache only without any network request.
|
|
40
|
+
- `cache_first`: Cache first, falling back to network.
|
|
41
|
+
- `stale_while_revalidate`: Fastest strategy, Use cached first but always request network to update the cache.
|
|
42
|
+
|
|
43
|
+
[Read more about standard cache strategies](https://developer.chrome.com/docs/workbox/caching-strategies-overview/#caching-strategies)
|
|
44
|
+
|
|
45
|
+
## API
|
|
46
|
+
|
|
47
|
+
### `fetch(options: FetchOptions): Promise<Response>`
|
|
48
|
+
|
|
49
|
+
It's a wrapper around the browser's `fetch` function that adds retry pattern with timeout and cacheStrategy.
|
|
50
|
+
|
|
51
|
+
```ts
|
|
52
|
+
const response = await fetch({
|
|
53
|
+
url: '/api/products',
|
|
54
|
+
queryParameters: {limit: 10},
|
|
55
|
+
timeout: 5_000,
|
|
56
|
+
retry: 3,
|
|
57
|
+
cacheStrategy: 'stale_while_revalidate',
|
|
58
|
+
});
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### `getJson<T>(options: FetchOptions): Promise<T>`
|
|
62
|
+
|
|
63
|
+
It fetches a JSON file from a URL, and returns the parsed data.
|
|
18
64
|
|
|
19
|
-
|
|
65
|
+
```ts
|
|
66
|
+
const productList = await getJson<ProductResponse>({
|
|
67
|
+
url: '/api/products',
|
|
68
|
+
queryParameters: {limit: 10},
|
|
69
|
+
timeout: 5_000,
|
|
70
|
+
retry: 3,
|
|
71
|
+
cacheStrategy: 'stale_while_revalidate',
|
|
72
|
+
});
|
|
20
73
|
```
|
package/fetch.d.ts
CHANGED
|
@@ -3,35 +3,79 @@ declare global {
|
|
|
3
3
|
abort(reason?: string): void;
|
|
4
4
|
}
|
|
5
5
|
}
|
|
6
|
+
export declare type CacheStrategy = 'network_only' | 'network_first' | 'cache_only' | 'cache_first' | 'stale_while_revalidate';
|
|
6
7
|
export interface FetchOptions extends RequestInit {
|
|
7
8
|
/**
|
|
8
|
-
*
|
|
9
|
+
* Request URL.
|
|
10
|
+
*/
|
|
11
|
+
url: string;
|
|
12
|
+
/**
|
|
13
|
+
* A timeout for the fetch request.
|
|
14
|
+
*
|
|
15
|
+
* @default 5000 ms
|
|
16
|
+
*/
|
|
17
|
+
timeout: number;
|
|
18
|
+
/**
|
|
19
|
+
* If fetch response not acceptable or timed out, it will retry the request.
|
|
20
|
+
*
|
|
21
|
+
* @default 3
|
|
22
|
+
*/
|
|
23
|
+
retry: number;
|
|
24
|
+
/**
|
|
25
|
+
* Strategies for caching.
|
|
26
|
+
*
|
|
27
|
+
* @default 'network_only'
|
|
28
|
+
*/
|
|
29
|
+
cacheStrategy: CacheStrategy;
|
|
30
|
+
/**
|
|
31
|
+
* Cache storage name.
|
|
32
|
+
*
|
|
33
|
+
* @default 'alwatr_fetch_cache'
|
|
34
|
+
*/
|
|
35
|
+
cacheStorageName: string;
|
|
36
|
+
/**
|
|
37
|
+
* Body as JS Object.
|
|
38
|
+
*/
|
|
39
|
+
bodyJson?: Record<string | number, unknown>;
|
|
40
|
+
/**
|
|
41
|
+
* URL Query Parameters as JS Object.
|
|
9
42
|
*/
|
|
10
|
-
timeout?: number;
|
|
11
|
-
bodyObject?: Record<string | number, unknown>;
|
|
12
43
|
queryParameters?: Record<string, string | number | boolean>;
|
|
13
44
|
}
|
|
14
45
|
/**
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
* const productList = await getJson('/api/products', {limit: 10}, {timeout: 5_000});
|
|
46
|
+
* It's a wrapper around the browser's `fetch` function that adds retry pattern with timeout and cacheStrategy.
|
|
47
|
+
*
|
|
48
|
+
* Example:
|
|
49
|
+
*
|
|
50
|
+
* ```ts
|
|
51
|
+
* const response = await fetch({
|
|
52
|
+
* url: '/api/products',
|
|
53
|
+
* queryParameters: {limit: 10},
|
|
54
|
+
* timeout: 5_000,
|
|
55
|
+
* retry: 3,
|
|
56
|
+
* cacheStrategy: 'stale_while_revalidate',
|
|
57
|
+
* });
|
|
58
|
+
* ```
|
|
29
59
|
*/
|
|
30
|
-
export declare function
|
|
60
|
+
export declare function fetch(_options: Partial<FetchOptions> & {
|
|
61
|
+
url: string;
|
|
62
|
+
}): Promise<Response>;
|
|
31
63
|
/**
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
64
|
+
* It fetches a JSON file from a URL, and returns the parsed data.
|
|
65
|
+
*
|
|
66
|
+
* Example:
|
|
67
|
+
*
|
|
68
|
+
* ```ts
|
|
69
|
+
* const productList = await getJson<ProductResponse>({
|
|
70
|
+
* url: '/api/products',
|
|
71
|
+
* queryParameters: {limit: 10},
|
|
72
|
+
* timeout: 5_000,
|
|
73
|
+
* retry: 3,
|
|
74
|
+
* cacheStrategy: 'stale_while_revalidate',
|
|
75
|
+
* });
|
|
76
|
+
* ```
|
|
35
77
|
*/
|
|
36
|
-
export declare function
|
|
78
|
+
export declare function getJson<ResponseType extends Record<string | number, unknown>>(options: Partial<FetchOptions> & {
|
|
79
|
+
url: string;
|
|
80
|
+
}): Promise<ResponseType>;
|
|
37
81
|
//# sourceMappingURL=fetch.d.ts.map
|
package/fetch.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fetch.d.ts","sourceRoot":"","sources":["src/fetch.ts"],"names":[],"mappings":"AASA,OAAO,CAAC,MAAM,CAAC;IAEb,UAAU,eAAe;QACvB,KAAK,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;KAC9B;CACF;
|
|
1
|
+
{"version":3,"file":"fetch.d.ts","sourceRoot":"","sources":["src/fetch.ts"],"names":[],"mappings":"AASA,OAAO,CAAC,MAAM,CAAC;IAEb,UAAU,eAAe;QACvB,KAAK,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;KAC9B;CACF;AAED,oBAAY,aAAa,GAAG,cAAc,GAAG,eAAe,GAAG,YAAY,GAAG,aAAa,GAAG,wBAAwB,CAAC;AAGvH,MAAM,WAAW,YAAa,SAAQ,WAAW;IAC/C;;OAEG;IACH,GAAG,EAAE,MAAM,CAAC;IAEZ;;;;OAIG;IACH,OAAO,EAAE,MAAM,CAAC;IAChB;;;;OAIG;IACH,KAAK,EAAE,MAAM,CAAC;IAEd;;;;OAIG;IACH,aAAa,EAAE,aAAa,CAAC;IAE7B;;;;OAIG;IACH,gBAAgB,EAAE,MAAM,CAAC;IAEzB;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,GAAG,MAAM,EAAE,OAAO,CAAC,CAAC;IAE5C;;OAEG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,CAAC;CAC7D;AAKD;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,KAAK,CAAC,QAAQ,EAAE,OAAO,CAAC,YAAY,CAAC,GAAG;IAAC,GAAG,EAAE,MAAM,CAAA;CAAC,GAAG,OAAO,CAAC,QAAQ,CAAC,CA+D9F;AA6GD;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,OAAO,CAAC,YAAY,SAAS,MAAM,CAAC,MAAM,GAAG,MAAM,EAAE,OAAO,CAAC,EAC/E,OAAO,EAAE,OAAO,CAAC,YAAY,CAAC,GAAG;IAAC,GAAG,EAAE,MAAM,CAAA;CAAC,GAC/C,OAAO,CAAC,YAAY,CAAC,CA6BvB"}
|
package/fetch.js
CHANGED
|
@@ -4,97 +4,210 @@ alwatrRegisteredList.push({
|
|
|
4
4
|
name: '@alwatr/fetch',
|
|
5
5
|
version: '{{ALWATR_VERSION}}',
|
|
6
6
|
});
|
|
7
|
+
let cacheStorage;
|
|
8
|
+
const cacheSupported = 'caches' in self;
|
|
7
9
|
/**
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
+
* It's a wrapper around the browser's `fetch` function that adds retry pattern with timeout and cacheStrategy.
|
|
11
|
+
*
|
|
12
|
+
* Example:
|
|
13
|
+
*
|
|
14
|
+
* ```ts
|
|
15
|
+
* const response = await fetch({
|
|
16
|
+
* url: '/api/products',
|
|
17
|
+
* queryParameters: {limit: 10},
|
|
18
|
+
* timeout: 5_000,
|
|
19
|
+
* retry: 3,
|
|
20
|
+
* cacheStrategy: 'stale_while_revalidate',
|
|
21
|
+
* });
|
|
22
|
+
* ```
|
|
10
23
|
*/
|
|
11
|
-
export function fetch(
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
24
|
+
export async function fetch(_options) {
|
|
25
|
+
const options = _processOptions(_options);
|
|
26
|
+
logger.logMethodArgs('fetch', { options });
|
|
27
|
+
if (options.cacheStrategy === 'network_only') {
|
|
28
|
+
return _fetch(options);
|
|
16
29
|
}
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
30
|
+
// else handle cache strategies!
|
|
31
|
+
if (cacheStorage == null) {
|
|
32
|
+
cacheStorage = await caches.open(options.cacheStorageName);
|
|
33
|
+
}
|
|
34
|
+
const request = new Request(options.url, options);
|
|
35
|
+
switch (options.cacheStrategy) {
|
|
36
|
+
case 'cache_first': {
|
|
37
|
+
const cachedResponse = await cacheStorage.match(request);
|
|
38
|
+
if (cachedResponse != null)
|
|
39
|
+
return cachedResponse;
|
|
40
|
+
const response = await _fetch(options);
|
|
41
|
+
if (response.ok) {
|
|
42
|
+
cacheStorage.put(request, response.clone());
|
|
43
|
+
}
|
|
44
|
+
return response;
|
|
45
|
+
}
|
|
46
|
+
case 'cache_only': {
|
|
47
|
+
const cachedResponse = await cacheStorage.match(request);
|
|
48
|
+
if (cachedResponse == null)
|
|
49
|
+
throw new Error('fetch_cache_not_found');
|
|
50
|
+
return cachedResponse;
|
|
51
|
+
}
|
|
52
|
+
case 'network_first': {
|
|
53
|
+
try {
|
|
54
|
+
const networkResponse = await _fetch(options);
|
|
55
|
+
if (networkResponse.ok) {
|
|
56
|
+
cacheStorage.put(request, networkResponse.clone());
|
|
57
|
+
}
|
|
58
|
+
return networkResponse;
|
|
59
|
+
}
|
|
60
|
+
catch (err) {
|
|
61
|
+
const cachedResponse = await cacheStorage.match(request);
|
|
62
|
+
if (cachedResponse == null)
|
|
63
|
+
throw err;
|
|
64
|
+
return cachedResponse;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
case 'stale_while_revalidate': {
|
|
68
|
+
const cachedResponse = await cacheStorage.match(request);
|
|
69
|
+
const fetchedResponsePromise = _fetch(options).then((networkResponse) => {
|
|
70
|
+
if (networkResponse.ok) {
|
|
71
|
+
cacheStorage.put(request, networkResponse.clone());
|
|
72
|
+
}
|
|
73
|
+
return networkResponse;
|
|
74
|
+
});
|
|
75
|
+
return cachedResponse || fetchedResponsePromise;
|
|
76
|
+
}
|
|
77
|
+
default: {
|
|
78
|
+
return _fetch(options);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
function _processOptions(options) {
|
|
83
|
+
options.method ?? (options.method = 'GET');
|
|
84
|
+
options.window ?? (options.window = null);
|
|
85
|
+
options.timeout ?? (options.timeout = 5000);
|
|
86
|
+
options.retry ?? (options.retry = 3);
|
|
87
|
+
options.cacheStrategy ?? (options.cacheStrategy = 'network_only');
|
|
88
|
+
options.cacheStorageName ?? (options.cacheStorageName = 'alwatr_fetch_cache');
|
|
89
|
+
if (options.cacheStrategy !== 'network_only' && cacheSupported !== true) {
|
|
90
|
+
logger.accident('fetch', 'fetch_cache_strategy_ignore', 'Cache storage not support in this browser', {
|
|
91
|
+
cacheSupported,
|
|
92
|
+
});
|
|
93
|
+
options.cacheStrategy = 'network_only';
|
|
94
|
+
}
|
|
95
|
+
if (options.url.lastIndexOf('?') === -1 && options.queryParameters != null) {
|
|
24
96
|
// prettier-ignore
|
|
25
97
|
const queryArray = Object
|
|
26
98
|
.keys(options.queryParameters)
|
|
27
99
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
28
100
|
.map((key) => `${key}=${String(options.queryParameters[key])}`);
|
|
29
101
|
if (queryArray.length > 0) {
|
|
30
|
-
url += '?' + queryArray.join('&');
|
|
102
|
+
options.url += '?' + queryArray.join('&');
|
|
31
103
|
}
|
|
32
104
|
}
|
|
33
|
-
if (options.
|
|
34
|
-
options.body = JSON.stringify(options.
|
|
105
|
+
if (options.body != null && options.bodyJson != null) {
|
|
106
|
+
options.body = JSON.stringify(options.bodyJson);
|
|
35
107
|
options.headers = {
|
|
36
108
|
...options.headers,
|
|
37
109
|
'Content-Type': 'application/json',
|
|
38
110
|
};
|
|
39
111
|
}
|
|
112
|
+
return options;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* It's a wrapper around the browser's `fetch` function that adds retry pattern with timeout.
|
|
116
|
+
*/
|
|
117
|
+
async function _fetch(options) {
|
|
118
|
+
logger.logMethodArgs('_fetch', { options });
|
|
40
119
|
// @TODO: AbortController polyfill
|
|
41
120
|
const abortController = new AbortController();
|
|
42
121
|
const externalAbortSignal = options.signal;
|
|
122
|
+
options.signal = abortController.signal;
|
|
123
|
+
let timedOut = false;
|
|
124
|
+
const timeoutId = setTimeout(() => {
|
|
125
|
+
abortController.abort('fetch_timeout');
|
|
126
|
+
timedOut = true;
|
|
127
|
+
}, options.timeout);
|
|
43
128
|
if (externalAbortSignal != null) {
|
|
44
129
|
// Respect external abort signal
|
|
45
130
|
externalAbortSignal.addEventListener('abort', () => {
|
|
46
131
|
abortController.abort(`external abort signal: ${externalAbortSignal.reason}`);
|
|
132
|
+
clearTimeout(timeoutId);
|
|
47
133
|
});
|
|
48
134
|
}
|
|
49
135
|
abortController.signal.addEventListener('abort', () => {
|
|
50
|
-
logger.incident('fetch', '
|
|
51
|
-
url,
|
|
136
|
+
logger.incident('fetch', 'fetch_abort_signal', 'fetch abort signal received', {
|
|
52
137
|
reason: abortController.signal.reason,
|
|
53
138
|
});
|
|
54
139
|
});
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
140
|
+
const retryFetch = () => {
|
|
141
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
142
|
+
options.retry--;
|
|
143
|
+
options.signal = externalAbortSignal;
|
|
144
|
+
return fetch(options);
|
|
145
|
+
};
|
|
146
|
+
try {
|
|
147
|
+
// @TODO: browser fetch polyfill
|
|
148
|
+
const response = await window.fetch(options.url, options);
|
|
149
|
+
clearTimeout(timeoutId);
|
|
150
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
151
|
+
if (options.retry > 1 && response.status >= 502 && response.status <= 504) {
|
|
152
|
+
logger.accident('fetch', 'fetch_not_valid', 'fetch not valid and retry', {
|
|
153
|
+
response,
|
|
154
|
+
});
|
|
155
|
+
return retryFetch();
|
|
156
|
+
}
|
|
157
|
+
return response;
|
|
158
|
+
}
|
|
159
|
+
catch (reason) {
|
|
160
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
161
|
+
if (timedOut && options.retry > 1) {
|
|
162
|
+
logger.incident('fetch', 'fetch_timeout', 'fetch timeout and retry', {
|
|
163
|
+
reason,
|
|
164
|
+
});
|
|
165
|
+
return retryFetch();
|
|
166
|
+
}
|
|
167
|
+
else {
|
|
168
|
+
clearTimeout(timeoutId);
|
|
169
|
+
throw reason;
|
|
170
|
+
}
|
|
84
171
|
}
|
|
85
|
-
return response.json();
|
|
86
172
|
}
|
|
87
173
|
/**
|
|
88
|
-
*
|
|
89
|
-
*
|
|
90
|
-
*
|
|
174
|
+
* It fetches a JSON file from a URL, and returns the parsed data.
|
|
175
|
+
*
|
|
176
|
+
* Example:
|
|
177
|
+
*
|
|
178
|
+
* ```ts
|
|
179
|
+
* const productList = await getJson<ProductResponse>({
|
|
180
|
+
* url: '/api/products',
|
|
181
|
+
* queryParameters: {limit: 10},
|
|
182
|
+
* timeout: 5_000,
|
|
183
|
+
* retry: 3,
|
|
184
|
+
* cacheStrategy: 'stale_while_revalidate',
|
|
185
|
+
* });
|
|
186
|
+
* ```
|
|
91
187
|
*/
|
|
92
|
-
export function
|
|
93
|
-
logger.logMethodArgs('
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
188
|
+
export async function getJson(options) {
|
|
189
|
+
logger.logMethodArgs('getJson', { options });
|
|
190
|
+
const response = await fetch(options);
|
|
191
|
+
let data;
|
|
192
|
+
try {
|
|
193
|
+
if (!response.ok) {
|
|
194
|
+
throw new Error('fetch_nok');
|
|
195
|
+
}
|
|
196
|
+
data = (await response.json());
|
|
197
|
+
}
|
|
198
|
+
catch (err) {
|
|
199
|
+
logger.accident('getJson', 'response_json', 'response json error', {
|
|
200
|
+
retry: options.retry,
|
|
201
|
+
err,
|
|
202
|
+
});
|
|
203
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
204
|
+
if (options.retry > 1) {
|
|
205
|
+
data = await getJson(options);
|
|
206
|
+
}
|
|
207
|
+
else {
|
|
208
|
+
throw err;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
return data;
|
|
99
212
|
}
|
|
100
213
|
//# sourceMappingURL=fetch.js.map
|
package/fetch.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fetch.js","sourceRoot":"","sources":["src/fetch.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,YAAY,EAAE,oBAAoB,EAAC,MAAM,gBAAgB,CAAC;AAElE,MAAM,MAAM,GAAG,YAAY,CAAC,cAAc,CAAC,CAAC;AAE5C,oBAAoB,CAAC,IAAI,CAAC;IACxB,IAAI,EAAE,eAAe;IACrB,OAAO,EAAE,oBAAoB;CAC9B,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"fetch.js","sourceRoot":"","sources":["src/fetch.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,YAAY,EAAE,oBAAoB,EAAC,MAAM,gBAAgB,CAAC;AAElE,MAAM,MAAM,GAAG,YAAY,CAAC,cAAc,CAAC,CAAC;AAE5C,oBAAoB,CAAC,IAAI,CAAC;IACxB,IAAI,EAAE,eAAe;IACrB,OAAO,EAAE,oBAAoB;CAC9B,CAAC,CAAC;AAwDH,IAAI,YAAmB,CAAC;AACxB,MAAM,cAAc,GAAG,QAAQ,IAAI,IAAI,CAAC;AAExC;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,KAAK,UAAU,KAAK,CAAC,QAA+C;IACzE,MAAM,OAAO,GAAG,eAAe,CAAC,QAAQ,CAAC,CAAC;IAE1C,MAAM,CAAC,aAAa,CAAC,OAAO,EAAE,EAAC,OAAO,EAAC,CAAC,CAAC;IAEzC,IAAI,OAAO,CAAC,aAAa,KAAK,cAAc,EAAE;QAC5C,OAAO,MAAM,CAAC,OAAO,CAAC,CAAC;KACxB;IACD,gCAAgC;IAEhC,IAAI,YAAY,IAAI,IAAI,EAAE;QACxB,YAAY,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC;KAC5D;IAED,MAAM,OAAO,GAAG,IAAI,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IAElD,QAAQ,OAAO,CAAC,aAAa,EAAE;QAC7B,KAAK,aAAa,CAAC,CAAC;YAClB,MAAM,cAAc,GAAG,MAAM,YAAY,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;YACzD,IAAI,cAAc,IAAI,IAAI;gBAAE,OAAO,cAAc,CAAC;YAClD,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,CAAC;YACvC,IAAI,QAAQ,CAAC,EAAE,EAAE;gBACf,YAAY,CAAC,GAAG,CAAC,OAAO,EAAE,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC;aAC7C;YACD,OAAO,QAAQ,CAAC;SACjB;QAED,KAAK,YAAY,CAAC,CAAC;YACjB,MAAM,cAAc,GAAG,MAAM,YAAY,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;YACzD,IAAI,cAAc,IAAI,IAAI;gBAAE,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAC;YACrE,OAAO,cAAc,CAAC;SACvB;QAED,KAAK,eAAe,CAAC,CAAC;YACpB,IAAI;gBACF,MAAM,eAAe,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,CAAC;gBAC9C,IAAI,eAAe,CAAC,EAAE,EAAE;oBACtB,YAAY,CAAC,GAAG,CAAC,OAAO,EAAE,eAAe,CAAC,KAAK,EAAE,CAAC,CAAC;iBACpD;gBACD,OAAO,eAAe,CAAC;aACxB;YACD,OAAO,GAAG,EAAE;gBACV,MAAM,cAAc,GAAG,MAAM,YAAY,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;gBACzD,IAAI,cAAc,IAAI,IAAI;oBAAE,MAAM,GAAG,CAAC;gBACtC,OAAO,cAAc,CAAC;aACvB;SACF;QAED,KAAK,wBAAwB,CAAC,CAAC;YAC7B,MAAM,cAAc,GAAG,MAAM,YAAY,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;YACzD,MAAM,sBAAsB,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,eAAe,EAAE,EAAE;gBACtE,IAAI,eAAe,CAAC,EAAE,EAAE;oBACtB,YAAY,CAAC,GAAG,CAAC,OAAO,EAAE,eAAe,CAAC,KAAK,EAAE,CAAC,CAAC;iBACpD;gBACD,OAAO,eAAe,CAAC;YACzB,CAAC,CAAC,CAAC;YACH,OAAO,cAAc,IAAI,sBAAsB,CAAC;SACjD;QAED,OAAO,CAAC,CAAC;YACP,OAAO,MAAM,CAAC,OAAO,CAAC,CAAC;SACxB;KACF;AACH,CAAC;AAED,SAAS,eAAe,CAAC,OAA8C;IACrE,OAAO,CAAC,MAAM,KAAd,OAAO,CAAC,MAAM,GAAK,KAAK,EAAC;IACzB,OAAO,CAAC,MAAM,KAAd,OAAO,CAAC,MAAM,GAAK,IAAI,EAAC;IAExB,OAAO,CAAC,OAAO,KAAf,OAAO,CAAC,OAAO,GAAK,IAAK,EAAC;IAC1B,OAAO,CAAC,KAAK,KAAb,OAAO,CAAC,KAAK,GAAK,CAAC,EAAC;IACpB,OAAO,CAAC,aAAa,KAArB,OAAO,CAAC,aAAa,GAAK,cAAc,EAAC;IACzC,OAAO,CAAC,gBAAgB,KAAxB,OAAO,CAAC,gBAAgB,GAAK,oBAAoB,EAAC;IAElD,IAAI,OAAO,CAAC,aAAa,KAAK,cAAc,IAAI,cAAc,KAAK,IAAI,EAAE;QACvE,MAAM,CAAC,QAAQ,CAAC,OAAO,EAAE,6BAA6B,EAAE,2CAA2C,EAAE;YACnG,cAAc;SACf,CAAC,CAAC;QACH,OAAO,CAAC,aAAa,GAAG,cAAc,CAAC;KACxC;IAED,IAAI,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,IAAI,OAAO,CAAC,eAAe,IAAI,IAAI,EAAE;QAC1E,kBAAkB;QAClB,MAAM,UAAU,GAAG,MAAM;aACpB,IAAI,CAAC,OAAO,CAAC,eAAe,CAAC;YAC9B,oEAAoE;aACnE,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,GAAG,IAAI,MAAM,CAAC,OAAO,CAAC,eAAgB,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC;QAErE,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE;YACzB,OAAO,CAAC,GAAG,IAAI,GAAG,GAAG,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;SAC3C;KACF;IAED,IAAI,OAAO,CAAC,IAAI,IAAI,IAAI,IAAI,OAAO,CAAC,QAAQ,IAAI,IAAI,EAAE;QACpD,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QAChD,OAAO,CAAC,OAAO,GAAG;YAChB,GAAG,OAAO,CAAC,OAAO;YAClB,cAAc,EAAE,kBAAkB;SACnC,CAAC;KACH;IAED,OAAO,OAAuB,CAAC;AACjC,CAAC;AAED;;GAEG;AACH,KAAK,UAAU,MAAM,CAAC,OAAqB;IACzC,MAAM,CAAC,aAAa,CAAC,QAAQ,EAAE,EAAC,OAAO,EAAC,CAAC,CAAC;IAE1C,kCAAkC;IAClC,MAAM,eAAe,GAAG,IAAI,eAAe,EAAE,CAAC;IAC9C,MAAM,mBAAmB,GAAG,OAAO,CAAC,MAAM,CAAC;IAC3C,OAAO,CAAC,MAAM,GAAG,eAAe,CAAC,MAAM,CAAC;IAExC,IAAI,QAAQ,GAAG,KAAK,CAAC;IACrB,MAAM,SAAS,GAAG,UAAU,CAAC,GAAG,EAAE;QAChC,eAAe,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC;QACvC,QAAQ,GAAG,IAAI,CAAC;IAClB,CAAC,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;IAEpB,IAAI,mBAAmB,IAAI,IAAI,EAAE;QAC/B,gCAAgC;QAChC,mBAAmB,CAAC,gBAAgB,CAAC,OAAO,EAAE,GAAG,EAAE;YACjD,eAAe,CAAC,KAAK,CAAC,0BAA0B,mBAAmB,CAAC,MAAM,EAAE,CAAC,CAAC;YAC9E,YAAY,CAAC,SAAS,CAAC,CAAC;QAC1B,CAAC,CAAC,CAAC;KACJ;IAED,eAAe,CAAC,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,GAAG,EAAE;QACpD,MAAM,CAAC,QAAQ,CAAC,OAAO,EAAE,oBAAoB,EAAE,6BAA6B,EAAE;YAC5E,MAAM,EAAE,eAAe,CAAC,MAAM,CAAC,MAAM;SACtC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,MAAM,UAAU,GAAG,GAAsB,EAAE;QACzC,oEAAoE;QACpE,OAAO,CAAC,KAAM,EAAE,CAAC;QACjB,OAAO,CAAC,MAAM,GAAG,mBAAmB,CAAC;QACrC,OAAO,KAAK,CAAC,OAAO,CAAC,CAAC;IACxB,CAAC,CAAC;IAEF,IAAI;QACF,gCAAgC;QAChC,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;QAC1D,YAAY,CAAC,SAAS,CAAC,CAAC;QAExB,oEAAoE;QACpE,IAAI,OAAO,CAAC,KAAM,GAAG,CAAC,IAAI,QAAQ,CAAC,MAAM,IAAI,GAAG,IAAI,QAAQ,CAAC,MAAM,IAAI,GAAG,EAAE;YAC1E,MAAM,CAAC,QAAQ,CAAC,OAAO,EAAE,iBAAiB,EAAE,2BAA2B,EAAE;gBACvE,QAAQ;aACT,CAAC,CAAC;YACH,OAAO,UAAU,EAAE,CAAC;SACrB;QAED,OAAO,QAAQ,CAAC;KACjB;IACD,OAAO,MAAM,EAAE;QACb,oEAAoE;QACpE,IAAI,QAAQ,IAAI,OAAO,CAAC,KAAM,GAAG,CAAC,EAAE;YAClC,MAAM,CAAC,QAAQ,CAAC,OAAO,EAAE,eAAe,EAAE,yBAAyB,EAAE;gBACnE,MAAM;aACP,CAAC,CAAC;YACH,OAAO,UAAU,EAAE,CAAC;SACrB;aACI;YACH,YAAY,CAAC,SAAS,CAAC,CAAC;YACxB,MAAM,MAAM,CAAC;SACd;KACF;AACH,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,KAAK,UAAU,OAAO,CACzB,OAA8C;IAEhD,MAAM,CAAC,aAAa,CAAC,SAAS,EAAE,EAAC,OAAO,EAAC,CAAC,CAAC;IAE3C,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,OAAO,CAAC,CAAC;IAEtC,IAAI,IAAkB,CAAC;IAEvB,IAAI;QACF,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE;YAChB,MAAM,IAAI,KAAK,CAAC,WAAW,CAAC,CAAC;SAC9B;QACD,IAAI,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAiB,CAAC;KAChD;IACD,OAAO,GAAG,EAAE;QACV,MAAM,CAAC,QAAQ,CAAC,SAAS,EAAE,eAAe,EAAE,qBAAqB,EAAE;YACjE,KAAK,EAAE,OAAO,CAAC,KAAK;YACpB,GAAG;SACJ,CAAC,CAAC;QAEH,oEAAoE;QACpE,IAAI,OAAO,CAAC,KAAM,GAAG,CAAC,EAAE;YACtB,IAAI,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;SAC/B;aACI;YACH,MAAM,GAAG,CAAC;SACX;KACF;IAED,OAAO,IAAI,CAAC;AACd,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@alwatr/fetch",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Enhanced fetch
|
|
3
|
+
"version": "0.18.0",
|
|
4
|
+
"description": "Enhanced fetch API with cache strategy, retry pattern, timeout, helper methods and enhanced types written in tiny TypeScript, ES module.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"fetch",
|
|
7
7
|
"request",
|
|
8
8
|
"api",
|
|
9
|
+
"retry",
|
|
10
|
+
"cache",
|
|
9
11
|
"timeout",
|
|
10
12
|
"typescript",
|
|
11
13
|
"esm",
|
|
@@ -32,8 +34,8 @@
|
|
|
32
34
|
"url": "https://github.com/AliMD/alwatr/issues"
|
|
33
35
|
},
|
|
34
36
|
"dependencies": {
|
|
35
|
-
"@alwatr/logger": "^0.
|
|
37
|
+
"@alwatr/logger": "^0.18.0",
|
|
36
38
|
"tslib": "^2.3.1"
|
|
37
39
|
},
|
|
38
|
-
"gitHead": "
|
|
40
|
+
"gitHead": "a6f75b381a758849b514ea0d59eec6a3b3444008"
|
|
39
41
|
}
|