@naturalcycles/nodejs-lib 13.17.0 → 13.19.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/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/stream/progressLogger.js +6 -1
- package/dist/stream/transform/transformLimit.d.ts +1 -4
- package/dist/stream/transform/transformLimit.js +1 -4
- package/dist/stream/transform/transformMap.d.ts +20 -7
- package/dist/stream/transform/transformMap.js +54 -34
- package/dist/stream/transform/transformMapSync.js +39 -24
- package/dist/stream/transform/transformOffset.d.ts +10 -0
- package/dist/stream/transform/transformOffset.js +24 -0
- package/package.json +1 -1
- package/src/index.ts +1 -0
- package/src/stream/progressLogger.ts +5 -1
- package/src/stream/transform/transformLimit.ts +1 -4
- package/src/stream/transform/transformMap.ts +72 -41
- package/src/stream/transform/transformMapSync.ts +38 -24
- package/src/stream/transform/transformOffset.ts +34 -0
package/dist/index.d.ts
CHANGED
|
@@ -37,6 +37,7 @@ export * from './stream/progressLogger';
|
|
|
37
37
|
export * from './stream/transform/transformChunk';
|
|
38
38
|
export * from './stream/transform/transformFilter';
|
|
39
39
|
export * from './stream/transform/transformLimit';
|
|
40
|
+
export * from './stream/transform/transformOffset';
|
|
40
41
|
export * from './stream/transform/transformLogProgress';
|
|
41
42
|
export * from './stream/transform/transformMap';
|
|
42
43
|
export * from './stream/transform/transformMapSimple';
|
package/dist/index.js
CHANGED
|
@@ -41,6 +41,7 @@ tslib_1.__exportStar(require("./stream/progressLogger"), exports);
|
|
|
41
41
|
tslib_1.__exportStar(require("./stream/transform/transformChunk"), exports);
|
|
42
42
|
tslib_1.__exportStar(require("./stream/transform/transformFilter"), exports);
|
|
43
43
|
tslib_1.__exportStar(require("./stream/transform/transformLimit"), exports);
|
|
44
|
+
tslib_1.__exportStar(require("./stream/transform/transformOffset"), exports);
|
|
44
45
|
tslib_1.__exportStar(require("./stream/transform/transformLogProgress"), exports);
|
|
45
46
|
tslib_1.__exportStar(require("./stream/transform/transformMap"), exports);
|
|
46
47
|
tslib_1.__exportStar(require("./stream/transform/transformMapSimple"), exports);
|
|
@@ -107,7 +107,12 @@ class ProgressLogger {
|
|
|
107
107
|
}
|
|
108
108
|
else if (final) {
|
|
109
109
|
logger.log(`${(0, colors_1.boldWhite)(metric)} took ${(0, colors_1.yellow)((0, js_lib_1._since)(this.started))} to process ${(0, colors_1.yellow)(batchedProgress)} rows with total RPS of ${(0, colors_1.yellow)(rpsTotal)}`);
|
|
110
|
-
|
|
110
|
+
try {
|
|
111
|
+
this.cfg.onProgressDone?.(o);
|
|
112
|
+
}
|
|
113
|
+
catch (err) {
|
|
114
|
+
logger.error(err);
|
|
115
|
+
}
|
|
111
116
|
}
|
|
112
117
|
}
|
|
113
118
|
}
|
|
@@ -34,7 +34,4 @@ export interface TransformLimitOptions extends TransformOptions {
|
|
|
34
34
|
*/
|
|
35
35
|
export declare class TransformLimit extends AbortableTransform {
|
|
36
36
|
}
|
|
37
|
-
|
|
38
|
-
* 0 or falsy value means "no limit"
|
|
39
|
-
*/
|
|
40
|
-
export declare function transformLimit<IN>(opt?: TransformLimitOptions): TransformTyped<IN, IN>;
|
|
37
|
+
export declare function transformLimit<IN>(opt: TransformLimitOptions): TransformTyped<IN, IN>;
|
|
@@ -10,10 +10,7 @@ const stream_util_1 = require("../stream.util");
|
|
|
10
10
|
class TransformLimit extends index_1.AbortableTransform {
|
|
11
11
|
}
|
|
12
12
|
exports.TransformLimit = TransformLimit;
|
|
13
|
-
|
|
14
|
-
* 0 or falsy value means "no limit"
|
|
15
|
-
*/
|
|
16
|
-
function transformLimit(opt = {}) {
|
|
13
|
+
function transformLimit(opt) {
|
|
17
14
|
const { logger = console, limit, debug } = opt;
|
|
18
15
|
if (!limit) {
|
|
19
16
|
// No limit - returning pass-through transform
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AbortableAsyncMapper, AsyncPredicate, CommonLogger, END, ErrorMode, SKIP, StringMap, UnixTimestampMillisNumber } from '@naturalcycles/js-lib';
|
|
1
|
+
import { AbortableAsyncMapper, AsyncPredicate, CommonLogger, END, ErrorMode, Promisable, SKIP, StringMap, UnixTimestampMillisNumber } from '@naturalcycles/js-lib';
|
|
2
2
|
import { TransformTyped } from '../stream.model';
|
|
3
3
|
export interface TransformMapOptions<IN = any, OUT = IN> {
|
|
4
4
|
/**
|
|
@@ -38,9 +38,9 @@ export interface TransformMapOptions<IN = any, OUT = IN> {
|
|
|
38
38
|
* Callback is called **before** [possible] Aggregated error is thrown,
|
|
39
39
|
* and before [possible] THROW_IMMEDIATELY error.
|
|
40
40
|
*
|
|
41
|
-
* onDone callback will be
|
|
41
|
+
* onDone callback will be awaited before Error is thrown.
|
|
42
42
|
*/
|
|
43
|
-
onDone?: (stats: TransformMapStats) => any
|
|
43
|
+
onDone?: (stats: TransformMapStats) => Promisable<any>;
|
|
44
44
|
/**
|
|
45
45
|
* Progress metric
|
|
46
46
|
*
|
|
@@ -63,6 +63,18 @@ export interface TransformMapStats {
|
|
|
63
63
|
countOut: number;
|
|
64
64
|
started: UnixTimestampMillisNumber;
|
|
65
65
|
}
|
|
66
|
+
export interface TransformMapStatsSummary extends TransformMapStats {
|
|
67
|
+
/**
|
|
68
|
+
* Name of the summary, defaults to `Transform`
|
|
69
|
+
*/
|
|
70
|
+
name?: string;
|
|
71
|
+
/**
|
|
72
|
+
* Allows to pass extra key-value object, which will be rendered as:
|
|
73
|
+
* key: value
|
|
74
|
+
* key2: value2
|
|
75
|
+
*/
|
|
76
|
+
extra?: StringMap<any>;
|
|
77
|
+
}
|
|
66
78
|
/**
|
|
67
79
|
* Like pMap, but for streams.
|
|
68
80
|
* Inspired by `through2`.
|
|
@@ -76,7 +88,8 @@ export interface TransformMapStats {
|
|
|
76
88
|
* If an Array is returned by `mapper` - it will be flattened and multiple results will be emitted from it. Tested by Array.isArray().
|
|
77
89
|
*/
|
|
78
90
|
export declare function transformMap<IN = any, OUT = IN>(mapper: AbortableAsyncMapper<IN, OUT | typeof SKIP | typeof END>, opt?: TransformMapOptions<IN, OUT>): TransformTyped<IN, OUT>;
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
91
|
+
/**
|
|
92
|
+
* Renders TransformMapStatsSummary into a friendly string,
|
|
93
|
+
* to be used e.g in Github Actions summary or Slack.
|
|
94
|
+
*/
|
|
95
|
+
export declare function transformMapStatsSummary(summary: TransformMapStatsSummary): string;
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.transformMapStatsSummary = exports.transformMap = void 0;
|
|
4
4
|
const js_lib_1 = require("@naturalcycles/js-lib");
|
|
5
5
|
const through2Concurrent = require("through2-concurrent");
|
|
6
6
|
const colors_1 = require("../../colors/colors");
|
|
7
|
-
const json2env_1 = require("../../fs/json2env");
|
|
8
7
|
const stream_util_1 = require("../stream.util");
|
|
9
8
|
// doesn't work, cause here we don't construct our Transform instance ourselves
|
|
10
9
|
// export class TransformMap extends AbortableTransform {}
|
|
@@ -35,27 +34,37 @@ function transformMap(mapper, opt = {}) {
|
|
|
35
34
|
// console.log('transformMap final')
|
|
36
35
|
logErrorStats(true);
|
|
37
36
|
if (collectedErrors.length) {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
37
|
+
try {
|
|
38
|
+
await onDone?.({
|
|
39
|
+
ok: false,
|
|
40
|
+
collectedErrors,
|
|
41
|
+
countErrors: errors,
|
|
42
|
+
countIn: index + 1,
|
|
43
|
+
countOut,
|
|
44
|
+
started,
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
catch (err) {
|
|
48
|
+
logger.error(err);
|
|
49
|
+
}
|
|
46
50
|
// emit Aggregated error
|
|
47
51
|
cb(new AggregateError(collectedErrors, `transformMap resulted in ${collectedErrors.length} error(s)`));
|
|
48
52
|
}
|
|
49
53
|
else {
|
|
50
54
|
// emit no error
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
55
|
+
try {
|
|
56
|
+
await onDone?.({
|
|
57
|
+
ok: true,
|
|
58
|
+
collectedErrors,
|
|
59
|
+
countErrors: errors,
|
|
60
|
+
countIn: index + 1,
|
|
61
|
+
countOut,
|
|
62
|
+
started,
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
catch (err) {
|
|
66
|
+
logger.error(err);
|
|
67
|
+
}
|
|
59
68
|
cb();
|
|
60
69
|
}
|
|
61
70
|
},
|
|
@@ -93,14 +102,19 @@ function transformMap(mapper, opt = {}) {
|
|
|
93
102
|
}
|
|
94
103
|
if (errorMode === js_lib_1.ErrorMode.THROW_IMMEDIATELY) {
|
|
95
104
|
isSettled = true;
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
105
|
+
try {
|
|
106
|
+
await onDone?.({
|
|
107
|
+
ok: false,
|
|
108
|
+
collectedErrors,
|
|
109
|
+
countErrors: errors,
|
|
110
|
+
countIn: index + 1,
|
|
111
|
+
countOut,
|
|
112
|
+
started,
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
catch (err) {
|
|
116
|
+
logger.error(err);
|
|
117
|
+
}
|
|
104
118
|
return cb(err); // Emit error immediately
|
|
105
119
|
}
|
|
106
120
|
if (errorMode === js_lib_1.ErrorMode.THROW_AGGREGATED) {
|
|
@@ -117,14 +131,20 @@ function transformMap(mapper, opt = {}) {
|
|
|
117
131
|
}
|
|
118
132
|
}
|
|
119
133
|
exports.transformMap = transformMap;
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
134
|
+
/**
|
|
135
|
+
* Renders TransformMapStatsSummary into a friendly string,
|
|
136
|
+
* to be used e.g in Github Actions summary or Slack.
|
|
137
|
+
*/
|
|
138
|
+
function transformMapStatsSummary(summary) {
|
|
139
|
+
const { countIn, countOut, countErrors, started, name = 'Transform', extra = {} } = summary;
|
|
140
|
+
return [
|
|
123
141
|
`### ${name} summary\n`,
|
|
124
142
|
`${(0, js_lib_1._since)(started)} spent`,
|
|
125
|
-
`${(0, js_lib_1._hc)(countIn)} / ${(0, js_lib_1._hc)(countOut)}
|
|
126
|
-
countErrors ? `${countErrors}
|
|
127
|
-
...Object.entries(extra).map(([k, v]) => `${k}: ${v}`),
|
|
128
|
-
]
|
|
143
|
+
`${(0, js_lib_1._hc)(countIn)} / ${(0, js_lib_1._hc)(countOut)} row(s) in / out`,
|
|
144
|
+
countErrors ? `${countErrors} error(s)` : '',
|
|
145
|
+
...Object.entries(extra).map(([k, v]) => `${k}: ${(0, js_lib_1._stringify)(v)}`),
|
|
146
|
+
]
|
|
147
|
+
.filter(Boolean)
|
|
148
|
+
.join('\n');
|
|
129
149
|
}
|
|
130
|
-
exports.
|
|
150
|
+
exports.transformMapStatsSummary = transformMapStatsSummary;
|
|
@@ -59,14 +59,19 @@ function transformMapSync(mapper, opt = {}) {
|
|
|
59
59
|
}
|
|
60
60
|
if (errorMode === js_lib_1.ErrorMode.THROW_IMMEDIATELY) {
|
|
61
61
|
isSettled = true;
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
62
|
+
try {
|
|
63
|
+
onDone?.({
|
|
64
|
+
ok: false,
|
|
65
|
+
collectedErrors,
|
|
66
|
+
countErrors: errors,
|
|
67
|
+
countIn: index + 1,
|
|
68
|
+
countOut,
|
|
69
|
+
started,
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
catch (err) {
|
|
73
|
+
logger.error(err);
|
|
74
|
+
}
|
|
70
75
|
// Emit error immediately
|
|
71
76
|
return cb(err);
|
|
72
77
|
}
|
|
@@ -80,27 +85,37 @@ function transformMapSync(mapper, opt = {}) {
|
|
|
80
85
|
// console.log('transformMap final')
|
|
81
86
|
logErrorStats(true);
|
|
82
87
|
if (collectedErrors.length) {
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
88
|
+
try {
|
|
89
|
+
onDone?.({
|
|
90
|
+
ok: false,
|
|
91
|
+
collectedErrors,
|
|
92
|
+
countErrors: errors,
|
|
93
|
+
countIn: index + 1,
|
|
94
|
+
countOut,
|
|
95
|
+
started,
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
catch (err) {
|
|
99
|
+
logger.error(err);
|
|
100
|
+
}
|
|
91
101
|
// emit Aggregated error
|
|
92
102
|
cb(new AggregateError(collectedErrors, `transformMapSync resulted in ${collectedErrors.length} error(s)`));
|
|
93
103
|
}
|
|
94
104
|
else {
|
|
95
105
|
// emit no error
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
106
|
+
try {
|
|
107
|
+
onDone?.({
|
|
108
|
+
ok: true,
|
|
109
|
+
collectedErrors,
|
|
110
|
+
countErrors: errors,
|
|
111
|
+
countIn: index + 1,
|
|
112
|
+
countOut,
|
|
113
|
+
started,
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
catch (err) {
|
|
117
|
+
logger.error(err);
|
|
118
|
+
}
|
|
104
119
|
cb();
|
|
105
120
|
}
|
|
106
121
|
},
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { TransformOptions, TransformTyped } from '../stream.model';
|
|
2
|
+
export interface TransformOffsetOptions extends TransformOptions {
|
|
3
|
+
/**
|
|
4
|
+
* How many items to skip (offset) in the stream.
|
|
5
|
+
*
|
|
6
|
+
* Nullish value (e.g 0 or undefined) would mean "no offset".
|
|
7
|
+
*/
|
|
8
|
+
offset?: number;
|
|
9
|
+
}
|
|
10
|
+
export declare function transformOffset<IN>(opt: TransformOffsetOptions): TransformTyped<IN, IN>;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.transformOffset = void 0;
|
|
4
|
+
const node_stream_1 = require("node:stream");
|
|
5
|
+
const index_1 = require("../../index");
|
|
6
|
+
function transformOffset(opt) {
|
|
7
|
+
const { offset } = opt;
|
|
8
|
+
if (!offset) {
|
|
9
|
+
// No offset - returning pass-through transform
|
|
10
|
+
return (0, index_1.transformNoOp)();
|
|
11
|
+
}
|
|
12
|
+
let i = 0; // so we start first chunk with 1
|
|
13
|
+
return new node_stream_1.Transform({
|
|
14
|
+
objectMode: true,
|
|
15
|
+
...opt,
|
|
16
|
+
transform(chunk, _, cb) {
|
|
17
|
+
if (++i <= offset) {
|
|
18
|
+
return cb(); // skip
|
|
19
|
+
}
|
|
20
|
+
cb(null, chunk);
|
|
21
|
+
},
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
exports.transformOffset = transformOffset;
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -47,6 +47,7 @@ export * from './stream/progressLogger'
|
|
|
47
47
|
export * from './stream/transform/transformChunk'
|
|
48
48
|
export * from './stream/transform/transformFilter'
|
|
49
49
|
export * from './stream/transform/transformLimit'
|
|
50
|
+
export * from './stream/transform/transformOffset'
|
|
50
51
|
export * from './stream/transform/transformLogProgress'
|
|
51
52
|
export * from './stream/transform/transformMap'
|
|
52
53
|
export * from './stream/transform/transformMapSimple'
|
|
@@ -305,7 +305,11 @@ export class ProgressLogger<T> implements Disposable {
|
|
|
305
305
|
)} rows with total RPS of ${yellow(rpsTotal)}`,
|
|
306
306
|
)
|
|
307
307
|
|
|
308
|
-
|
|
308
|
+
try {
|
|
309
|
+
this.cfg.onProgressDone?.(o)
|
|
310
|
+
} catch (err) {
|
|
311
|
+
logger.error(err)
|
|
312
|
+
}
|
|
309
313
|
}
|
|
310
314
|
}
|
|
311
315
|
}
|
|
@@ -40,10 +40,7 @@ export interface TransformLimitOptions extends TransformOptions {
|
|
|
40
40
|
*/
|
|
41
41
|
export class TransformLimit extends AbortableTransform {}
|
|
42
42
|
|
|
43
|
-
|
|
44
|
-
* 0 or falsy value means "no limit"
|
|
45
|
-
*/
|
|
46
|
-
export function transformLimit<IN>(opt: TransformLimitOptions = {}): TransformTyped<IN, IN> {
|
|
43
|
+
export function transformLimit<IN>(opt: TransformLimitOptions): TransformTyped<IN, IN> {
|
|
47
44
|
const { logger = console, limit, debug } = opt
|
|
48
45
|
|
|
49
46
|
if (!limit) {
|
|
@@ -2,19 +2,20 @@ import {
|
|
|
2
2
|
_anyToError,
|
|
3
3
|
_hc,
|
|
4
4
|
_since,
|
|
5
|
+
_stringify,
|
|
5
6
|
AbortableAsyncMapper,
|
|
6
7
|
AsyncPredicate,
|
|
7
8
|
CommonLogger,
|
|
8
9
|
END,
|
|
9
10
|
ErrorMode,
|
|
10
11
|
pFilter,
|
|
12
|
+
Promisable,
|
|
11
13
|
SKIP,
|
|
12
14
|
StringMap,
|
|
13
15
|
UnixTimestampMillisNumber,
|
|
14
16
|
} from '@naturalcycles/js-lib'
|
|
15
17
|
import through2Concurrent = require('through2-concurrent')
|
|
16
18
|
import { yellow } from '../../colors/colors'
|
|
17
|
-
import { appendToGithubSummary } from '../../fs/json2env'
|
|
18
19
|
import { AbortableTransform } from '../pipeline/pipeline'
|
|
19
20
|
import { TransformTyped } from '../stream.model'
|
|
20
21
|
import { pipelineClose } from '../stream.util'
|
|
@@ -62,9 +63,9 @@ export interface TransformMapOptions<IN = any, OUT = IN> {
|
|
|
62
63
|
* Callback is called **before** [possible] Aggregated error is thrown,
|
|
63
64
|
* and before [possible] THROW_IMMEDIATELY error.
|
|
64
65
|
*
|
|
65
|
-
* onDone callback will be
|
|
66
|
+
* onDone callback will be awaited before Error is thrown.
|
|
66
67
|
*/
|
|
67
|
-
onDone?: (stats: TransformMapStats) => any
|
|
68
|
+
onDone?: (stats: TransformMapStats) => Promisable<any>
|
|
68
69
|
|
|
69
70
|
/**
|
|
70
71
|
* Progress metric
|
|
@@ -91,6 +92,20 @@ export interface TransformMapStats {
|
|
|
91
92
|
started: UnixTimestampMillisNumber
|
|
92
93
|
}
|
|
93
94
|
|
|
95
|
+
export interface TransformMapStatsSummary extends TransformMapStats {
|
|
96
|
+
/**
|
|
97
|
+
* Name of the summary, defaults to `Transform`
|
|
98
|
+
*/
|
|
99
|
+
name?: string
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Allows to pass extra key-value object, which will be rendered as:
|
|
103
|
+
* key: value
|
|
104
|
+
* key2: value2
|
|
105
|
+
*/
|
|
106
|
+
extra?: StringMap<any>
|
|
107
|
+
}
|
|
108
|
+
|
|
94
109
|
// doesn't work, cause here we don't construct our Transform instance ourselves
|
|
95
110
|
// export class TransformMap extends AbortableTransform {}
|
|
96
111
|
|
|
@@ -137,14 +152,18 @@ export function transformMap<IN = any, OUT = IN>(
|
|
|
137
152
|
logErrorStats(true)
|
|
138
153
|
|
|
139
154
|
if (collectedErrors.length) {
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
155
|
+
try {
|
|
156
|
+
await onDone?.({
|
|
157
|
+
ok: false,
|
|
158
|
+
collectedErrors,
|
|
159
|
+
countErrors: errors,
|
|
160
|
+
countIn: index + 1,
|
|
161
|
+
countOut,
|
|
162
|
+
started,
|
|
163
|
+
})
|
|
164
|
+
} catch (err) {
|
|
165
|
+
logger.error(err)
|
|
166
|
+
}
|
|
148
167
|
|
|
149
168
|
// emit Aggregated error
|
|
150
169
|
cb(
|
|
@@ -156,14 +175,18 @@ export function transformMap<IN = any, OUT = IN>(
|
|
|
156
175
|
} else {
|
|
157
176
|
// emit no error
|
|
158
177
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
178
|
+
try {
|
|
179
|
+
await onDone?.({
|
|
180
|
+
ok: true,
|
|
181
|
+
collectedErrors,
|
|
182
|
+
countErrors: errors,
|
|
183
|
+
countIn: index + 1,
|
|
184
|
+
countOut,
|
|
185
|
+
started,
|
|
186
|
+
})
|
|
187
|
+
} catch (err) {
|
|
188
|
+
logger.error(err)
|
|
189
|
+
}
|
|
167
190
|
|
|
168
191
|
cb()
|
|
169
192
|
}
|
|
@@ -210,14 +233,20 @@ export function transformMap<IN = any, OUT = IN>(
|
|
|
210
233
|
|
|
211
234
|
if (errorMode === ErrorMode.THROW_IMMEDIATELY) {
|
|
212
235
|
isSettled = true
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
236
|
+
|
|
237
|
+
try {
|
|
238
|
+
await onDone?.({
|
|
239
|
+
ok: false,
|
|
240
|
+
collectedErrors,
|
|
241
|
+
countErrors: errors,
|
|
242
|
+
countIn: index + 1,
|
|
243
|
+
countOut,
|
|
244
|
+
started,
|
|
245
|
+
})
|
|
246
|
+
} catch (err) {
|
|
247
|
+
logger.error(err)
|
|
248
|
+
}
|
|
249
|
+
|
|
221
250
|
return cb(err) // Emit error immediately
|
|
222
251
|
}
|
|
223
252
|
|
|
@@ -237,18 +266,20 @@ export function transformMap<IN = any, OUT = IN>(
|
|
|
237
266
|
}
|
|
238
267
|
}
|
|
239
268
|
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
269
|
+
/**
|
|
270
|
+
* Renders TransformMapStatsSummary into a friendly string,
|
|
271
|
+
* to be used e.g in Github Actions summary or Slack.
|
|
272
|
+
*/
|
|
273
|
+
export function transformMapStatsSummary(summary: TransformMapStatsSummary): string {
|
|
274
|
+
const { countIn, countOut, countErrors, started, name = 'Transform', extra = {} } = summary
|
|
275
|
+
|
|
276
|
+
return [
|
|
277
|
+
`### ${name} summary\n`,
|
|
278
|
+
`${_since(started)} spent`,
|
|
279
|
+
`${_hc(countIn)} / ${_hc(countOut)} row(s) in / out`,
|
|
280
|
+
countErrors ? `${countErrors} error(s)` : '',
|
|
281
|
+
...Object.entries(extra).map(([k, v]) => `${k}: ${_stringify(v)}`),
|
|
282
|
+
]
|
|
283
|
+
.filter(Boolean)
|
|
284
|
+
.join('\n')
|
|
254
285
|
}
|
|
@@ -139,14 +139,20 @@ export function transformMapSync<IN = any, OUT = IN>(
|
|
|
139
139
|
|
|
140
140
|
if (errorMode === ErrorMode.THROW_IMMEDIATELY) {
|
|
141
141
|
isSettled = true
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
142
|
+
|
|
143
|
+
try {
|
|
144
|
+
onDone?.({
|
|
145
|
+
ok: false,
|
|
146
|
+
collectedErrors,
|
|
147
|
+
countErrors: errors,
|
|
148
|
+
countIn: index + 1,
|
|
149
|
+
countOut,
|
|
150
|
+
started,
|
|
151
|
+
})
|
|
152
|
+
} catch (err) {
|
|
153
|
+
logger.error(err)
|
|
154
|
+
}
|
|
155
|
+
|
|
150
156
|
// Emit error immediately
|
|
151
157
|
return cb(err as Error)
|
|
152
158
|
}
|
|
@@ -164,14 +170,18 @@ export function transformMapSync<IN = any, OUT = IN>(
|
|
|
164
170
|
logErrorStats(true)
|
|
165
171
|
|
|
166
172
|
if (collectedErrors.length) {
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
173
|
+
try {
|
|
174
|
+
onDone?.({
|
|
175
|
+
ok: false,
|
|
176
|
+
collectedErrors,
|
|
177
|
+
countErrors: errors,
|
|
178
|
+
countIn: index + 1,
|
|
179
|
+
countOut,
|
|
180
|
+
started,
|
|
181
|
+
})
|
|
182
|
+
} catch (err) {
|
|
183
|
+
logger.error(err)
|
|
184
|
+
}
|
|
175
185
|
|
|
176
186
|
// emit Aggregated error
|
|
177
187
|
cb(
|
|
@@ -183,14 +193,18 @@ export function transformMapSync<IN = any, OUT = IN>(
|
|
|
183
193
|
} else {
|
|
184
194
|
// emit no error
|
|
185
195
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
196
|
+
try {
|
|
197
|
+
onDone?.({
|
|
198
|
+
ok: true,
|
|
199
|
+
collectedErrors,
|
|
200
|
+
countErrors: errors,
|
|
201
|
+
countIn: index + 1,
|
|
202
|
+
countOut,
|
|
203
|
+
started,
|
|
204
|
+
})
|
|
205
|
+
} catch (err) {
|
|
206
|
+
logger.error(err)
|
|
207
|
+
}
|
|
194
208
|
|
|
195
209
|
cb()
|
|
196
210
|
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { Transform } from 'node:stream'
|
|
2
|
+
import { transformNoOp } from '../../index'
|
|
3
|
+
import { TransformOptions, TransformTyped } from '../stream.model'
|
|
4
|
+
|
|
5
|
+
export interface TransformOffsetOptions extends TransformOptions {
|
|
6
|
+
/**
|
|
7
|
+
* How many items to skip (offset) in the stream.
|
|
8
|
+
*
|
|
9
|
+
* Nullish value (e.g 0 or undefined) would mean "no offset".
|
|
10
|
+
*/
|
|
11
|
+
offset?: number
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function transformOffset<IN>(opt: TransformOffsetOptions): TransformTyped<IN, IN> {
|
|
15
|
+
const { offset } = opt
|
|
16
|
+
|
|
17
|
+
if (!offset) {
|
|
18
|
+
// No offset - returning pass-through transform
|
|
19
|
+
return transformNoOp()
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
let i = 0 // so we start first chunk with 1
|
|
23
|
+
return new Transform({
|
|
24
|
+
objectMode: true,
|
|
25
|
+
...opt,
|
|
26
|
+
transform(chunk: IN, _, cb) {
|
|
27
|
+
if (++i <= offset) {
|
|
28
|
+
return cb() // skip
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
cb(null, chunk)
|
|
32
|
+
},
|
|
33
|
+
})
|
|
34
|
+
}
|