@naturalcycles/nodejs-lib 15.28.0 → 15.30.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.
@@ -1,7 +1,7 @@
1
1
  import { type Transform } from 'node:stream';
2
2
  import type { ReadableStream as WebReadableStream } from 'node:stream/web';
3
3
  import { type ZlibOptions } from 'node:zlib';
4
- import type { AbortableAsyncMapper, AsyncIndexedMapper, AsyncPredicate, END, IndexedMapper, NonNegativeInteger, PositiveInteger, Predicate, SKIP } from '@naturalcycles/js-lib/types';
4
+ import { type AbortableAsyncMapper, type AsyncIndexedMapper, type AsyncPredicate, type END, type IndexedMapper, type NonNegativeInteger, type PositiveInteger, type Predicate, type SKIP } from '@naturalcycles/js-lib/types';
5
5
  import type { ReadableTyped, TransformOptions, TransformTyped, WritableTyped } from './stream.model.js';
6
6
  import { type TransformLogProgressOptions } from './transform/transformLogProgress.js';
7
7
  import { type TransformMapOptions } from './transform/transformMap.js';
@@ -63,7 +63,7 @@ export declare class Pipeline<T = unknown> {
63
63
  map<TO>(mapper: AbortableAsyncMapper<T, TO | typeof SKIP | typeof END>, opt?: TransformMapOptions<T, TO>): Pipeline<TO>;
64
64
  mapSync<TO>(mapper: IndexedMapper<T, TO | typeof SKIP | typeof END>, opt?: TransformMapSyncOptions): Pipeline<TO>;
65
65
  mapSimple<TO>(mapper: IndexedMapper<T, TO>, opt?: TransformMapSimpleOptions): Pipeline<TO>;
66
- filter(predicate: AsyncPredicate<T>, opt?: TransformMapOptions): this;
66
+ filter(asyncPredicate: AsyncPredicate<T>, opt?: TransformMapOptions): this;
67
67
  filterSync(predicate: Predicate<T>, opt?: TransformOptions): this;
68
68
  offset(opt: TransformOffsetOptions): this;
69
69
  tap(fn: AsyncIndexedMapper<T, any>, opt?: TransformOptions): this;
@@ -96,7 +96,7 @@ export declare class Pipeline<T = unknown> {
96
96
  toFile(outputFilePath: string): Promise<void>;
97
97
  toNDJsonFile(outputFilePath: string): Promise<void>;
98
98
  to(destination: WritableTyped<T>): Promise<void>;
99
- forEach(fn: AsyncIndexedMapper<T, void>, opt?: TransformMapOptions<T, void>): Promise<void>;
100
- forEachSync(fn: IndexedMapper<T, void>, opt?: TransformMapSyncOptions<T, void>): Promise<void>;
99
+ forEach(fn: AsyncIndexedMapper<T, void>, opt?: TransformMapOptions<T, void> & TransformLogProgressOptions<T>): Promise<void>;
100
+ forEachSync(fn: IndexedMapper<T, void>, opt?: TransformMapSyncOptions<T, void> & TransformLogProgressOptions<T>): Promise<void>;
101
101
  run(): Promise<void>;
102
102
  }
@@ -3,6 +3,7 @@ import { pipeline } from 'node:stream/promises';
3
3
  import { createUnzip } from 'node:zlib';
4
4
  import { createGzip } from 'node:zlib';
5
5
  import { createAbortableSignal } from '@naturalcycles/js-lib';
6
+ import { _passthroughPredicate, } from '@naturalcycles/js-lib/types';
6
7
  import { fs2 } from '../fs/fs2.js';
7
8
  import { createReadStreamAsNDJson } from './ndjson/createReadStreamAsNDJson.js';
8
9
  import { transformJsonParse } from './ndjson/transformJsonParse.js';
@@ -100,6 +101,11 @@ export class Pipeline {
100
101
  * less clean than `.take()` on the source.
101
102
  */
102
103
  limit(limit) {
104
+ if (!this.transforms.length) {
105
+ console.warn(`Pipeline.limit was used as a very first Transfrom - please use Pipeline.limitSource instead`);
106
+ this.limitSource(limit);
107
+ return this;
108
+ }
103
109
  this.transforms.push(transformLimit({
104
110
  limit,
105
111
  signal: this.abortableSignal,
@@ -141,9 +147,9 @@ export class Pipeline {
141
147
  this.transforms.push(transformMapSimple(mapper, opt));
142
148
  return this;
143
149
  }
144
- filter(predicate, opt) {
150
+ filter(asyncPredicate, opt) {
145
151
  this.transforms.push(transformMap(v => v, {
146
- predicate,
152
+ asyncPredicate,
147
153
  ...opt,
148
154
  signal: this.abortableSignal,
149
155
  }));
@@ -270,18 +276,26 @@ export class Pipeline {
270
276
  this.destination = destination;
271
277
  await this.run();
272
278
  }
273
- async forEach(fn, opt) {
279
+ async forEach(fn, opt = {}) {
274
280
  this.transforms.push(transformMap(fn, {
281
+ predicate: opt.logEvery ? _passthroughPredicate : undefined, // for the logger to work
275
282
  ...opt,
276
283
  signal: this.abortableSignal,
277
284
  }));
285
+ if (opt.logEvery) {
286
+ this.transforms.push(transformLogProgress(opt));
287
+ }
278
288
  await this.run();
279
289
  }
280
- async forEachSync(fn, opt) {
290
+ async forEachSync(fn, opt = {}) {
281
291
  this.transforms.push(transformMapSync(fn, {
292
+ predicate: opt.logEvery ? _passthroughPredicate : undefined, // for the logger to work
282
293
  ...opt,
283
294
  signal: this.abortableSignal,
284
295
  }));
296
+ if (opt.logEvery) {
297
+ this.transforms.push(transformLogProgress(opt));
298
+ }
285
299
  await this.run();
286
300
  }
287
301
  async run() {
@@ -4,7 +4,7 @@ import type { TransformMapOptions } from './transformMap.js';
4
4
  /**
5
5
  * Just a convenience wrapper around `transformMap` that has built-in predicate filtering support.
6
6
  */
7
- export declare function transformFilter<IN = any>(predicate: AsyncPredicate<IN>, opt?: TransformMapOptions): TransformTyped<IN, IN>;
7
+ export declare function transformFilter<IN = any>(asyncPredicate: AsyncPredicate<IN>, opt?: TransformMapOptions): TransformTyped<IN, IN>;
8
8
  /**
9
9
  * Sync version of `transformFilter`
10
10
  */
@@ -3,9 +3,9 @@ import { transformMap } from './transformMap.js';
3
3
  /**
4
4
  * Just a convenience wrapper around `transformMap` that has built-in predicate filtering support.
5
5
  */
6
- export function transformFilter(predicate, opt = {}) {
6
+ export function transformFilter(asyncPredicate, opt = {}) {
7
7
  return transformMap(v => v, {
8
- predicate,
8
+ asyncPredicate,
9
9
  ...opt,
10
10
  });
11
11
  }
@@ -4,7 +4,7 @@ import { progressLogger } from '../progressLogger.js';
4
4
  * Pass-through transform that optionally logs progress.
5
5
  */
6
6
  export function transformLogProgress(opt = {}) {
7
- const { objectMode = true, highWaterMark } = opt;
7
+ const { objectMode = true, highWaterMark = 1 } = opt;
8
8
  const progress = progressLogger(opt);
9
9
  return new Transform({
10
10
  objectMode,
@@ -10,7 +10,8 @@ export interface TransformMapOptions<IN = any, OUT = IN> extends TransformOption
10
10
  * Defaults to "pass everything" (including null, undefined, etc).
11
11
  * Simpler way to exclude certain cases is to return SKIP symbol from the mapper.
12
12
  */
13
- predicate?: Predicate<OUT> | AsyncPredicate<OUT>;
13
+ predicate?: Predicate<OUT>;
14
+ asyncPredicate?: AsyncPredicate<OUT>;
14
15
  /**
15
16
  * Number of concurrently pending promises returned by `mapper`.
16
17
  *
@@ -23,7 +23,7 @@ import { PIPELINE_GRACEFUL_ABORT } from '../stream.util.js';
23
23
  */
24
24
  export function transformMap(mapper, opt = {}) {
25
25
  const { concurrency = 16, highWaterMark = 64, predicate, // we now default to "no predicate" (meaning pass-everything)
26
- errorMode = ErrorMode.THROW_IMMEDIATELY, onError, onDone, metric = 'stream', signal, } = opt;
26
+ asyncPredicate, errorMode = ErrorMode.THROW_IMMEDIATELY, onError, onDone, metric = 'stream', signal, } = opt;
27
27
  const started = Date.now();
28
28
  let index = -1;
29
29
  let countOut = 0;
@@ -94,8 +94,20 @@ export function transformMap(mapper, opt = {}) {
94
94
  // do nothing, don't push
95
95
  return cb();
96
96
  }
97
- if (!predicate || ((await predicate(res, currentIndex)) && !isSettled)) {
98
- // isSettled could have happened in parallel, hence the extra check
97
+ if (predicate) {
98
+ if (predicate(res, currentIndex)) {
99
+ countOut++;
100
+ this.push(res);
101
+ }
102
+ }
103
+ else if (asyncPredicate) {
104
+ if ((await asyncPredicate(res, currentIndex)) && !isSettled) {
105
+ // isSettled could have happened in parallel, hence the extra check
106
+ countOut++;
107
+ this.push(res);
108
+ }
109
+ }
110
+ else {
99
111
  countOut++;
100
112
  this.push(res);
101
113
  }
@@ -5,9 +5,10 @@ import { Writable } from 'node:stream';
5
5
  * Put it in the end of your pipeline in case it ends with Transform that needs a consumer.
6
6
  */
7
7
  export function writableVoid(opt = {}) {
8
+ const { objectMode = true, highWaterMark = 1 } = opt;
8
9
  return new Writable({
9
- objectMode: true,
10
- ...opt,
10
+ objectMode,
11
+ highWaterMark,
11
12
  write(_chunk, _, cb) {
12
13
  cb();
13
14
  },
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@naturalcycles/nodejs-lib",
3
3
  "type": "module",
4
- "version": "15.28.0",
4
+ "version": "15.30.0",
5
5
  "dependencies": {
6
6
  "@naturalcycles/js-lib": "^15",
7
7
  "@types/js-yaml": "^4",
@@ -23,7 +23,7 @@
23
23
  },
24
24
  "devDependencies": {
25
25
  "@types/through2-concurrent": "^2",
26
- "@naturalcycles/dev-lib": "19.37.0"
26
+ "@naturalcycles/dev-lib": "18.4.2"
27
27
  },
28
28
  "exports": {
29
29
  ".": "./dist/index.js",
@@ -4,17 +4,18 @@ import type { ReadableStream as WebReadableStream } from 'node:stream/web'
4
4
  import { createUnzip, type ZlibOptions } from 'node:zlib'
5
5
  import { createGzip } from 'node:zlib'
6
6
  import { createAbortableSignal } from '@naturalcycles/js-lib'
7
- import type {
8
- AbortableAsyncMapper,
9
- AsyncIndexedMapper,
10
- AsyncPredicate,
11
- END,
12
- IndexedMapper,
13
- Integer,
14
- NonNegativeInteger,
15
- PositiveInteger,
16
- Predicate,
17
- SKIP,
7
+ import {
8
+ _passthroughPredicate,
9
+ type AbortableAsyncMapper,
10
+ type AsyncIndexedMapper,
11
+ type AsyncPredicate,
12
+ type END,
13
+ type IndexedMapper,
14
+ type Integer,
15
+ type NonNegativeInteger,
16
+ type PositiveInteger,
17
+ type Predicate,
18
+ type SKIP,
18
19
  } from '@naturalcycles/js-lib/types'
19
20
  import { fs2 } from '../fs/fs2.js'
20
21
  import { createReadStreamAsNDJson } from './ndjson/createReadStreamAsNDJson.js'
@@ -139,6 +140,14 @@ export class Pipeline<T = unknown> {
139
140
  * less clean than `.take()` on the source.
140
141
  */
141
142
  limit(limit: NonNegativeInteger | undefined): this {
143
+ if (!this.transforms.length) {
144
+ console.warn(
145
+ `Pipeline.limit was used as a very first Transfrom - please use Pipeline.limitSource instead`,
146
+ )
147
+ this.limitSource(limit)
148
+ return this
149
+ }
150
+
142
151
  this.transforms.push(
143
152
  transformLimit({
144
153
  limit,
@@ -200,10 +209,10 @@ export class Pipeline<T = unknown> {
200
209
  return this as any
201
210
  }
202
211
 
203
- filter(predicate: AsyncPredicate<T>, opt?: TransformMapOptions): this {
212
+ filter(asyncPredicate: AsyncPredicate<T>, opt?: TransformMapOptions): this {
204
213
  this.transforms.push(
205
214
  transformMap(v => v, {
206
- predicate,
215
+ asyncPredicate,
207
216
  ...opt,
208
217
  signal: this.abortableSignal,
209
218
  }),
@@ -362,27 +371,35 @@ export class Pipeline<T = unknown> {
362
371
 
363
372
  async forEach(
364
373
  fn: AsyncIndexedMapper<T, void>,
365
- opt?: TransformMapOptions<T, void>,
374
+ opt: TransformMapOptions<T, void> & TransformLogProgressOptions<T> = {},
366
375
  ): Promise<void> {
367
376
  this.transforms.push(
368
377
  transformMap(fn, {
378
+ predicate: opt.logEvery ? _passthroughPredicate : undefined, // for the logger to work
369
379
  ...opt,
370
380
  signal: this.abortableSignal,
371
381
  }),
372
382
  )
383
+ if (opt.logEvery) {
384
+ this.transforms.push(transformLogProgress(opt))
385
+ }
373
386
  await this.run()
374
387
  }
375
388
 
376
389
  async forEachSync(
377
390
  fn: IndexedMapper<T, void>,
378
- opt?: TransformMapSyncOptions<T, void>,
391
+ opt: TransformMapSyncOptions<T, void> & TransformLogProgressOptions<T> = {},
379
392
  ): Promise<void> {
380
393
  this.transforms.push(
381
394
  transformMapSync(fn, {
395
+ predicate: opt.logEvery ? _passthroughPredicate : undefined, // for the logger to work
382
396
  ...opt,
383
397
  signal: this.abortableSignal,
384
398
  }),
385
399
  )
400
+ if (opt.logEvery) {
401
+ this.transforms.push(transformLogProgress(opt))
402
+ }
386
403
  await this.run()
387
404
  }
388
405
 
@@ -8,11 +8,11 @@ import { transformMap } from './transformMap.js'
8
8
  * Just a convenience wrapper around `transformMap` that has built-in predicate filtering support.
9
9
  */
10
10
  export function transformFilter<IN = any>(
11
- predicate: AsyncPredicate<IN>,
11
+ asyncPredicate: AsyncPredicate<IN>,
12
12
  opt: TransformMapOptions = {},
13
13
  ): TransformTyped<IN, IN> {
14
14
  return transformMap(v => v, {
15
- predicate,
15
+ asyncPredicate,
16
16
  ...opt,
17
17
  })
18
18
  }
@@ -13,7 +13,7 @@ export interface TransformLogProgressOptions<IN = any>
13
13
  export function transformLogProgress<IN = any>(
14
14
  opt: TransformLogProgressOptions = {},
15
15
  ): TransformTyped<IN, IN> {
16
- const { objectMode = true, highWaterMark } = opt
16
+ const { objectMode = true, highWaterMark = 1 } = opt
17
17
  const progress = progressLogger(opt)
18
18
 
19
19
  return new Transform({
@@ -27,7 +27,9 @@ export interface TransformMapOptions<IN = any, OUT = IN> extends TransformOption
27
27
  * Defaults to "pass everything" (including null, undefined, etc).
28
28
  * Simpler way to exclude certain cases is to return SKIP symbol from the mapper.
29
29
  */
30
- predicate?: Predicate<OUT> | AsyncPredicate<OUT>
30
+ predicate?: Predicate<OUT>
31
+
32
+ asyncPredicate?: AsyncPredicate<OUT>
31
33
 
32
34
  /**
33
35
  * Number of concurrently pending promises returned by `mapper`.
@@ -138,6 +140,7 @@ export function transformMap<IN = any, OUT = IN>(
138
140
  concurrency = 16,
139
141
  highWaterMark = 64,
140
142
  predicate, // we now default to "no predicate" (meaning pass-everything)
143
+ asyncPredicate,
141
144
  errorMode = ErrorMode.THROW_IMMEDIATELY,
142
145
  onError,
143
146
  onDone,
@@ -227,8 +230,18 @@ export function transformMap<IN = any, OUT = IN>(
227
230
  return cb()
228
231
  }
229
232
 
230
- if (!predicate || ((await predicate(res, currentIndex)) && !isSettled)) {
231
- // isSettled could have happened in parallel, hence the extra check
233
+ if (predicate) {
234
+ if (predicate(res, currentIndex)) {
235
+ countOut++
236
+ this.push(res)
237
+ }
238
+ } else if (asyncPredicate) {
239
+ if ((await asyncPredicate(res, currentIndex)) && !isSettled) {
240
+ // isSettled could have happened in parallel, hence the extra check
241
+ countOut++
242
+ this.push(res)
243
+ }
244
+ } else {
232
245
  countOut++
233
246
  this.push(res)
234
247
  }
@@ -7,9 +7,10 @@ import type { TransformOptions } from '../stream.model.js'
7
7
  * Put it in the end of your pipeline in case it ends with Transform that needs a consumer.
8
8
  */
9
9
  export function writableVoid(opt: TransformOptions = {}): Writable {
10
+ const { objectMode = true, highWaterMark = 1 } = opt
10
11
  return new Writable({
11
- objectMode: true,
12
- ...opt,
12
+ objectMode,
13
+ highWaterMark,
13
14
  write(_chunk, _, cb) {
14
15
  cb()
15
16
  },