@naturalcycles/js-lib 15.33.0 → 15.33.2

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.
@@ -4,7 +4,7 @@
4
4
  import type { ReadableStream as WebReadableStream } from 'node:stream/web';
5
5
  import { HttpRequestError } from '../error/error.util.js';
6
6
  import type { ErrorDataTuple } from '../types.js';
7
- import type { FetcherAfterResponseHook, FetcherBeforeRequestHook, FetcherBeforeRetryHook, FetcherCfg, FetcherGraphQLOptions, FetcherNormalizedCfg, FetcherOnErrorHook, FetcherOptions, FetcherResponse, RequestInitNormalized } from './fetcher.model.js';
7
+ import type { FetcherAfterResponseHook, FetcherBeforeRequestHook, FetcherBeforeRetryHook, FetcherCfg, FetcherGraphQLOptions, FetcherNormalizedCfg, FetcherOnErrorHook, FetcherOptions, FetcherResponse, FetchFunction, RequestInitNormalized } from './fetcher.model.js';
8
8
  /**
9
9
  * Experimental wrapper around Fetch.
10
10
  * Works in both Browser and Node, using `globalThis.fetch`.
@@ -92,7 +92,7 @@ export declare class Fetcher {
92
92
  * This method exists to be able to easily mock it.
93
93
  * It is static, so mocking applies to ALL instances (even future ones) of Fetcher at once.
94
94
  */
95
- static callNativeFetch(url: string, init: RequestInitNormalized): Promise<Response>;
95
+ static callNativeFetch(url: string, init: RequestInitNormalized, fetchFn?: FetchFunction): Promise<Response>;
96
96
  private onNotOkResponse;
97
97
  private processRetry;
98
98
  private getRetryTimeout;
@@ -283,8 +283,7 @@ export class Fetcher {
283
283
  }
284
284
  }
285
285
  try {
286
- // Calls cfg.fetchFn if set, otherwise Fetcher.callNativeFetch
287
- res.fetchResponse = await (this.cfg.fetchFn || Fetcher.callNativeFetch)(req.fullUrl, req.init);
286
+ res.fetchResponse = await (this.cfg.overrideFetchFn || Fetcher.callNativeFetch)(req.fullUrl, req.init, this.cfg.fetchFn);
288
287
  res.ok = res.fetchResponse.ok;
289
288
  // important to set it to undefined, otherwise it can keep the previous value (from previous try)
290
289
  res.err = undefined;
@@ -400,8 +399,8 @@ export class Fetcher {
400
399
  * This method exists to be able to easily mock it.
401
400
  * It is static, so mocking applies to ALL instances (even future ones) of Fetcher at once.
402
401
  */
403
- static async callNativeFetch(url, init) {
404
- return await globalThis.fetch(url, init);
402
+ static async callNativeFetch(url, init, fetchFn) {
403
+ return await (fetchFn || globalThis.fetch)(url, init);
405
404
  }
406
405
  async onNotOkResponse(res) {
407
406
  let cause;
@@ -227,9 +227,23 @@ export interface FetcherOptions {
227
227
  */
228
228
  debug?: boolean;
229
229
  /**
230
- * If provided - will be used instead of static `Fetcher.callNativeFetch`.
230
+ * If provided - will be used instead of `globalThis.fetch`.
231
+ * Can be used e.g to pass a `fetch` function from `undici` (in Node.js).
232
+ *
233
+ * This function IS called from `Fetcher.callNativeFetch`, so
234
+ * when `callNativeFetch` is mocked - fetchFn is NOT called.
231
235
  */
232
236
  fetchFn?: FetchFunction;
237
+ /**
238
+ * Allows to provide a fetch function that is NOT mocked by `Fetcher.callNativeFetch`.
239
+ *
240
+ * By default - consider `fetchFn`, that's what you would need most of the time.
241
+ *
242
+ * If you want to pass a fetch function that is NOT mockable - use `overrideFetchFn`.
243
+ * Example of where it is useful: in backend resourceTestService, which still needs to call
244
+ * native fetch, while allowing unit tests' fetch calls to be mocked.
245
+ */
246
+ overrideFetchFn?: FetchFunction;
233
247
  /**
234
248
  * Default to true.
235
249
  * Set to false to not throw on `!Response.ok`, but simply return `Response.body` as-is (json parsed, etc).
@@ -284,7 +298,26 @@ export type FetcherResponseType = 'json' | 'text' | 'void' | 'arrayBuffer' | 'bl
284
298
  * Used to be able to override and provide a different implementation,
285
299
  * e.g when mocking.
286
300
  */
287
- export type FetchFunction = (url: string, init: RequestInitNormalized) => Promise<Response>;
301
+ export type FetchFunction = (url: string, init: RequestInit) => Promise<Response>;
302
+ /**
303
+ * A subset of RequestInit that would match both:
304
+ *
305
+ * 1. RequestInit from dom types
306
+ * 2. RequestInit from undici types
307
+ */
308
+ export interface RequestInitLike {
309
+ method?: string;
310
+ referrer?: string;
311
+ keepalive?: boolean;
312
+ }
313
+ /**
314
+ * A subset of Response type that matches both dom and undici types.
315
+ */
316
+ export interface ResponseLike {
317
+ ok: boolean;
318
+ status: number;
319
+ statusText: string;
320
+ }
288
321
  export type GraphQLResponse<DATA> = GraphQLSuccessResponse<DATA> | GraphQLErrorResponse;
289
322
  export interface GraphQLSuccessResponse<DATA> {
290
323
  data: DATA;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@naturalcycles/js-lib",
3
3
  "type": "module",
4
- "version": "15.33.0",
4
+ "version": "15.33.2",
5
5
  "dependencies": {
6
6
  "tslib": "^2",
7
7
  "undici": "^7",
@@ -13,7 +13,7 @@
13
13
  "@types/semver": "^7",
14
14
  "crypto-js": "^4",
15
15
  "dayjs": "^1",
16
- "@naturalcycles/dev-lib": "19.37.0"
16
+ "@naturalcycles/dev-lib": "18.4.2"
17
17
  },
18
18
  "exports": {
19
19
  ".": "./dist/index.js",
@@ -290,10 +290,25 @@ export interface FetcherOptions {
290
290
  debug?: boolean
291
291
 
292
292
  /**
293
- * If provided - will be used instead of static `Fetcher.callNativeFetch`.
293
+ * If provided - will be used instead of `globalThis.fetch`.
294
+ * Can be used e.g to pass a `fetch` function from `undici` (in Node.js).
295
+ *
296
+ * This function IS called from `Fetcher.callNativeFetch`, so
297
+ * when `callNativeFetch` is mocked - fetchFn is NOT called.
294
298
  */
295
299
  fetchFn?: FetchFunction
296
300
 
301
+ /**
302
+ * Allows to provide a fetch function that is NOT mocked by `Fetcher.callNativeFetch`.
303
+ *
304
+ * By default - consider `fetchFn`, that's what you would need most of the time.
305
+ *
306
+ * If you want to pass a fetch function that is NOT mockable - use `overrideFetchFn`.
307
+ * Example of where it is useful: in backend resourceTestService, which still needs to call
308
+ * native fetch, while allowing unit tests' fetch calls to be mocked.
309
+ */
310
+ overrideFetchFn?: FetchFunction
311
+
297
312
  /**
298
313
  * Default to true.
299
314
  * Set to false to not throw on `!Response.ok`, but simply return `Response.body` as-is (json parsed, etc).
@@ -364,7 +379,28 @@ export type FetcherResponseType =
364
379
  * Used to be able to override and provide a different implementation,
365
380
  * e.g when mocking.
366
381
  */
367
- export type FetchFunction = (url: string, init: RequestInitNormalized) => Promise<Response>
382
+ export type FetchFunction = (url: string, init: RequestInit) => Promise<Response>
383
+
384
+ /**
385
+ * A subset of RequestInit that would match both:
386
+ *
387
+ * 1. RequestInit from dom types
388
+ * 2. RequestInit from undici types
389
+ */
390
+ export interface RequestInitLike {
391
+ method?: string
392
+ referrer?: string
393
+ keepalive?: boolean
394
+ }
395
+
396
+ /**
397
+ * A subset of Response type that matches both dom and undici types.
398
+ */
399
+ export interface ResponseLike {
400
+ ok: boolean
401
+ status: number
402
+ statusText: string
403
+ }
368
404
 
369
405
  export type GraphQLResponse<DATA> = GraphQLSuccessResponse<DATA> | GraphQLErrorResponse
370
406
 
@@ -49,6 +49,7 @@ import type {
49
49
  FetcherResponse,
50
50
  FetcherResponseType,
51
51
  FetcherRetryOptions,
52
+ FetchFunction,
52
53
  GraphQLResponse,
53
54
  RequestInitNormalized,
54
55
  } from './fetcher.model.js'
@@ -369,10 +370,10 @@ export class Fetcher {
369
370
  }
370
371
 
371
372
  try {
372
- // Calls cfg.fetchFn if set, otherwise Fetcher.callNativeFetch
373
- res.fetchResponse = await (this.cfg.fetchFn || Fetcher.callNativeFetch)(
373
+ res.fetchResponse = await (this.cfg.overrideFetchFn || Fetcher.callNativeFetch)(
374
374
  req.fullUrl,
375
375
  req.init,
376
+ this.cfg.fetchFn,
376
377
  )
377
378
  res.ok = res.fetchResponse.ok
378
379
  // important to set it to undefined, otherwise it can keep the previous value (from previous try)
@@ -502,8 +503,12 @@ export class Fetcher {
502
503
  * This method exists to be able to easily mock it.
503
504
  * It is static, so mocking applies to ALL instances (even future ones) of Fetcher at once.
504
505
  */
505
- static async callNativeFetch(url: string, init: RequestInitNormalized): Promise<Response> {
506
- return await globalThis.fetch(url, init)
506
+ static async callNativeFetch(
507
+ url: string,
508
+ init: RequestInitNormalized,
509
+ fetchFn?: FetchFunction,
510
+ ): Promise<Response> {
511
+ return await (fetchFn || globalThis.fetch)(url, init)
507
512
  }
508
513
 
509
514
  private async onNotOkResponse(res: FetcherResponse): Promise<void> {