@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 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.16.0](https://github.com/AliMD/alwatr/compare/v0.15.0...v0.16.0) (2022-09-08)
6
+ # [0.18.0](https://github.com/AliMD/alwatr/compare/v0.17.0...v0.18.0) (2022-10-22)
7
7
 
8
- **Note:** Version bump only for package @alwatr/fetch
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 the timeout, helper methods, and types written in tiny TypeScript, ES module.
3
+ Enhanced fetch API with cache strategy, retry pattern, timeout, helper methods and enhanced types written in tiny TypeScript, ES module.
4
4
 
5
- ## Options
5
+ ## Example usage
6
6
 
7
- `Options` inherited from the `RequestInit`. you can watch all documents of the parameters RequestInit in [`fetch init parameters`](https://developer.mozilla.org/en-US/docs/Web/API/fetch#parameters)
7
+ ```ts
8
+ import {getJson} from 'https://esm.run/@alwatr/fetch';
8
9
 
9
- Options have two other parameters:
10
+ interface ProductInterface {
11
+ _id: string;
12
+ name: string;
13
+ description: string;
14
+ image: string;
15
+ }
10
16
 
11
- - `bodyObject`: a JSON object that converts to string and put on the body.
12
- - `queryParameters`: a JSON object that converts to URL query params
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
- ## Example usage
26
+ ## Fetch Options
15
27
 
16
- ```js
17
- import {getJson} from 'https://esm.run/@alwatr/fetch';
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
- const productList = await getJson('/api/products', {limit: 10}, {timeout: 5_000});
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
- * @default 10_000 ms
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
- * Enhanced base fetch API.
16
- * @example const response = await fetch(url, {jsonResponse: false});
17
- */
18
- export declare function fetch(url: string, options?: FetchOptions): Promise<Response>;
19
- /**
20
- * Enhanced get data.
21
- * @example
22
- * const response = await postData('/api/products', {limit: 10}, {timeout: 5_000});
23
- */
24
- export declare function getData(url: string, queryParameters?: Record<string | number, string | number | boolean>, options?: FetchOptions): Promise<Response>;
25
- /**
26
- * Enhanced fetch JSON.
27
- * @example
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 getJson<ResponseType extends Record<string | number, unknown>>(url: string, queryParameters?: Record<string | number, string | number | boolean>, options?: FetchOptions): Promise<ResponseType>;
60
+ export declare function fetch(_options: Partial<FetchOptions> & {
61
+ url: string;
62
+ }): Promise<Response>;
31
63
  /**
32
- * Enhanced post json data.
33
- * @example
34
- * const response = await postData('/api/product/new', {name: 'foo', ...});
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 postData(url: string, body: Record<string | number, unknown>, options?: FetchOptions): Promise<Response>;
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;AAGD,MAAM,WAAW,YAAa,SAAQ,WAAW;IAC/C;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,GAAG,MAAM,EAAE,OAAO,CAAC,CAAC;IAC9C,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,CAAC;CAC7D;AAED;;;GAGG;AACH,wBAAgB,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,QAAQ,CAAC,CA0D5E;AAED;;;;GAIG;AACH,wBAAgB,OAAO,CACnB,GAAG,EAAE,MAAM,EACX,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,GAAG,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,EACpE,OAAO,CAAC,EAAE,YAAY,GACvB,OAAO,CAAC,QAAQ,CAAC,CAMnB;AAED;;;;GAIG;AACH,wBAAsB,OAAO,CAAC,YAAY,SAAS,MAAM,CAAC,MAAM,GAAG,MAAM,EAAE,OAAO,CAAC,EAC/E,GAAG,EAAE,MAAM,EACX,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,GAAG,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,EACpE,OAAO,CAAC,EAAE,YAAY,GACvB,OAAO,CAAC,YAAY,CAAC,CASvB;AAED;;;;GAIG;AACH,wBAAgB,QAAQ,CACpB,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,MAAM,CAAC,MAAM,GAAG,MAAM,EAAE,OAAO,CAAC,EACtC,OAAO,CAAC,EAAE,YAAY,GACvB,OAAO,CAAC,QAAQ,CAAC,CAOnB"}
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
- * Enhanced base fetch API.
9
- * @example const response = await fetch(url, {jsonResponse: false});
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(url, options) {
12
- logger.logMethodArgs('fetch', { url, options });
13
- if (!navigator.onLine) {
14
- logger.accident('fetch', 'abort_signal', 'abort signal received', { url });
15
- throw new Error('fetch_offline');
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
- options = {
18
- method: 'GET',
19
- timeout: 15000,
20
- window: null,
21
- ...options,
22
- };
23
- if (options.queryParameters != null) {
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.bodyObject != null) {
34
- options.body = JSON.stringify(options.bodyObject);
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', 'abort_signal', 'abort signal received', {
51
- url,
136
+ logger.incident('fetch', 'fetch_abort_signal', 'fetch abort signal received', {
52
137
  reason: abortController.signal.reason,
53
138
  });
54
139
  });
55
- options.signal = abortController.signal;
56
- const timeoutId = setTimeout(() => abortController.abort('fetch_timeout'), options.timeout);
57
- // @TODO: browser fetch polyfill
58
- const response = window.fetch(url, options);
59
- response.then(() => clearTimeout(timeoutId));
60
- return response;
61
- }
62
- /**
63
- * Enhanced get data.
64
- * @example
65
- * const response = await postData('/api/products', {limit: 10}, {timeout: 5_000});
66
- */
67
- export function getData(url, queryParameters, options) {
68
- logger.logMethodArgs('getData', { url, queryParameters, options });
69
- return fetch(url, {
70
- queryParameters,
71
- ...options,
72
- });
73
- }
74
- /**
75
- * Enhanced fetch JSON.
76
- * @example
77
- * const productList = await getJson('/api/products', {limit: 10}, {timeout: 5_000});
78
- */
79
- export async function getJson(url, queryParameters, options) {
80
- logger.logMethodArgs('getJson', { url, queryParameters, options });
81
- const response = await getData(url, queryParameters, options);
82
- if (!response.ok) {
83
- throw new Error('fetch_nok');
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
- * Enhanced post json data.
89
- * @example
90
- * const response = await postData('/api/product/new', {name: 'foo', ...});
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 postData(url, body, options) {
93
- logger.logMethodArgs('postData', { url, body, options });
94
- return fetch(url, {
95
- method: 'POST',
96
- bodyObject: body,
97
- ...options,
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":"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"}
1
+ {"version":3,"file":"fetch.js","sourceRoot":"","sources":["src/fetch.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,11 +1,13 @@
1
1
  {
2
2
  "name": "@alwatr/fetch",
3
- "version": "0.16.0",
4
- "description": "Enhanced fetch api with timeout, helper methods and types written in tiny TypeScript module.",
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.16.0",
37
+ "@alwatr/logger": "^0.18.0",
36
38
  "tslib": "^2.3.1"
37
39
  },
38
- "gitHead": "403b42f686edc84c4a3021b40f5b05dce0289f12"
40
+ "gitHead": "a6f75b381a758849b514ea0d59eec6a3b3444008"
39
41
  }