@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.
- package/dist/stream/pipeline.d.ts +4 -4
- package/dist/stream/pipeline.js +18 -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 +32 -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';
|
|
@@ -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(
|
|
150
|
+
filter(asyncPredicate, opt) {
|
|
145
151
|
this.transforms.push(transformMap(v => v, {
|
|
146
|
-
|
|
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>(
|
|
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.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": "
|
|
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'
|
|
@@ -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(
|
|
212
|
+
filter(asyncPredicate: AsyncPredicate<T>, opt?: TransformMapOptions): this {
|
|
204
213
|
this.transforms.push(
|
|
205
214
|
transformMap(v => v, {
|
|
206
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
},
|