@naturalcycles/nodejs-lib 15.28.0 → 15.29.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/dist/stream/pipeline.d.ts +4 -4
- package/dist/stream/pipeline.js +13 -4
- package/dist/stream/transform/transformFilter.d.ts +1 -1
- package/dist/stream/transform/transformFilter.js +2 -2
- package/dist/stream/transform/transformLogProgress.js +1 -1
- package/dist/stream/transform/transformMap.d.ts +2 -1
- package/dist/stream/transform/transformMap.js +15 -3
- package/dist/stream/writable/writableVoid.js +3 -2
- package/package.json +2 -2
- package/src/stream/pipeline.ts +24 -15
- package/src/stream/transform/transformFilter.ts +2 -2
- package/src/stream/transform/transformLogProgress.ts +1 -1
- package/src/stream/transform/transformMap.ts +16 -3
- package/src/stream/writable/writableVoid.ts +3 -2
|
@@ -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
|
|
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(
|
|
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
|
}
|
package/dist/stream/pipeline.js
CHANGED
|
@@ -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';
|
|
@@ -141,9 +142,9 @@ export class Pipeline {
|
|
|
141
142
|
this.transforms.push(transformMapSimple(mapper, opt));
|
|
142
143
|
return this;
|
|
143
144
|
}
|
|
144
|
-
filter(
|
|
145
|
+
filter(asyncPredicate, opt) {
|
|
145
146
|
this.transforms.push(transformMap(v => v, {
|
|
146
|
-
|
|
147
|
+
asyncPredicate,
|
|
147
148
|
...opt,
|
|
148
149
|
signal: this.abortableSignal,
|
|
149
150
|
}));
|
|
@@ -270,18 +271,26 @@ export class Pipeline {
|
|
|
270
271
|
this.destination = destination;
|
|
271
272
|
await this.run();
|
|
272
273
|
}
|
|
273
|
-
async forEach(fn, opt) {
|
|
274
|
+
async forEach(fn, opt = {}) {
|
|
274
275
|
this.transforms.push(transformMap(fn, {
|
|
276
|
+
predicate: opt.logEvery ? _passthroughPredicate : undefined, // for the logger to work
|
|
275
277
|
...opt,
|
|
276
278
|
signal: this.abortableSignal,
|
|
277
279
|
}));
|
|
280
|
+
if (opt.logEvery) {
|
|
281
|
+
this.transforms.push(transformLogProgress(opt));
|
|
282
|
+
}
|
|
278
283
|
await this.run();
|
|
279
284
|
}
|
|
280
|
-
async forEachSync(fn, opt) {
|
|
285
|
+
async forEachSync(fn, opt = {}) {
|
|
281
286
|
this.transforms.push(transformMapSync(fn, {
|
|
287
|
+
predicate: opt.logEvery ? _passthroughPredicate : undefined, // for the logger to work
|
|
282
288
|
...opt,
|
|
283
289
|
signal: this.abortableSignal,
|
|
284
290
|
}));
|
|
291
|
+
if (opt.logEvery) {
|
|
292
|
+
this.transforms.push(transformLogProgress(opt));
|
|
293
|
+
}
|
|
285
294
|
await this.run();
|
|
286
295
|
}
|
|
287
296
|
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>(
|
|
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(
|
|
6
|
+
export function transformFilter(asyncPredicate, opt = {}) {
|
|
7
7
|
return transformMap(v => v, {
|
|
8
|
-
|
|
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
|
|
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 (
|
|
98
|
-
|
|
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
|
|
10
|
-
|
|
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.
|
|
4
|
+
"version": "15.29.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": "
|
|
26
|
+
"@naturalcycles/dev-lib": "18.4.2"
|
|
27
27
|
},
|
|
28
28
|
"exports": {
|
|
29
29
|
".": "./dist/index.js",
|
package/src/stream/pipeline.ts
CHANGED
|
@@ -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
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
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'
|
|
@@ -200,10 +201,10 @@ export class Pipeline<T = unknown> {
|
|
|
200
201
|
return this as any
|
|
201
202
|
}
|
|
202
203
|
|
|
203
|
-
filter(
|
|
204
|
+
filter(asyncPredicate: AsyncPredicate<T>, opt?: TransformMapOptions): this {
|
|
204
205
|
this.transforms.push(
|
|
205
206
|
transformMap(v => v, {
|
|
206
|
-
|
|
207
|
+
asyncPredicate,
|
|
207
208
|
...opt,
|
|
208
209
|
signal: this.abortableSignal,
|
|
209
210
|
}),
|
|
@@ -362,27 +363,35 @@ export class Pipeline<T = unknown> {
|
|
|
362
363
|
|
|
363
364
|
async forEach(
|
|
364
365
|
fn: AsyncIndexedMapper<T, void>,
|
|
365
|
-
opt
|
|
366
|
+
opt: TransformMapOptions<T, void> & TransformLogProgressOptions<T> = {},
|
|
366
367
|
): Promise<void> {
|
|
367
368
|
this.transforms.push(
|
|
368
369
|
transformMap(fn, {
|
|
370
|
+
predicate: opt.logEvery ? _passthroughPredicate : undefined, // for the logger to work
|
|
369
371
|
...opt,
|
|
370
372
|
signal: this.abortableSignal,
|
|
371
373
|
}),
|
|
372
374
|
)
|
|
375
|
+
if (opt.logEvery) {
|
|
376
|
+
this.transforms.push(transformLogProgress(opt))
|
|
377
|
+
}
|
|
373
378
|
await this.run()
|
|
374
379
|
}
|
|
375
380
|
|
|
376
381
|
async forEachSync(
|
|
377
382
|
fn: IndexedMapper<T, void>,
|
|
378
|
-
opt
|
|
383
|
+
opt: TransformMapSyncOptions<T, void> & TransformLogProgressOptions<T> = {},
|
|
379
384
|
): Promise<void> {
|
|
380
385
|
this.transforms.push(
|
|
381
386
|
transformMapSync(fn, {
|
|
387
|
+
predicate: opt.logEvery ? _passthroughPredicate : undefined, // for the logger to work
|
|
382
388
|
...opt,
|
|
383
389
|
signal: this.abortableSignal,
|
|
384
390
|
}),
|
|
385
391
|
)
|
|
392
|
+
if (opt.logEvery) {
|
|
393
|
+
this.transforms.push(transformLogProgress(opt))
|
|
394
|
+
}
|
|
386
395
|
await this.run()
|
|
387
396
|
}
|
|
388
397
|
|
|
@@ -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
|
-
|
|
11
|
+
asyncPredicate: AsyncPredicate<IN>,
|
|
12
12
|
opt: TransformMapOptions = {},
|
|
13
13
|
): TransformTyped<IN, IN> {
|
|
14
14
|
return transformMap(v => v, {
|
|
15
|
-
|
|
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>
|
|
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 (
|
|
231
|
-
|
|
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
|
|
12
|
-
|
|
12
|
+
objectMode,
|
|
13
|
+
highWaterMark,
|
|
13
14
|
write(_chunk, _, cb) {
|
|
14
15
|
cb()
|
|
15
16
|
},
|