@naturalcycles/nodejs-lib 12.58.0 → 12.62.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/got/getGot.js +98 -28
- package/dist/got/got.model.d.ts +6 -0
- package/dist/index.d.ts +37 -36
- package/dist/index.js +36 -129
- package/dist/log/log.util.d.ts +4 -0
- package/dist/log/log.util.js +11 -0
- package/dist/stream/ndjson/ndjsonMap.d.ts +2 -2
- package/dist/stream/ndjson/ndjsonMap.js +4 -3
- package/dist/stream/ndjson/ndjsonStreamForEach.d.ts +2 -2
- package/dist/stream/ndjson/transformJsonParse.js +3 -3
- package/dist/stream/ndjson/transformToNDJson.js +2 -2
- package/dist/stream/pipeline/pipeline.d.ts +25 -3
- package/dist/stream/pipeline/pipeline.js +76 -9
- package/dist/stream/readable/readableCreate.d.ts +8 -0
- package/dist/stream/readable/readableCreate.js +9 -1
- package/dist/stream/readable/readableForEach.d.ts +2 -2
- package/dist/stream/readable/readableFromArray.d.ts +2 -2
- package/dist/stream/readable/readableFromArray.js +17 -13
- package/dist/stream/readable/readableMap.d.ts +2 -2
- package/dist/stream/readable/readableMap.js +22 -17
- package/dist/stream/sizeStack.d.ts +9 -0
- package/dist/stream/sizeStack.js +48 -0
- package/dist/stream/stream.util.d.ts +4 -0
- package/dist/stream/stream.util.js +24 -0
- package/dist/stream/transform/transformBuffer.js +1 -1
- package/dist/stream/transform/transformFilter.d.ts +3 -4
- package/dist/stream/transform/transformFilter.js +5 -20
- package/dist/stream/transform/transformLimit.d.ts +32 -1
- package/dist/stream/transform/transformLimit.js +33 -16
- package/dist/stream/transform/transformLogProgress.d.ts +20 -0
- package/dist/stream/transform/transformLogProgress.js +36 -18
- package/dist/stream/transform/transformMap.d.ts +4 -15
- package/dist/stream/transform/transformMap.js +54 -71
- package/dist/stream/transform/transformMapSimple.js +1 -1
- package/dist/stream/transform/transformMapSync.d.ts +5 -3
- package/dist/stream/transform/transformMapSync.js +28 -22
- package/dist/stream/transform/transformNoOp.js +1 -1
- package/dist/stream/transform/transformTap.js +3 -3
- package/dist/stream/transform/transformToArray.js +1 -1
- package/dist/stream/transform/transformToString.js +2 -2
- package/dist/stream/transform/worker/transformMultiThreaded.js +1 -1
- package/dist/stream/transform/worker/workerClassProxy.js +1 -0
- package/dist/stream/writable/writableFork.js +1 -1
- package/dist/stream/writable/writableLimit.d.ts +9 -0
- package/dist/stream/writable/writableLimit.js +29 -0
- package/dist/stream/writable/writablePushToArray.js +1 -1
- package/dist/stream/writable/writableVoid.d.ts +8 -1
- package/dist/stream/writable/writableVoid.js +6 -2
- package/dist/util/zip.util.d.ts +15 -7
- package/dist/util/zip.util.js +27 -22
- package/package.json +1 -1
- package/src/got/getGot.ts +120 -31
- package/src/got/got.model.ts +8 -0
- package/src/index.ts +36 -194
- package/src/log/log.util.ts +9 -0
- package/src/stream/ndjson/ndjsonMap.ts +7 -5
- package/src/stream/ndjson/ndjsonStreamForEach.ts +2 -2
- package/src/stream/ndjson/transformJsonParse.ts +3 -3
- package/src/stream/ndjson/transformToNDJson.ts +2 -2
- package/src/stream/pipeline/pipeline.ts +102 -9
- package/src/stream/readable/readableCreate.ts +9 -1
- package/src/stream/readable/readableForEach.ts +2 -2
- package/src/stream/readable/readableFromArray.ts +18 -21
- package/src/stream/readable/readableMap.ts +24 -21
- package/src/stream/sizeStack.ts +56 -0
- package/src/stream/stream.util.ts +29 -0
- package/src/stream/transform/transformBuffer.ts +1 -1
- package/src/stream/transform/transformFilter.ts +6 -20
- package/src/stream/transform/transformLimit.ts +66 -20
- package/src/stream/transform/transformLogProgress.ts +72 -23
- package/src/stream/transform/transformMap.ts +75 -101
- package/src/stream/transform/transformMapSimple.ts +1 -1
- package/src/stream/transform/transformMapSync.ts +40 -26
- package/src/stream/transform/transformNoOp.ts +1 -1
- package/src/stream/transform/transformTap.ts +3 -3
- package/src/stream/transform/transformToArray.ts +1 -1
- package/src/stream/transform/transformToString.ts +2 -2
- package/src/stream/transform/worker/transformMultiThreaded.ts +1 -1
- package/src/stream/transform/worker/workerClassProxy.js +1 -0
- package/src/stream/writable/writableFork.ts +1 -1
- package/src/stream/writable/writableLimit.ts +28 -0
- package/src/stream/writable/writablePushToArray.ts +1 -1
- package/src/stream/writable/writableVoid.ts +14 -2
- package/src/util/zip.util.ts +26 -20
- package/dist/stream/transform/legacy/transformMap.d.ts +0 -17
- package/dist/stream/transform/legacy/transformMap.js +0 -94
- package/src/stream/transform/legacy/transformMap.ts +0 -133
|
@@ -84,6 +84,26 @@ export interface TransformLogProgressOptions<IN = any> extends TransformOptions
|
|
|
84
84
|
* Defaults to 1.
|
|
85
85
|
*/
|
|
86
86
|
batchSize?: number;
|
|
87
|
+
/**
|
|
88
|
+
* Experimental logging of item (shunk) sizes, when json-stringified.
|
|
89
|
+
*
|
|
90
|
+
* Defaults to false.
|
|
91
|
+
*
|
|
92
|
+
* @experimental
|
|
93
|
+
*/
|
|
94
|
+
logSizes?: boolean;
|
|
95
|
+
/**
|
|
96
|
+
* How many last item sizes to keep in a buffer, to calculate stats (p50, p90, avg, etc).
|
|
97
|
+
* Defaults to 100_000.
|
|
98
|
+
* Cannot be Infinity.
|
|
99
|
+
*/
|
|
100
|
+
logSizesBuffer?: number;
|
|
101
|
+
/**
|
|
102
|
+
* Works in addition to `logSizes`. Adds "zipped sizes".
|
|
103
|
+
*
|
|
104
|
+
* @experimental
|
|
105
|
+
*/
|
|
106
|
+
logZippedSizes?: boolean;
|
|
87
107
|
}
|
|
88
108
|
/**
|
|
89
109
|
* Pass-through transform that optionally logs progress.
|
|
@@ -7,6 +7,7 @@ const js_lib_1 = require("@naturalcycles/js-lib");
|
|
|
7
7
|
const time_lib_1 = require("@naturalcycles/time-lib");
|
|
8
8
|
const colors_1 = require("../../colors");
|
|
9
9
|
const colors_2 = require("../../colors/colors");
|
|
10
|
+
const sizeStack_1 = require("../sizeStack");
|
|
10
11
|
const inspectOpt = {
|
|
11
12
|
colors: colors_2.hasColors,
|
|
12
13
|
breakLength: 300,
|
|
@@ -15,7 +16,7 @@ const inspectOpt = {
|
|
|
15
16
|
* Pass-through transform that optionally logs progress.
|
|
16
17
|
*/
|
|
17
18
|
function transformLogProgress(opt = {}) {
|
|
18
|
-
const { metric = 'progress', heapTotal: logHeapTotal = false, heapUsed: logHeapUsed = false, rss: logRss = true, peakRSS: logPeakRSS = true, logRPS = true, logEvery = 1000, batchSize = 1, extra, logger = console, } = opt;
|
|
19
|
+
const { metric = 'progress', heapTotal: logHeapTotal = false, heapUsed: logHeapUsed = false, rss: logRss = true, peakRSS: logPeakRSS = true, logRPS = true, logEvery = 1000, logSizes = false, logSizesBuffer = 100000, logZippedSizes = false, batchSize = 1, extra, logger = console, } = opt;
|
|
19
20
|
const logProgress = opt.logProgress !== false && logEvery !== 0; // true by default
|
|
20
21
|
const logEvery10 = logEvery * 10;
|
|
21
22
|
const started = Date.now();
|
|
@@ -24,13 +25,19 @@ function transformLogProgress(opt = {}) {
|
|
|
24
25
|
let processedLastSecond = 0;
|
|
25
26
|
let progress = 0;
|
|
26
27
|
let peakRSS = 0;
|
|
28
|
+
const sizes = logSizes ? new sizeStack_1.SizeStack('json', logSizesBuffer) : undefined;
|
|
29
|
+
const sizesZipped = logZippedSizes ? new sizeStack_1.SizeStack('json.gz', logSizesBuffer) : undefined;
|
|
27
30
|
logStats(); // initial
|
|
28
31
|
return new stream_1.Transform({
|
|
29
32
|
objectMode: true,
|
|
30
33
|
...opt,
|
|
31
|
-
transform(chunk,
|
|
34
|
+
transform(chunk, _, cb) {
|
|
32
35
|
progress++;
|
|
33
36
|
processedLastSecond++;
|
|
37
|
+
if (sizes) {
|
|
38
|
+
// Check it, cause gzipping might be delayed here..
|
|
39
|
+
void sizeStack_1.SizeStack.countItem(chunk, logger, sizes, sizesZipped);
|
|
40
|
+
}
|
|
34
41
|
if (logProgress && progress % logEvery === 0) {
|
|
35
42
|
logStats(chunk, false, progress % logEvery10 === 0);
|
|
36
43
|
}
|
|
@@ -54,23 +61,34 @@ function transformLogProgress(opt = {}) {
|
|
|
54
61
|
const rps10 = Math.round(sma.push(lastRPS));
|
|
55
62
|
if (mem.rss > peakRSS)
|
|
56
63
|
peakRSS = mem.rss;
|
|
57
|
-
|
|
64
|
+
const o = {
|
|
58
65
|
[final ? `${metric}_final` : metric]: batchedProgress,
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
66
|
+
};
|
|
67
|
+
if (extra)
|
|
68
|
+
Object.assign(o, extra(chunk, progress));
|
|
69
|
+
if (logHeapUsed)
|
|
70
|
+
o.heapUsed = (0, js_lib_1._mb)(mem.heapUsed);
|
|
71
|
+
if (logHeapTotal)
|
|
72
|
+
o.heapTotal = (0, js_lib_1._mb)(mem.heapTotal);
|
|
73
|
+
if (logRss)
|
|
74
|
+
o.rss = (0, js_lib_1._mb)(mem.rss);
|
|
75
|
+
if (logPeakRSS)
|
|
76
|
+
o.peakRSS = (0, js_lib_1._mb)(peakRSS);
|
|
77
|
+
if (opt.rssMinusHeap)
|
|
78
|
+
o.rssMinusHeap = (0, js_lib_1._mb)(mem.rss - mem.heapTotal);
|
|
79
|
+
if (opt.external)
|
|
80
|
+
o.external = (0, js_lib_1._mb)(mem.external);
|
|
81
|
+
if (opt.arrayBuffers)
|
|
82
|
+
o.arrayBuffers = (0, js_lib_1._mb)(mem.arrayBuffers || 0);
|
|
83
|
+
if (logRPS)
|
|
84
|
+
Object.assign(o, { rps10, rpsTotal });
|
|
85
|
+
logger.log((0, util_1.inspect)(o, inspectOpt));
|
|
86
|
+
if (sizes?.items.length) {
|
|
87
|
+
logger.log(sizes.getStats());
|
|
88
|
+
if (sizesZipped?.items.length) {
|
|
89
|
+
logger.log(sizesZipped.getStats());
|
|
90
|
+
}
|
|
91
|
+
}
|
|
74
92
|
if (tenx) {
|
|
75
93
|
let perHour = Math.round((batchedProgress * 1000 * 60 * 60) / (now - started)) || 0;
|
|
76
94
|
if (perHour > 900) {
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { AbortableAsyncMapper, AsyncPredicate, CommonLogger, ErrorMode } from '@naturalcycles/js-lib';
|
|
2
2
|
import { TransformTyped } from '../stream.model';
|
|
3
|
-
import { transformMapLegacy } from './legacy/transformMap';
|
|
4
3
|
export interface TransformMapOptions<IN = any, OUT = IN> {
|
|
5
4
|
/**
|
|
6
5
|
* Set true to support "multiMap" - possibility to return [] and emit 1 result for each item in the array.
|
|
@@ -12,9 +11,8 @@ export interface TransformMapOptions<IN = any, OUT = IN> {
|
|
|
12
11
|
* Predicate to filter outgoing results (after mapper).
|
|
13
12
|
* Allows to not emit all results.
|
|
14
13
|
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
* @default to filter out undefined/null values, but pass anything else
|
|
14
|
+
* Defaults to "pass everything" (including null, undefined, etc).
|
|
15
|
+
* Simpler way to exclude certain cases is to return SKIP symbol from the mapper.
|
|
18
16
|
*/
|
|
19
17
|
predicate?: AsyncPredicate<OUT>;
|
|
20
18
|
/**
|
|
@@ -38,17 +36,8 @@ export interface TransformMapOptions<IN = any, OUT = IN> {
|
|
|
38
36
|
* @default `stream`
|
|
39
37
|
*/
|
|
40
38
|
metric?: string;
|
|
41
|
-
/**
|
|
42
|
-
* If defined - called BEFORE `final()` callback is called.
|
|
43
|
-
*/
|
|
44
|
-
beforeFinal?: () => any;
|
|
45
39
|
logger?: CommonLogger;
|
|
46
40
|
}
|
|
47
|
-
export declare function notNullishPredicate(item: any): boolean;
|
|
48
|
-
/**
|
|
49
|
-
* Temporary export legacy transformMap, to debug 503 errors
|
|
50
|
-
*/
|
|
51
|
-
export declare const transformMap: typeof transformMapLegacy;
|
|
52
41
|
/**
|
|
53
42
|
* Like pMap, but for streams.
|
|
54
43
|
* Inspired by `through2`.
|
|
@@ -61,4 +50,4 @@ export declare const transformMap: typeof transformMapLegacy;
|
|
|
61
50
|
*
|
|
62
51
|
* If an Array is returned by `mapper` - it will be flattened and multiple results will be emitted from it. Tested by Array.isArray().
|
|
63
52
|
*/
|
|
64
|
-
export declare function
|
|
53
|
+
export declare function transformMap<IN = any, OUT = IN>(mapper: AbortableAsyncMapper<IN, OUT>, opt?: TransformMapOptions<IN, OUT>): TransformTyped<IN, OUT>;
|
|
@@ -1,18 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
4
|
-
const stream_1 = require("stream");
|
|
3
|
+
exports.transformMap = void 0;
|
|
5
4
|
const js_lib_1 = require("@naturalcycles/js-lib");
|
|
5
|
+
const through2Concurrent = require("through2-concurrent");
|
|
6
6
|
const colors_1 = require("../../colors");
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
}
|
|
11
|
-
exports.notNullishPredicate = notNullishPredicate;
|
|
12
|
-
/**
|
|
13
|
-
* Temporary export legacy transformMap, to debug 503 errors
|
|
14
|
-
*/
|
|
15
|
-
exports.transformMap = transformMap_1.transformMapLegacy;
|
|
7
|
+
const stream_util_1 = require("../stream.util");
|
|
8
|
+
// doesn't work, cause here we don't construct our Transform instance ourselves
|
|
9
|
+
// export class TransformMap extends AbortableTransform {}
|
|
16
10
|
/**
|
|
17
11
|
* Like pMap, but for streams.
|
|
18
12
|
* Inspired by `through2`.
|
|
@@ -25,84 +19,73 @@ exports.transformMap = transformMap_1.transformMapLegacy;
|
|
|
25
19
|
*
|
|
26
20
|
* If an Array is returned by `mapper` - it will be flattened and multiple results will be emitted from it. Tested by Array.isArray().
|
|
27
21
|
*/
|
|
28
|
-
function
|
|
29
|
-
const { concurrency = 16, predicate
|
|
22
|
+
function transformMap(mapper, opt = {}) {
|
|
23
|
+
const { concurrency = 16, predicate, // we now default to "no predicate" (meaning pass-everything)
|
|
24
|
+
errorMode = js_lib_1.ErrorMode.THROW_IMMEDIATELY, flattenArrayOutput, onError, metric = 'stream', logger = console, } = opt;
|
|
30
25
|
let index = -1;
|
|
31
|
-
let
|
|
26
|
+
let isSettled = false;
|
|
32
27
|
let errors = 0;
|
|
33
28
|
const collectedErrors = []; // only used if errorMode == THROW_AGGREGATED
|
|
34
|
-
|
|
35
|
-
concurrency,
|
|
36
|
-
resolveOn: 'start',
|
|
37
|
-
// debug: true,
|
|
38
|
-
});
|
|
39
|
-
return new stream_1.Transform({
|
|
40
|
-
objectMode: true,
|
|
29
|
+
return through2Concurrent.obj({
|
|
30
|
+
maxConcurrency: concurrency,
|
|
41
31
|
async final(cb) {
|
|
42
|
-
// console.log('transformMap final'
|
|
43
|
-
|
|
44
|
-
await q.onIdle();
|
|
45
|
-
logErrorStats(logger, true);
|
|
46
|
-
await beforeFinal?.(); // call beforeFinal if defined
|
|
32
|
+
// console.log('transformMap final')
|
|
33
|
+
logErrorStats(true);
|
|
47
34
|
if (collectedErrors.length) {
|
|
48
35
|
// emit Aggregated error
|
|
49
|
-
// For the same reason, magically, let's not call `cb`, but emit an error event instead
|
|
50
|
-
// this.emit('error', new AggregatedError(collectedErrors))
|
|
51
36
|
cb(new js_lib_1.AggregatedError(collectedErrors));
|
|
52
37
|
}
|
|
53
38
|
else {
|
|
54
39
|
// emit no error
|
|
55
|
-
|
|
56
|
-
// Commenting it out seems to work ?!
|
|
57
|
-
// ?!
|
|
58
|
-
// cb()
|
|
40
|
+
cb();
|
|
59
41
|
}
|
|
60
42
|
},
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
const res = await mapper(chunk, currentIndex);
|
|
73
|
-
const passedResults = await (0, js_lib_1.pFilter)(flattenArrayOutput && Array.isArray(res) ? res : [res], async (r) => await predicate(r, currentIndex));
|
|
74
|
-
passedResults.forEach(r => this.push(r));
|
|
75
|
-
}
|
|
76
|
-
catch (err) {
|
|
77
|
-
logger.error(err);
|
|
78
|
-
errors++;
|
|
79
|
-
logErrorStats(logger);
|
|
80
|
-
if (onError) {
|
|
81
|
-
try {
|
|
82
|
-
onError(err, chunk);
|
|
83
|
-
}
|
|
84
|
-
catch { }
|
|
85
|
-
}
|
|
86
|
-
if (errorMode === js_lib_1.ErrorMode.THROW_IMMEDIATELY) {
|
|
87
|
-
isRejected = true;
|
|
88
|
-
// Emit error immediately
|
|
89
|
-
// return cb(err as Error)
|
|
90
|
-
return this.emit('error', err);
|
|
91
|
-
}
|
|
92
|
-
if (errorMode === js_lib_1.ErrorMode.THROW_AGGREGATED) {
|
|
93
|
-
collectedErrors.push(err);
|
|
94
|
-
}
|
|
43
|
+
}, async function transformMapFn(chunk, _, cb) {
|
|
44
|
+
// Stop processing if isSettled (either THROW_IMMEDIATELY was fired or END received)
|
|
45
|
+
if (isSettled)
|
|
46
|
+
return cb();
|
|
47
|
+
const currentIndex = ++index;
|
|
48
|
+
try {
|
|
49
|
+
const res = await mapper(chunk, currentIndex);
|
|
50
|
+
const passedResults = await (0, js_lib_1.pFilter)(flattenArrayOutput && Array.isArray(res) ? res : [res], async (r) => {
|
|
51
|
+
if (r === js_lib_1.END) {
|
|
52
|
+
isSettled = true; // will be checked later
|
|
53
|
+
return false;
|
|
95
54
|
}
|
|
55
|
+
return r !== js_lib_1.SKIP && (!predicate || (await predicate(r, currentIndex)));
|
|
96
56
|
});
|
|
97
|
-
|
|
98
|
-
|
|
57
|
+
passedResults.forEach(r => this.push(r));
|
|
58
|
+
if (isSettled) {
|
|
59
|
+
logger.log(`transformMap END received at index ${currentIndex}`);
|
|
60
|
+
(0, stream_util_1.pipelineClose)('transformMap', this, this.sourceReadable, this.streamDone, logger);
|
|
61
|
+
}
|
|
62
|
+
cb(); // done processing
|
|
63
|
+
}
|
|
64
|
+
catch (err) {
|
|
65
|
+
logger.error(err);
|
|
66
|
+
errors++;
|
|
67
|
+
logErrorStats();
|
|
68
|
+
if (onError) {
|
|
69
|
+
try {
|
|
70
|
+
onError(err, chunk);
|
|
71
|
+
}
|
|
72
|
+
catch { }
|
|
73
|
+
}
|
|
74
|
+
if (errorMode === js_lib_1.ErrorMode.THROW_IMMEDIATELY) {
|
|
75
|
+
isSettled = true;
|
|
76
|
+
return cb(err); // Emit error immediately
|
|
77
|
+
}
|
|
78
|
+
if (errorMode === js_lib_1.ErrorMode.THROW_AGGREGATED) {
|
|
79
|
+
collectedErrors.push(err);
|
|
80
|
+
}
|
|
81
|
+
// Tell input stream that we're done processing, but emit nothing to output - not error nor result
|
|
99
82
|
cb();
|
|
100
|
-
}
|
|
83
|
+
}
|
|
101
84
|
});
|
|
102
|
-
function logErrorStats(
|
|
85
|
+
function logErrorStats(final = false) {
|
|
103
86
|
if (!errors)
|
|
104
87
|
return;
|
|
105
88
|
logger.log(`${metric} ${final ? 'final ' : ''}errors: ${(0, colors_1.yellow)(errors)}`);
|
|
106
89
|
}
|
|
107
90
|
}
|
|
108
|
-
exports.
|
|
91
|
+
exports.transformMap = transformMap;
|
|
@@ -17,7 +17,7 @@ function transformMapSimple(mapper, opt = {}) {
|
|
|
17
17
|
const { errorMode = js_lib_1.ErrorMode.THROW_IMMEDIATELY, logger = console } = opt;
|
|
18
18
|
return new stream_1.Transform({
|
|
19
19
|
objectMode: true,
|
|
20
|
-
transform(chunk,
|
|
20
|
+
transform(chunk, _, cb) {
|
|
21
21
|
try {
|
|
22
22
|
cb(null, mapper(chunk, ++index));
|
|
23
23
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { CommonLogger, ErrorMode, Mapper, Predicate } from '@naturalcycles/js-lib';
|
|
2
|
+
import { AbortableTransform } from '../pipeline/pipeline';
|
|
2
3
|
import { TransformTyped } from '../stream.model';
|
|
3
4
|
export interface TransformMapSyncOptions<IN = any, OUT = IN> {
|
|
4
5
|
/**
|
|
@@ -14,9 +15,8 @@ export interface TransformMapSyncOptions<IN = any, OUT = IN> {
|
|
|
14
15
|
* Predicate to filter outgoing results (after mapper).
|
|
15
16
|
* Allows to not emit all results.
|
|
16
17
|
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
* Set to `r => r` (passthrough predicate) to pass ANY value (including undefined/null)
|
|
18
|
+
* Defaults to "pass everything".
|
|
19
|
+
* Simpler way to skip individual entries is to return SKIP symbol.
|
|
20
20
|
*/
|
|
21
21
|
predicate?: Predicate<OUT>;
|
|
22
22
|
/**
|
|
@@ -36,6 +36,8 @@ export interface TransformMapSyncOptions<IN = any, OUT = IN> {
|
|
|
36
36
|
metric?: string;
|
|
37
37
|
logger?: CommonLogger;
|
|
38
38
|
}
|
|
39
|
+
export declare class TransformMapSync extends AbortableTransform {
|
|
40
|
+
}
|
|
39
41
|
/**
|
|
40
42
|
* Sync (not async) version of transformMap.
|
|
41
43
|
* Supposedly faster, for cases when async is not needed.
|
|
@@ -1,42 +1,48 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.transformMapSync = void 0;
|
|
4
|
-
const stream_1 = require("stream");
|
|
3
|
+
exports.transformMapSync = exports.TransformMapSync = void 0;
|
|
5
4
|
const js_lib_1 = require("@naturalcycles/js-lib");
|
|
6
5
|
const colors_1 = require("../../colors");
|
|
7
|
-
const
|
|
6
|
+
const pipeline_1 = require("../pipeline/pipeline");
|
|
7
|
+
const stream_util_1 = require("../stream.util");
|
|
8
|
+
class TransformMapSync extends pipeline_1.AbortableTransform {
|
|
9
|
+
}
|
|
10
|
+
exports.TransformMapSync = TransformMapSync;
|
|
8
11
|
/**
|
|
9
12
|
* Sync (not async) version of transformMap.
|
|
10
13
|
* Supposedly faster, for cases when async is not needed.
|
|
11
14
|
*/
|
|
12
15
|
function transformMapSync(mapper, opt = {}) {
|
|
13
16
|
let index = -1;
|
|
14
|
-
const { predicate
|
|
15
|
-
|
|
17
|
+
const { predicate, // defaults to "no predicate" (pass everything)
|
|
18
|
+
errorMode = js_lib_1.ErrorMode.THROW_IMMEDIATELY, flattenArrayOutput = false, onError, metric = 'stream', objectMode = true, logger = console, } = opt;
|
|
19
|
+
let isSettled = false;
|
|
16
20
|
let errors = 0;
|
|
17
21
|
const collectedErrors = []; // only used if errorMode == THROW_AGGREGATED
|
|
18
|
-
return new
|
|
22
|
+
return new TransformMapSync({
|
|
19
23
|
objectMode,
|
|
20
24
|
...opt,
|
|
21
|
-
transform(chunk,
|
|
22
|
-
// Stop processing if
|
|
23
|
-
if (
|
|
25
|
+
transform(chunk, _, cb) {
|
|
26
|
+
// Stop processing if isSettled
|
|
27
|
+
if (isSettled)
|
|
24
28
|
return cb();
|
|
25
|
-
|
|
29
|
+
const currentIndex = ++index;
|
|
26
30
|
try {
|
|
27
|
-
if (!predicate(chunk, ++index)) {
|
|
28
|
-
cb(); // signal that we've finished processing, but emit no output here
|
|
29
|
-
return;
|
|
30
|
-
}
|
|
31
31
|
// map and pass through
|
|
32
|
-
const v = mapper(chunk,
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
32
|
+
const v = mapper(chunk, currentIndex);
|
|
33
|
+
const passedResults = (flattenArrayOutput && Array.isArray(v) ? v : [v]).filter(r => {
|
|
34
|
+
if (r === js_lib_1.END) {
|
|
35
|
+
isSettled = true; // will be checked later
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
return r !== js_lib_1.SKIP && (!predicate || predicate(r, currentIndex));
|
|
39
|
+
});
|
|
40
|
+
passedResults.forEach(r => this.push(r));
|
|
41
|
+
if (isSettled) {
|
|
42
|
+
logger.log(`transformMapSync END received at index ${currentIndex}`);
|
|
43
|
+
(0, stream_util_1.pipelineClose)('transformMapSync', this, this.sourceReadable, this.streamDone, logger);
|
|
39
44
|
}
|
|
45
|
+
cb(); // done processing
|
|
40
46
|
}
|
|
41
47
|
catch (err) {
|
|
42
48
|
logger.error(err);
|
|
@@ -49,7 +55,7 @@ function transformMapSync(mapper, opt = {}) {
|
|
|
49
55
|
catch { }
|
|
50
56
|
}
|
|
51
57
|
if (errorMode === js_lib_1.ErrorMode.THROW_IMMEDIATELY) {
|
|
52
|
-
|
|
58
|
+
isSettled = true;
|
|
53
59
|
// Emit error immediately
|
|
54
60
|
return cb(err);
|
|
55
61
|
}
|
|
@@ -10,14 +10,14 @@ const stream_1 = require("stream");
|
|
|
10
10
|
*/
|
|
11
11
|
function transformTap(fn, opt = {}) {
|
|
12
12
|
const { logger = console } = opt;
|
|
13
|
-
let index =
|
|
13
|
+
let index = -1;
|
|
14
14
|
return new stream_1.Transform({
|
|
15
15
|
objectMode: true,
|
|
16
16
|
...opt,
|
|
17
|
-
async transform(chunk,
|
|
17
|
+
async transform(chunk, _, cb) {
|
|
18
18
|
// console.log('tap', chunk)
|
|
19
19
|
try {
|
|
20
|
-
await fn(chunk, index
|
|
20
|
+
await fn(chunk, ++index);
|
|
21
21
|
}
|
|
22
22
|
catch (err) {
|
|
23
23
|
logger.error(err);
|
|
@@ -10,7 +10,7 @@ function transformToArray(opt = {}) {
|
|
|
10
10
|
return new stream_1.Transform({
|
|
11
11
|
objectMode: true,
|
|
12
12
|
...opt,
|
|
13
|
-
transform(chunk,
|
|
13
|
+
transform(chunk, _, cb) {
|
|
14
14
|
res.push(chunk);
|
|
15
15
|
// callback to signal that we processed input, but not emitting any output
|
|
16
16
|
cb();
|
|
@@ -15,8 +15,8 @@ function transformToString() {
|
|
|
15
15
|
return new stream_1.Transform({
|
|
16
16
|
objectMode: false,
|
|
17
17
|
readableObjectMode: true,
|
|
18
|
-
transform(chunk,
|
|
19
|
-
// console.log(`enc: ${
|
|
18
|
+
transform(chunk, _, cb) {
|
|
19
|
+
// console.log(`enc: ${_}`, chunk.toString())
|
|
20
20
|
cb(null, chunk.toString());
|
|
21
21
|
},
|
|
22
22
|
});
|
|
@@ -71,7 +71,7 @@ function transformMultiThreaded(opt) {
|
|
|
71
71
|
cb(err);
|
|
72
72
|
}
|
|
73
73
|
},
|
|
74
|
-
}, async function transformMapFn(chunk,
|
|
74
|
+
}, async function transformMapFn(chunk, _, cb) {
|
|
75
75
|
// Freezing the index, because it may change due to concurrency
|
|
76
76
|
const currentIndex = ++index;
|
|
77
77
|
// Create the unresolved promise (to avait)
|
|
@@ -24,7 +24,7 @@ function writableFork(chains, opt) {
|
|
|
24
24
|
return new stream_1.Writable({
|
|
25
25
|
objectMode: true,
|
|
26
26
|
...opt,
|
|
27
|
-
write(chunk,
|
|
27
|
+
write(chunk, _, cb) {
|
|
28
28
|
// Push/fork to all sub-streams
|
|
29
29
|
// No backpressure is ensured here, it'll push regardless of the
|
|
30
30
|
readables.forEach(readable => readable.push(chunk));
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import { Readable } from 'stream';
|
|
3
|
+
import { WritableTyped } from '../stream.model';
|
|
4
|
+
/**
|
|
5
|
+
* Allows to stop the Readable stream after the pipeline has processed X number of rows.
|
|
6
|
+
* It counts OUTPUT rows (not input), because this Writable is always at the end of the Pipeline.
|
|
7
|
+
* It ensures that everything has been processed before issuing a STOP on the readable.
|
|
8
|
+
*/
|
|
9
|
+
export declare function writableLimit<T>(readable: Readable, limit: number): WritableTyped<T>;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.writableLimit = void 0;
|
|
4
|
+
const stream_1 = require("stream");
|
|
5
|
+
/**
|
|
6
|
+
* Allows to stop the Readable stream after the pipeline has processed X number of rows.
|
|
7
|
+
* It counts OUTPUT rows (not input), because this Writable is always at the end of the Pipeline.
|
|
8
|
+
* It ensures that everything has been processed before issuing a STOP on the readable.
|
|
9
|
+
*/
|
|
10
|
+
function writableLimit(readable, limit) {
|
|
11
|
+
let i = 0;
|
|
12
|
+
return new stream_1.Writable({
|
|
13
|
+
objectMode: true,
|
|
14
|
+
write(chunk, _, cb) {
|
|
15
|
+
if (limit === 0)
|
|
16
|
+
return cb(); // no limit, just passthrough
|
|
17
|
+
i++;
|
|
18
|
+
if (i === limit) {
|
|
19
|
+
console.log(`writableLimit of ${limit} reached`);
|
|
20
|
+
readable.destroy();
|
|
21
|
+
cb(); // do we need it?
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
cb(); // passthrough
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
exports.writableLimit = writableLimit;
|
|
@@ -9,7 +9,7 @@ function writablePushToArray(arr, opt = {}) {
|
|
|
9
9
|
return new stream_1.Writable({
|
|
10
10
|
objectMode: true,
|
|
11
11
|
...opt,
|
|
12
|
-
write(chunk,
|
|
12
|
+
write(chunk, _, cb) {
|
|
13
13
|
arr.push(chunk);
|
|
14
14
|
// callback to signal that we processed input, but not emitting any output
|
|
15
15
|
cb();
|
|
@@ -1,9 +1,16 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
2
|
import { Writable } from 'stream';
|
|
3
|
+
import { DeferredPromise } from '@naturalcycles/js-lib';
|
|
3
4
|
import { TransformOptions } from '../stream.model';
|
|
5
|
+
export interface WritableVoidOptions extends TransformOptions {
|
|
6
|
+
/**
|
|
7
|
+
* If set - it will be Resolved when the Stream is done (after final.cb)
|
|
8
|
+
*/
|
|
9
|
+
streamDone?: DeferredPromise;
|
|
10
|
+
}
|
|
4
11
|
/**
|
|
5
12
|
* Use as a "null-terminator" of stream.pipeline.
|
|
6
13
|
* It consumes the stream as quickly as possible without doing anything.
|
|
7
14
|
* Put it in the end of your pipeline in case it ends with Transform that needs a consumer.
|
|
8
15
|
*/
|
|
9
|
-
export declare function writableVoid(opt?:
|
|
16
|
+
export declare function writableVoid(opt?: WritableVoidOptions): Writable;
|
|
@@ -7,13 +7,17 @@ const stream_1 = require("stream");
|
|
|
7
7
|
* It consumes the stream as quickly as possible without doing anything.
|
|
8
8
|
* Put it in the end of your pipeline in case it ends with Transform that needs a consumer.
|
|
9
9
|
*/
|
|
10
|
-
function writableVoid(opt) {
|
|
10
|
+
function writableVoid(opt = {}) {
|
|
11
11
|
return new stream_1.Writable({
|
|
12
12
|
objectMode: true,
|
|
13
13
|
...opt,
|
|
14
|
-
write(chunk,
|
|
14
|
+
write(chunk, _, cb) {
|
|
15
15
|
cb();
|
|
16
16
|
},
|
|
17
|
+
final(cb) {
|
|
18
|
+
cb();
|
|
19
|
+
opt.streamDone?.resolve();
|
|
20
|
+
},
|
|
17
21
|
});
|
|
18
22
|
}
|
|
19
23
|
exports.writableVoid = writableVoid;
|
package/dist/util/zip.util.d.ts
CHANGED
|
@@ -1,18 +1,26 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
2
|
import { ZlibOptions } from 'zlib';
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
5
|
-
* It's 9 bytes shorter than gzip
|
|
4
|
+
* deflateBuffer uses `deflate`.
|
|
5
|
+
* It's 9 bytes shorter than `gzip`.
|
|
6
6
|
*/
|
|
7
|
-
export declare function
|
|
7
|
+
export declare function deflateBuffer(buf: Buffer, options?: ZlibOptions): Promise<Buffer>;
|
|
8
|
+
export declare function inflateBuffer(buf: Buffer, options?: ZlibOptions): Promise<Buffer>;
|
|
9
|
+
/**
|
|
10
|
+
* deflateString uses `deflate`.
|
|
11
|
+
* It's 9 bytes shorter than `gzip`.
|
|
12
|
+
*/
|
|
13
|
+
export declare function deflateString(s: string, options?: ZlibOptions): Promise<Buffer>;
|
|
14
|
+
export declare function inflateToString(buf: Buffer, options?: ZlibOptions): Promise<string>;
|
|
8
15
|
/**
|
|
9
16
|
* gzipBuffer uses `gzip`
|
|
10
|
-
* It's 9 bytes longer than deflate
|
|
17
|
+
* It's 9 bytes longer than `deflate`.
|
|
11
18
|
*/
|
|
12
19
|
export declare function gzipBuffer(buf: Buffer, options?: ZlibOptions): Promise<Buffer>;
|
|
13
|
-
export declare function unzipBuffer(buf: Buffer, options?: ZlibOptions): Promise<Buffer>;
|
|
14
20
|
export declare function gunzipBuffer(buf: Buffer, options?: ZlibOptions): Promise<Buffer>;
|
|
15
|
-
|
|
21
|
+
/**
|
|
22
|
+
* gzipString uses `gzip`.
|
|
23
|
+
* It's 9 bytes longer than `deflate`.
|
|
24
|
+
*/
|
|
16
25
|
export declare function gzipString(s: string, options?: ZlibOptions): Promise<Buffer>;
|
|
17
|
-
export declare function unzipToString(buf: Buffer, options?: ZlibOptions): Promise<string>;
|
|
18
26
|
export declare function gunzipToString(buf: Buffer, options?: ZlibOptions): Promise<string>;
|