@naturalcycles/js-lib 15.32.0 → 15.33.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.
@@ -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 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 = globalThis.fetch) {
403
+ return (await fetchFn(url, init));
405
404
  }
406
405
  async onNotOkResponse(res) {
407
406
  let cause;
@@ -284,7 +284,26 @@ export type FetcherResponseType = 'json' | 'text' | 'void' | 'arrayBuffer' | 'bl
284
284
  * Used to be able to override and provide a different implementation,
285
285
  * e.g when mocking.
286
286
  */
287
- export type FetchFunction = (url: string, init: RequestInitNormalized) => Promise<Response>;
287
+ export type FetchFunction = (url: string, init: RequestInitCrossPlatform) => Promise<ResponseCrossPlatform>;
288
+ /**
289
+ * A subset of RequestInit that would match both:
290
+ *
291
+ * 1. RequestInit from dom types
292
+ * 2. RequestInit from undici types
293
+ */
294
+ export interface RequestInitCrossPlatform {
295
+ method?: string;
296
+ referrer?: string;
297
+ keepalive?: boolean;
298
+ }
299
+ /**
300
+ * A subset of Response type that matches both dom and undici types.
301
+ */
302
+ export interface ResponseCrossPlatform {
303
+ ok: boolean;
304
+ status: number;
305
+ statusText: string;
306
+ }
288
307
  export type GraphQLResponse<DATA> = GraphQLSuccessResponse<DATA> | GraphQLErrorResponse;
289
308
  export interface GraphQLSuccessResponse<DATA> {
290
309
  data: DATA;
@@ -1,4 +1,4 @@
1
- import type { AbortableAsyncMapper, AbortableAsyncPredicate, Promisable } from '../types.js';
1
+ import type { AbortableAsyncMapper, AbortableAsyncPredicate, AbortableMapper, AbortablePredicate, Promisable } from '../types.js';
2
2
  import { END } from '../types.js';
3
3
  /**
4
4
  * Similar to Iterable2, but for AsyncIterable.
@@ -20,8 +20,13 @@ export declare class AsyncIterable2<T> implements AsyncIterable<T> {
20
20
  toArray(): Promise<T[]>;
21
21
  forEach(cb: (v: T, i: number) => Promisable<any | typeof END>): Promise<void>;
22
22
  some(cb: AbortableAsyncPredicate<T>): Promise<boolean>;
23
+ someSync(cb: AbortablePredicate<T>): Promise<boolean>;
23
24
  every(cb: AbortableAsyncPredicate<T>): Promise<boolean>;
25
+ everySync(cb: AbortablePredicate<T>): Promise<boolean>;
24
26
  find(cb: AbortableAsyncPredicate<T>): Promise<T | undefined>;
27
+ findSync(cb: AbortablePredicate<T>): Promise<T | undefined>;
25
28
  filter(cb: AbortableAsyncPredicate<T>): AsyncIterable2<T>;
29
+ filterSync(cb: AbortablePredicate<T>): AsyncIterable2<T>;
26
30
  map<OUT>(mapper: AbortableAsyncMapper<T, OUT>): AsyncIterable2<OUT>;
31
+ mapSync<OUT>(mapper: AbortableMapper<T, OUT>): AsyncIterable2<OUT>;
27
32
  }
@@ -51,6 +51,9 @@ export class AsyncIterable2 {
51
51
  async some(cb) {
52
52
  return !!(await this.find(cb));
53
53
  }
54
+ async someSync(cb) {
55
+ return !!(await this.findSync(cb));
56
+ }
54
57
  async every(cb) {
55
58
  let i = 0;
56
59
  for await (const v of this.it) {
@@ -60,6 +63,15 @@ export class AsyncIterable2 {
60
63
  }
61
64
  return true;
62
65
  }
66
+ async everySync(cb) {
67
+ let i = 0;
68
+ for await (const v of this.it) {
69
+ const r = cb(v, i++);
70
+ if (r === END || !r)
71
+ return false;
72
+ }
73
+ return true;
74
+ }
63
75
  async find(cb) {
64
76
  let i = 0;
65
77
  for await (const v of this.it) {
@@ -70,6 +82,16 @@ export class AsyncIterable2 {
70
82
  return v;
71
83
  }
72
84
  }
85
+ async findSync(cb) {
86
+ let i = 0;
87
+ for await (const v of this.it) {
88
+ const r = cb(v, i++);
89
+ if (r === END)
90
+ return;
91
+ if (r)
92
+ return v;
93
+ }
94
+ }
73
95
  filter(cb) {
74
96
  const { it } = this;
75
97
  return new AsyncIterable2({
@@ -85,6 +107,21 @@ export class AsyncIterable2 {
85
107
  },
86
108
  });
87
109
  }
110
+ filterSync(cb) {
111
+ const { it } = this;
112
+ return new AsyncIterable2({
113
+ async *[Symbol.asyncIterator]() {
114
+ let i = 0;
115
+ for await (const v of it) {
116
+ const r = cb(v, i++);
117
+ if (r === END)
118
+ return;
119
+ if (r)
120
+ yield v;
121
+ }
122
+ },
123
+ });
124
+ }
88
125
  map(mapper) {
89
126
  const { it } = this;
90
127
  return new AsyncIterable2({
@@ -101,4 +138,20 @@ export class AsyncIterable2 {
101
138
  },
102
139
  });
103
140
  }
141
+ mapSync(mapper) {
142
+ const { it } = this;
143
+ return new AsyncIterable2({
144
+ async *[Symbol.asyncIterator]() {
145
+ let i = 0;
146
+ for await (const v of it) {
147
+ const r = mapper(v, i++);
148
+ if (r === END)
149
+ return;
150
+ if (r === SKIP)
151
+ continue;
152
+ yield r;
153
+ }
154
+ },
155
+ });
156
+ }
104
157
  }
package/dist/types.d.ts CHANGED
@@ -114,10 +114,10 @@ export declare const SKIP: unique symbol;
114
114
  */
115
115
  export declare const MISS: unique symbol;
116
116
  /**
117
- * Function which is called for every item in `input`. Expected to return a `Promise` or value.
117
+ * Function which is called for every item in `input`. Expected to return a `Promise`.
118
118
  */
119
- export type AsyncMapper<IN = any, OUT = any> = (input: IN) => OUT | PromiseLike<OUT>;
120
- export type AsyncIndexedMapper<IN = any, OUT = any> = (input: IN, index: number) => OUT | PromiseLike<OUT>;
119
+ export type AsyncMapper<IN = any, OUT = any> = (input: IN) => PromiseLike<OUT>;
120
+ export type AsyncIndexedMapper<IN = any, OUT = any> = (input: IN, index: number) => PromiseLike<OUT>;
121
121
  export type Mapper<IN = any, OUT = any> = (input: IN) => OUT;
122
122
  export type IndexedMapper<IN = any, OUT = any> = (input: IN, index: number) => OUT;
123
123
  export declare const _passthroughMapper: IndexedMapper;
@@ -127,11 +127,11 @@ export declare const _passUndefinedMapper: IndexedMapper<any, void>;
127
127
  */
128
128
  export declare const _noop: (..._args: any[]) => undefined;
129
129
  export type Predicate<T> = (item: T, index: number) => boolean;
130
- export type AsyncPredicate<T> = (item: T, index: number) => boolean | PromiseLike<boolean>;
130
+ export type AsyncPredicate<T> = (item: T, index: number) => PromiseLike<boolean>;
131
131
  export type AbortablePredicate<T> = (item: T, i: number) => boolean | typeof END;
132
- export type AbortableAsyncPredicate<T> = (item: T, i: number) => Promisable<boolean | typeof END>;
132
+ export type AbortableAsyncPredicate<T> = (item: T, i: number) => PromiseLike<boolean | typeof END>;
133
133
  export type AbortableMapper<IN = any, OUT = any> = (input: IN, i: number) => OUT | typeof SKIP | typeof END;
134
- export type AbortableAsyncMapper<IN = any, OUT = any> = (input: IN, i: number) => Promisable<OUT | typeof SKIP | typeof END>;
134
+ export type AbortableAsyncMapper<IN = any, OUT = any> = (input: IN, i: number) => PromiseLike<OUT | typeof SKIP | typeof END>;
135
135
  export declare const _passthroughPredicate: Predicate<any>;
136
136
  export declare const _passNothingPredicate: Predicate<any>;
137
137
  export interface BatchResult<RES = any, ERR = Error> {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@naturalcycles/js-lib",
3
3
  "type": "module",
4
- "version": "15.32.0",
4
+ "version": "15.33.1",
5
5
  "dependencies": {
6
6
  "tslib": "^2",
7
7
  "undici": "^7",
@@ -364,7 +364,31 @@ export type FetcherResponseType =
364
364
  * Used to be able to override and provide a different implementation,
365
365
  * e.g when mocking.
366
366
  */
367
- export type FetchFunction = (url: string, init: RequestInitNormalized) => Promise<Response>
367
+ export type FetchFunction = (
368
+ url: string,
369
+ init: RequestInitCrossPlatform,
370
+ ) => Promise<ResponseCrossPlatform>
371
+
372
+ /**
373
+ * A subset of RequestInit that would match both:
374
+ *
375
+ * 1. RequestInit from dom types
376
+ * 2. RequestInit from undici types
377
+ */
378
+ export interface RequestInitCrossPlatform {
379
+ method?: string
380
+ referrer?: string
381
+ keepalive?: boolean
382
+ }
383
+
384
+ /**
385
+ * A subset of Response type that matches both dom and undici types.
386
+ */
387
+ export interface ResponseCrossPlatform {
388
+ ok: boolean
389
+ status: number
390
+ statusText: string
391
+ }
368
392
 
369
393
  export type GraphQLResponse<DATA> = GraphQLSuccessResponse<DATA> | GraphQLErrorResponse
370
394
 
@@ -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,11 +370,7 @@ 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)(
374
- req.fullUrl,
375
- req.init,
376
- )
373
+ res.fetchResponse = await Fetcher.callNativeFetch(req.fullUrl, req.init, this.cfg.fetchFn)
377
374
  res.ok = res.fetchResponse.ok
378
375
  // important to set it to undefined, otherwise it can keep the previous value (from previous try)
379
376
  res.err = undefined
@@ -502,8 +499,12 @@ export class Fetcher {
502
499
  * This method exists to be able to easily mock it.
503
500
  * It is static, so mocking applies to ALL instances (even future ones) of Fetcher at once.
504
501
  */
505
- static async callNativeFetch(url: string, init: RequestInitNormalized): Promise<Response> {
506
- return await globalThis.fetch(url, init)
502
+ static async callNativeFetch(
503
+ url: string,
504
+ init: RequestInitNormalized,
505
+ fetchFn: FetchFunction = globalThis.fetch,
506
+ ): Promise<Response> {
507
+ return (await fetchFn(url, init)) as Response
507
508
  }
508
509
 
509
510
  private async onNotOkResponse(res: FetcherResponse): Promise<void> {
@@ -1,4 +1,10 @@
1
- import type { AbortableAsyncMapper, AbortableAsyncPredicate, Promisable } from '../types.js'
1
+ import type {
2
+ AbortableAsyncMapper,
3
+ AbortableAsyncPredicate,
4
+ AbortableMapper,
5
+ AbortablePredicate,
6
+ Promisable,
7
+ } from '../types.js'
2
8
  import { END, SKIP } from '../types.js'
3
9
 
4
10
  /**
@@ -58,6 +64,10 @@ export class AsyncIterable2<T> implements AsyncIterable<T> {
58
64
  return !!(await this.find(cb))
59
65
  }
60
66
 
67
+ async someSync(cb: AbortablePredicate<T>): Promise<boolean> {
68
+ return !!(await this.findSync(cb))
69
+ }
70
+
61
71
  async every(cb: AbortableAsyncPredicate<T>): Promise<boolean> {
62
72
  let i = 0
63
73
  for await (const v of this.it) {
@@ -67,6 +77,15 @@ export class AsyncIterable2<T> implements AsyncIterable<T> {
67
77
  return true
68
78
  }
69
79
 
80
+ async everySync(cb: AbortablePredicate<T>): Promise<boolean> {
81
+ let i = 0
82
+ for await (const v of this.it) {
83
+ const r = cb(v, i++)
84
+ if (r === END || !r) return false
85
+ }
86
+ return true
87
+ }
88
+
70
89
  async find(cb: AbortableAsyncPredicate<T>): Promise<T | undefined> {
71
90
  let i = 0
72
91
  for await (const v of this.it) {
@@ -76,6 +95,15 @@ export class AsyncIterable2<T> implements AsyncIterable<T> {
76
95
  }
77
96
  }
78
97
 
98
+ async findSync(cb: AbortablePredicate<T>): Promise<T | undefined> {
99
+ let i = 0
100
+ for await (const v of this.it) {
101
+ const r = cb(v, i++)
102
+ if (r === END) return
103
+ if (r) return v
104
+ }
105
+ }
106
+
79
107
  filter(cb: AbortableAsyncPredicate<T>): AsyncIterable2<T> {
80
108
  const { it } = this
81
109
 
@@ -91,6 +119,21 @@ export class AsyncIterable2<T> implements AsyncIterable<T> {
91
119
  })
92
120
  }
93
121
 
122
+ filterSync(cb: AbortablePredicate<T>): AsyncIterable2<T> {
123
+ const { it } = this
124
+
125
+ return new AsyncIterable2<T>({
126
+ async *[Symbol.asyncIterator]() {
127
+ let i = 0
128
+ for await (const v of it) {
129
+ const r = cb(v, i++)
130
+ if (r === END) return
131
+ if (r) yield v
132
+ }
133
+ },
134
+ })
135
+ }
136
+
94
137
  map<OUT>(mapper: AbortableAsyncMapper<T, OUT>): AsyncIterable2<OUT> {
95
138
  const { it } = this
96
139
 
@@ -106,4 +149,20 @@ export class AsyncIterable2<T> implements AsyncIterable<T> {
106
149
  },
107
150
  })
108
151
  }
152
+
153
+ mapSync<OUT>(mapper: AbortableMapper<T, OUT>): AsyncIterable2<OUT> {
154
+ const { it } = this
155
+
156
+ return new AsyncIterable2<OUT>({
157
+ async *[Symbol.asyncIterator]() {
158
+ let i = 0
159
+ for await (const v of it) {
160
+ const r = mapper(v, i++)
161
+ if (r === END) return
162
+ if (r === SKIP) continue
163
+ yield r
164
+ }
165
+ },
166
+ })
167
+ }
109
168
  }
package/src/types.ts CHANGED
@@ -141,13 +141,10 @@ export const SKIP = Symbol('SKIP')
141
141
  export const MISS = Symbol('MISS')
142
142
 
143
143
  /**
144
- * Function which is called for every item in `input`. Expected to return a `Promise` or value.
144
+ * Function which is called for every item in `input`. Expected to return a `Promise`.
145
145
  */
146
- export type AsyncMapper<IN = any, OUT = any> = (input: IN) => OUT | PromiseLike<OUT>
147
- export type AsyncIndexedMapper<IN = any, OUT = any> = (
148
- input: IN,
149
- index: number,
150
- ) => OUT | PromiseLike<OUT>
146
+ export type AsyncMapper<IN = any, OUT = any> = (input: IN) => PromiseLike<OUT>
147
+ export type AsyncIndexedMapper<IN = any, OUT = any> = (input: IN, index: number) => PromiseLike<OUT>
151
148
  export type Mapper<IN = any, OUT = any> = (input: IN) => OUT
152
149
  export type IndexedMapper<IN = any, OUT = any> = (input: IN, index: number) => OUT
153
150
 
@@ -160,10 +157,10 @@ export const _passUndefinedMapper: IndexedMapper<any, void> = () => undefined
160
157
  export const _noop = (..._args: any[]): undefined => undefined
161
158
 
162
159
  export type Predicate<T> = (item: T, index: number) => boolean
163
- export type AsyncPredicate<T> = (item: T, index: number) => boolean | PromiseLike<boolean>
160
+ export type AsyncPredicate<T> = (item: T, index: number) => PromiseLike<boolean>
164
161
 
165
162
  export type AbortablePredicate<T> = (item: T, i: number) => boolean | typeof END
166
- export type AbortableAsyncPredicate<T> = (item: T, i: number) => Promisable<boolean | typeof END>
163
+ export type AbortableAsyncPredicate<T> = (item: T, i: number) => PromiseLike<boolean | typeof END>
167
164
  export type AbortableMapper<IN = any, OUT = any> = (
168
165
  input: IN,
169
166
  i: number,
@@ -171,7 +168,7 @@ export type AbortableMapper<IN = any, OUT = any> = (
171
168
  export type AbortableAsyncMapper<IN = any, OUT = any> = (
172
169
  input: IN,
173
170
  i: number,
174
- ) => Promisable<OUT | typeof SKIP | typeof END>
171
+ ) => PromiseLike<OUT | typeof SKIP | typeof END>
175
172
 
176
173
  export const _passthroughPredicate: Predicate<any> = () => true
177
174
  export const _passNothingPredicate: Predicate<any> = () => false