@naturalcycles/nodejs-lib 12.59.0 → 12.60.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/ndjson/transformJsonParse.js +3 -3
- package/dist/stream/ndjson/transformToNDJson.js +2 -2
- package/dist/stream/sizeStack.d.ts +9 -0
- package/dist/stream/sizeStack.js +48 -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/transformLogProgress.d.ts +20 -0
- package/dist/stream/transform/transformLogProgress.js +36 -18
- package/dist/stream/transform/transformMap.d.ts +2 -4
- package/dist/stream/transform/transformMap.js +6 -11
- 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/writable/writableFork.js +1 -1
- package/dist/stream/writable/writablePushToArray.js +1 -1
- package/dist/stream/writable/writableVoid.js +1 -1
- package/dist/util/zip.util.d.ts +10 -2
- package/dist/util/zip.util.js +10 -3
- package/package.json +1 -1
- package/src/stream/ndjson/transformJsonParse.ts +3 -3
- package/src/stream/ndjson/transformToNDJson.ts +2 -2
- package/src/stream/sizeStack.ts +56 -0
- package/src/stream/transform/transformBuffer.ts +1 -1
- package/src/stream/transform/transformFilter.ts +6 -20
- package/src/stream/transform/transformLogProgress.ts +72 -23
- package/src/stream/transform/transformMap.ts +7 -14
- 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/writable/writableFork.ts +1 -1
- package/src/stream/writable/writablePushToArray.ts +1 -1
- package/src/stream/writable/writableVoid.ts +1 -1
- package/src/util/zip.util.ts +11 -3
|
@@ -33,17 +33,17 @@ export function transformJsonParse<OUT = any>(
|
|
|
33
33
|
const { strict = true, reviver } = opt
|
|
34
34
|
|
|
35
35
|
return new Transform({
|
|
36
|
-
|
|
36
|
+
writableObjectMode: false,
|
|
37
37
|
readableObjectMode: true,
|
|
38
|
-
transform(chunk: string,
|
|
38
|
+
transform(chunk: string, _, cb) {
|
|
39
39
|
try {
|
|
40
40
|
const data = JSON.parse(chunk, reviver)
|
|
41
41
|
cb(null, data)
|
|
42
42
|
} catch (err) {
|
|
43
|
-
// console.error(err)
|
|
44
43
|
if (strict) {
|
|
45
44
|
cb(err as Error) // emit error
|
|
46
45
|
} else {
|
|
46
|
+
console.error(err)
|
|
47
47
|
cb() // emit no error, but no result neither
|
|
48
48
|
}
|
|
49
49
|
}
|
|
@@ -37,9 +37,9 @@ export function transformToNDJson<IN = any>(
|
|
|
37
37
|
const { strict = true, separator = '\n', sortObjects = false, useFlatstr = false } = opt
|
|
38
38
|
|
|
39
39
|
return new Transform({
|
|
40
|
-
|
|
40
|
+
writableObjectMode: true,
|
|
41
41
|
readableObjectMode: false,
|
|
42
|
-
transform(chunk: IN,
|
|
42
|
+
transform(chunk: IN, _, cb) {
|
|
43
43
|
try {
|
|
44
44
|
if (sortObjects) {
|
|
45
45
|
chunk = _sortObjectDeep(chunk as any)
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { _hb, CommonLogger, NumberStack } from '@naturalcycles/js-lib'
|
|
2
|
+
import { yellow } from '../colors'
|
|
3
|
+
import { gzipBuffer } from '../util/zip.util'
|
|
4
|
+
|
|
5
|
+
export class SizeStack extends NumberStack {
|
|
6
|
+
constructor(public name: string, size: number) {
|
|
7
|
+
super(size)
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
total = 0
|
|
11
|
+
|
|
12
|
+
override push(item: any): this {
|
|
13
|
+
this.total += item
|
|
14
|
+
return super.push(item)
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
getStats(): string {
|
|
18
|
+
const pcs = this.percentiles([50, 90])
|
|
19
|
+
|
|
20
|
+
return [
|
|
21
|
+
this.name,
|
|
22
|
+
'avg',
|
|
23
|
+
yellow(_hb(this.avg())),
|
|
24
|
+
'p50',
|
|
25
|
+
yellow(_hb(pcs[50])),
|
|
26
|
+
'p90',
|
|
27
|
+
yellow(_hb(pcs[90])),
|
|
28
|
+
'total',
|
|
29
|
+
yellow(_hb(this.total)),
|
|
30
|
+
].join(' ')
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
static async countItem(
|
|
34
|
+
item: any,
|
|
35
|
+
logger: CommonLogger,
|
|
36
|
+
sizes?: SizeStack,
|
|
37
|
+
sizesZipped?: SizeStack,
|
|
38
|
+
): Promise<void> {
|
|
39
|
+
if (!sizes) return
|
|
40
|
+
|
|
41
|
+
// try-catch, because we don't want to fail the pipeline on logProgress
|
|
42
|
+
try {
|
|
43
|
+
const buf = Buffer.from(JSON.stringify(item))
|
|
44
|
+
sizes.push(buf.byteLength)
|
|
45
|
+
|
|
46
|
+
if (sizesZipped) {
|
|
47
|
+
const { byteLength } = await gzipBuffer(buf)
|
|
48
|
+
sizesZipped.push(byteLength)
|
|
49
|
+
}
|
|
50
|
+
} catch (err) {
|
|
51
|
+
logger.warn(
|
|
52
|
+
`transformLogProgress failed to JSON.stringify the chunk: ${(err as Error).message}`,
|
|
53
|
+
)
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
@@ -18,7 +18,7 @@ export function transformBuffer<IN = any>(opt: TransformBufferOptions): Transfor
|
|
|
18
18
|
return new Transform({
|
|
19
19
|
objectMode: true,
|
|
20
20
|
...opt,
|
|
21
|
-
transform(chunk,
|
|
21
|
+
transform(chunk, _, cb) {
|
|
22
22
|
buf.push(chunk)
|
|
23
23
|
|
|
24
24
|
if (buf.length >= batchSize) {
|
|
@@ -1,32 +1,18 @@
|
|
|
1
1
|
import { Transform } from 'stream'
|
|
2
2
|
import { AsyncPredicate, Predicate } from '@naturalcycles/js-lib'
|
|
3
3
|
import { TransformOptions, TransformTyped } from '../stream.model'
|
|
4
|
+
import { transformMap, TransformMapOptions } from './transformMap'
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
|
-
*
|
|
7
|
-
* So, it's recommended to use transformMap instead, that is both concurrent and has
|
|
8
|
-
* filtering feature by default.
|
|
7
|
+
* Just a convenience wrapper around `transformMap` that has built-in predicate filtering support.
|
|
9
8
|
*/
|
|
10
9
|
export function transformFilter<IN = any>(
|
|
11
10
|
predicate: AsyncPredicate<IN>,
|
|
12
|
-
opt:
|
|
11
|
+
opt: TransformMapOptions = {},
|
|
13
12
|
): TransformTyped<IN, IN> {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
return new Transform({
|
|
17
|
-
objectMode: true,
|
|
13
|
+
return transformMap(v => v, {
|
|
14
|
+
predicate,
|
|
18
15
|
...opt,
|
|
19
|
-
async transform(chunk: IN, _encoding, cb) {
|
|
20
|
-
try {
|
|
21
|
-
if (await predicate(chunk, index++)) {
|
|
22
|
-
cb(null, chunk) // pass through
|
|
23
|
-
} else {
|
|
24
|
-
cb() // signal that we've finished processing, but emit no output here
|
|
25
|
-
}
|
|
26
|
-
} catch (err) {
|
|
27
|
-
cb(err as Error)
|
|
28
|
-
}
|
|
29
|
-
},
|
|
30
16
|
})
|
|
31
17
|
}
|
|
32
18
|
|
|
@@ -42,7 +28,7 @@ export function transformFilterSync<IN = any>(
|
|
|
42
28
|
return new Transform({
|
|
43
29
|
objectMode: true,
|
|
44
30
|
...opt,
|
|
45
|
-
|
|
31
|
+
transform(chunk: IN, _, cb) {
|
|
46
32
|
try {
|
|
47
33
|
if (predicate(chunk, index++)) {
|
|
48
34
|
cb(null, chunk) // pass through
|
|
@@ -4,6 +4,7 @@ import { SimpleMovingAverage, _mb, _since, AnyObject, CommonLogger } from '@natu
|
|
|
4
4
|
import { dayjs } from '@naturalcycles/time-lib'
|
|
5
5
|
import { boldWhite, dimGrey, white, yellow } from '../../colors'
|
|
6
6
|
import { hasColors } from '../../colors/colors'
|
|
7
|
+
import { SizeStack } from '../sizeStack'
|
|
7
8
|
import { TransformOptions, TransformTyped } from '../stream.model'
|
|
8
9
|
|
|
9
10
|
export interface TransformLogProgressOptions<IN = any> extends TransformOptions {
|
|
@@ -103,6 +104,41 @@ export interface TransformLogProgressOptions<IN = any> extends TransformOptions
|
|
|
103
104
|
* Defaults to 1.
|
|
104
105
|
*/
|
|
105
106
|
batchSize?: number
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Experimental logging of item (shunk) sizes, when json-stringified.
|
|
110
|
+
*
|
|
111
|
+
* Defaults to false.
|
|
112
|
+
*
|
|
113
|
+
* @experimental
|
|
114
|
+
*/
|
|
115
|
+
logSizes?: boolean
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* How many last item sizes to keep in a buffer, to calculate stats (p50, p90, avg, etc).
|
|
119
|
+
* Defaults to 100_000.
|
|
120
|
+
* Cannot be Infinity.
|
|
121
|
+
*/
|
|
122
|
+
logSizesBuffer?: number
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Works in addition to `logSizes`. Adds "zipped sizes".
|
|
126
|
+
*
|
|
127
|
+
* @experimental
|
|
128
|
+
*/
|
|
129
|
+
logZippedSizes?: boolean
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
interface LogItem extends AnyObject {
|
|
133
|
+
heapUsed?: number
|
|
134
|
+
heapTotal?: number
|
|
135
|
+
rss?: number
|
|
136
|
+
peakRSS?: number
|
|
137
|
+
rssMinusHeap?: number
|
|
138
|
+
external?: number
|
|
139
|
+
arrayBuffers?: number
|
|
140
|
+
rps10?: number
|
|
141
|
+
rpsTotal?: number
|
|
106
142
|
}
|
|
107
143
|
|
|
108
144
|
const inspectOpt: InspectOptions = {
|
|
@@ -124,6 +160,9 @@ export function transformLogProgress<IN = any>(
|
|
|
124
160
|
peakRSS: logPeakRSS = true,
|
|
125
161
|
logRPS = true,
|
|
126
162
|
logEvery = 1000,
|
|
163
|
+
logSizes = false,
|
|
164
|
+
logSizesBuffer = 100_000,
|
|
165
|
+
logZippedSizes = false,
|
|
127
166
|
batchSize = 1,
|
|
128
167
|
extra,
|
|
129
168
|
logger = console,
|
|
@@ -138,15 +177,23 @@ export function transformLogProgress<IN = any>(
|
|
|
138
177
|
let progress = 0
|
|
139
178
|
let peakRSS = 0
|
|
140
179
|
|
|
180
|
+
const sizes = logSizes ? new SizeStack('json', logSizesBuffer) : undefined
|
|
181
|
+
const sizesZipped = logZippedSizes ? new SizeStack('json.gz', logSizesBuffer) : undefined
|
|
182
|
+
|
|
141
183
|
logStats() // initial
|
|
142
184
|
|
|
143
185
|
return new Transform({
|
|
144
186
|
objectMode: true,
|
|
145
187
|
...opt,
|
|
146
|
-
transform(chunk: IN,
|
|
188
|
+
transform(chunk: IN, _, cb) {
|
|
147
189
|
progress++
|
|
148
190
|
processedLastSecond++
|
|
149
191
|
|
|
192
|
+
if (sizes) {
|
|
193
|
+
// Check it, cause gzipping might be delayed here..
|
|
194
|
+
void SizeStack.countItem(chunk, logger, sizes, sizesZipped)
|
|
195
|
+
}
|
|
196
|
+
|
|
150
197
|
if (logProgress && progress % logEvery === 0) {
|
|
151
198
|
logStats(chunk, false, progress % logEvery10 === 0)
|
|
152
199
|
}
|
|
@@ -175,28 +222,30 @@ export function transformLogProgress<IN = any>(
|
|
|
175
222
|
const rps10 = Math.round(sma.push(lastRPS))
|
|
176
223
|
if (mem.rss > peakRSS) peakRSS = mem.rss
|
|
177
224
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
)
|
|
199
|
-
|
|
225
|
+
const o: LogItem = {
|
|
226
|
+
[final ? `${metric}_final` : metric]: batchedProgress,
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
if (extra) Object.assign(o, extra(chunk, progress))
|
|
230
|
+
if (logHeapUsed) o.heapUsed = _mb(mem.heapUsed)
|
|
231
|
+
if (logHeapTotal) o.heapTotal = _mb(mem.heapTotal)
|
|
232
|
+
if (logRss) o.rss = _mb(mem.rss)
|
|
233
|
+
if (logPeakRSS) o.peakRSS = _mb(peakRSS)
|
|
234
|
+
if (opt.rssMinusHeap) o.rssMinusHeap = _mb(mem.rss - mem.heapTotal)
|
|
235
|
+
if (opt.external) o.external = _mb(mem.external)
|
|
236
|
+
if (opt.arrayBuffers) o.arrayBuffers = _mb(mem.arrayBuffers || 0)
|
|
237
|
+
|
|
238
|
+
if (logRPS) Object.assign(o, { rps10, rpsTotal })
|
|
239
|
+
|
|
240
|
+
logger.log(inspect(o, inspectOpt))
|
|
241
|
+
|
|
242
|
+
if (sizes?.items.length) {
|
|
243
|
+
logger.log(sizes.getStats())
|
|
244
|
+
|
|
245
|
+
if (sizesZipped?.items.length) {
|
|
246
|
+
logger.log(sizesZipped.getStats())
|
|
247
|
+
}
|
|
248
|
+
}
|
|
200
249
|
|
|
201
250
|
if (tenx) {
|
|
202
251
|
let perHour: number | string =
|
|
@@ -26,9 +26,8 @@ export interface TransformMapOptions<IN = any, OUT = IN> {
|
|
|
26
26
|
* Predicate to filter outgoing results (after mapper).
|
|
27
27
|
* Allows to not emit all results.
|
|
28
28
|
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
* @default to filter out undefined/null values, but pass anything else
|
|
29
|
+
* Defaults to "pass everything" (including null, undefined, etc).
|
|
30
|
+
* Simpler way to exclude certain cases is to return SKIP symbol from the mapper.
|
|
32
31
|
*/
|
|
33
32
|
predicate?: AsyncPredicate<OUT>
|
|
34
33
|
|
|
@@ -60,10 +59,6 @@ export interface TransformMapOptions<IN = any, OUT = IN> {
|
|
|
60
59
|
logger?: CommonLogger
|
|
61
60
|
}
|
|
62
61
|
|
|
63
|
-
export function notNullishPredicate(item: any): boolean {
|
|
64
|
-
return item !== undefined && item !== null
|
|
65
|
-
}
|
|
66
|
-
|
|
67
62
|
// doesn't work, cause here we don't construct our Transform instance ourselves
|
|
68
63
|
// export class TransformMap extends AbortableTransform {}
|
|
69
64
|
|
|
@@ -85,7 +80,7 @@ export function transformMap<IN = any, OUT = IN>(
|
|
|
85
80
|
): TransformTyped<IN, OUT> {
|
|
86
81
|
const {
|
|
87
82
|
concurrency = 16,
|
|
88
|
-
predicate
|
|
83
|
+
predicate, // we now default to "no predicate" (meaning pass-everything)
|
|
89
84
|
errorMode = ErrorMode.THROW_IMMEDIATELY,
|
|
90
85
|
flattenArrayOutput,
|
|
91
86
|
onError,
|
|
@@ -116,14 +111,12 @@ export function transformMap<IN = any, OUT = IN>(
|
|
|
116
111
|
},
|
|
117
112
|
},
|
|
118
113
|
async function transformMapFn(this: AbortableTransform, chunk: IN, _, cb) {
|
|
119
|
-
index++
|
|
120
|
-
// console.log({chunk, _encoding})
|
|
121
|
-
|
|
122
114
|
// Stop processing if isSettled (either THROW_IMMEDIATELY was fired or END received)
|
|
123
115
|
if (isSettled) return cb()
|
|
124
116
|
|
|
117
|
+
const currentIndex = ++index
|
|
118
|
+
|
|
125
119
|
try {
|
|
126
|
-
const currentIndex = index // because we need to pass it to 2 functions - mapper and predicate. Refers to INPUT index (since it may return multiple outputs)
|
|
127
120
|
const res = await mapper(chunk, currentIndex)
|
|
128
121
|
const passedResults = await pFilter(
|
|
129
122
|
flattenArrayOutput && Array.isArray(res) ? res : [res],
|
|
@@ -132,14 +125,14 @@ export function transformMap<IN = any, OUT = IN>(
|
|
|
132
125
|
isSettled = true // will be checked later
|
|
133
126
|
return false
|
|
134
127
|
}
|
|
135
|
-
return r !== SKIP && (await predicate(r, currentIndex))
|
|
128
|
+
return r !== SKIP && (!predicate || (await predicate(r, currentIndex)))
|
|
136
129
|
},
|
|
137
130
|
)
|
|
138
131
|
|
|
139
132
|
passedResults.forEach(r => this.push(r))
|
|
140
133
|
|
|
141
134
|
if (isSettled) {
|
|
142
|
-
logger.log(`transformMap END received at index ${
|
|
135
|
+
logger.log(`transformMap END received at index ${currentIndex}`)
|
|
143
136
|
pipelineClose('transformMap', this, this.sourceReadable, this.streamDone, logger)
|
|
144
137
|
}
|
|
145
138
|
|
|
@@ -1,8 +1,16 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import {
|
|
2
|
+
AggregatedError,
|
|
3
|
+
CommonLogger,
|
|
4
|
+
END,
|
|
5
|
+
ErrorMode,
|
|
6
|
+
Mapper,
|
|
7
|
+
Predicate,
|
|
8
|
+
SKIP,
|
|
9
|
+
} from '@naturalcycles/js-lib'
|
|
3
10
|
import { yellow } from '../../colors'
|
|
11
|
+
import { AbortableTransform } from '../pipeline/pipeline'
|
|
4
12
|
import { TransformTyped } from '../stream.model'
|
|
5
|
-
import {
|
|
13
|
+
import { pipelineClose } from '../stream.util'
|
|
6
14
|
|
|
7
15
|
export interface TransformMapSyncOptions<IN = any, OUT = IN> {
|
|
8
16
|
/**
|
|
@@ -20,9 +28,8 @@ export interface TransformMapSyncOptions<IN = any, OUT = IN> {
|
|
|
20
28
|
* Predicate to filter outgoing results (after mapper).
|
|
21
29
|
* Allows to not emit all results.
|
|
22
30
|
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
* Set to `r => r` (passthrough predicate) to pass ANY value (including undefined/null)
|
|
31
|
+
* Defaults to "pass everything".
|
|
32
|
+
* Simpler way to skip individual entries is to return SKIP symbol.
|
|
26
33
|
*/
|
|
27
34
|
predicate?: Predicate<OUT>
|
|
28
35
|
|
|
@@ -47,6 +54,8 @@ export interface TransformMapSyncOptions<IN = any, OUT = IN> {
|
|
|
47
54
|
logger?: CommonLogger
|
|
48
55
|
}
|
|
49
56
|
|
|
57
|
+
export class TransformMapSync extends AbortableTransform {}
|
|
58
|
+
|
|
50
59
|
/**
|
|
51
60
|
* Sync (not async) version of transformMap.
|
|
52
61
|
* Supposedly faster, for cases when async is not needed.
|
|
@@ -58,7 +67,7 @@ export function transformMapSync<IN = any, OUT = IN>(
|
|
|
58
67
|
let index = -1
|
|
59
68
|
|
|
60
69
|
const {
|
|
61
|
-
predicate
|
|
70
|
+
predicate, // defaults to "no predicate" (pass everything)
|
|
62
71
|
errorMode = ErrorMode.THROW_IMMEDIATELY,
|
|
63
72
|
flattenArrayOutput = false,
|
|
64
73
|
onError,
|
|
@@ -66,34 +75,39 @@ export function transformMapSync<IN = any, OUT = IN>(
|
|
|
66
75
|
objectMode = true,
|
|
67
76
|
logger = console,
|
|
68
77
|
} = opt
|
|
69
|
-
let
|
|
78
|
+
let isSettled = false
|
|
70
79
|
let errors = 0
|
|
71
80
|
const collectedErrors: Error[] = [] // only used if errorMode == THROW_AGGREGATED
|
|
72
81
|
|
|
73
|
-
return new
|
|
82
|
+
return new TransformMapSync({
|
|
74
83
|
objectMode,
|
|
75
84
|
...opt,
|
|
76
|
-
transform(this:
|
|
77
|
-
// Stop processing if
|
|
78
|
-
if (
|
|
79
|
-
return cb()
|
|
80
|
-
}
|
|
85
|
+
transform(this: AbortableTransform, chunk: IN, _, cb) {
|
|
86
|
+
// Stop processing if isSettled
|
|
87
|
+
if (isSettled) return cb()
|
|
81
88
|
|
|
82
|
-
|
|
83
|
-
if (!predicate(chunk, ++index)) {
|
|
84
|
-
cb() // signal that we've finished processing, but emit no output here
|
|
85
|
-
return
|
|
86
|
-
}
|
|
89
|
+
const currentIndex = ++index
|
|
87
90
|
|
|
91
|
+
try {
|
|
88
92
|
// map and pass through
|
|
89
|
-
const v = mapper(chunk,
|
|
93
|
+
const v = mapper(chunk, currentIndex)
|
|
94
|
+
|
|
95
|
+
const passedResults = (flattenArrayOutput && Array.isArray(v) ? v : [v]).filter(r => {
|
|
96
|
+
if (r === END) {
|
|
97
|
+
isSettled = true // will be checked later
|
|
98
|
+
return false
|
|
99
|
+
}
|
|
100
|
+
return r !== SKIP && (!predicate || predicate(r, currentIndex))
|
|
101
|
+
})
|
|
90
102
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
103
|
+
passedResults.forEach(r => this.push(r))
|
|
104
|
+
|
|
105
|
+
if (isSettled) {
|
|
106
|
+
logger.log(`transformMapSync END received at index ${currentIndex}`)
|
|
107
|
+
pipelineClose('transformMapSync', this, this.sourceReadable, this.streamDone, logger)
|
|
96
108
|
}
|
|
109
|
+
|
|
110
|
+
cb() // done processing
|
|
97
111
|
} catch (err) {
|
|
98
112
|
logger.error(err)
|
|
99
113
|
errors++
|
|
@@ -107,7 +121,7 @@ export function transformMapSync<IN = any, OUT = IN>(
|
|
|
107
121
|
}
|
|
108
122
|
|
|
109
123
|
if (errorMode === ErrorMode.THROW_IMMEDIATELY) {
|
|
110
|
-
|
|
124
|
+
isSettled = true
|
|
111
125
|
// Emit error immediately
|
|
112
126
|
return cb(err as Error)
|
|
113
127
|
}
|
|
@@ -9,7 +9,7 @@ import { TransformTyped } from '../stream.model'
|
|
|
9
9
|
export function transformNoOp<T = any>(): TransformTyped<T, T> {
|
|
10
10
|
return new Transform({
|
|
11
11
|
objectMode: true,
|
|
12
|
-
transform(chunk: T,
|
|
12
|
+
transform(chunk: T, _, cb) {
|
|
13
13
|
cb(null, chunk)
|
|
14
14
|
},
|
|
15
15
|
})
|
|
@@ -17,16 +17,16 @@ export function transformTap<IN>(
|
|
|
17
17
|
opt: TransformTapOptions = {},
|
|
18
18
|
): TransformTyped<IN, IN> {
|
|
19
19
|
const { logger = console } = opt
|
|
20
|
-
let index =
|
|
20
|
+
let index = -1
|
|
21
21
|
|
|
22
22
|
return new Transform({
|
|
23
23
|
objectMode: true,
|
|
24
24
|
...opt,
|
|
25
|
-
async transform(chunk: IN,
|
|
25
|
+
async transform(chunk: IN, _, cb) {
|
|
26
26
|
// console.log('tap', chunk)
|
|
27
27
|
|
|
28
28
|
try {
|
|
29
|
-
await fn(chunk, index
|
|
29
|
+
await fn(chunk, ++index)
|
|
30
30
|
} catch (err) {
|
|
31
31
|
logger.error(err)
|
|
32
32
|
// suppressed error
|
|
@@ -10,7 +10,7 @@ export function transformToArray<IN>(opt: TransformOptions = {}): TransformTyped
|
|
|
10
10
|
return new Transform({
|
|
11
11
|
objectMode: true,
|
|
12
12
|
...opt,
|
|
13
|
-
transform(chunk: IN,
|
|
13
|
+
transform(chunk: IN, _, cb) {
|
|
14
14
|
res.push(chunk)
|
|
15
15
|
// callback to signal that we processed input, but not emitting any output
|
|
16
16
|
cb()
|
|
@@ -14,8 +14,8 @@ export function transformToString(): TransformTyped<Buffer, string> {
|
|
|
14
14
|
return new Transform({
|
|
15
15
|
objectMode: false,
|
|
16
16
|
readableObjectMode: true,
|
|
17
|
-
transform(chunk: Buffer,
|
|
18
|
-
// console.log(`enc: ${
|
|
17
|
+
transform(chunk: Buffer, _, cb) {
|
|
18
|
+
// console.log(`enc: ${_}`, chunk.toString())
|
|
19
19
|
cb(null, chunk.toString())
|
|
20
20
|
},
|
|
21
21
|
})
|
|
@@ -115,7 +115,7 @@ export function transformMultiThreaded<IN, OUT>(
|
|
|
115
115
|
}
|
|
116
116
|
},
|
|
117
117
|
},
|
|
118
|
-
async function transformMapFn(chunk: IN,
|
|
118
|
+
async function transformMapFn(chunk: IN, _, cb) {
|
|
119
119
|
// Freezing the index, because it may change due to concurrency
|
|
120
120
|
const currentIndex = ++index
|
|
121
121
|
|
|
@@ -31,7 +31,7 @@ export function writableFork<T>(
|
|
|
31
31
|
return new Writable({
|
|
32
32
|
objectMode: true,
|
|
33
33
|
...opt,
|
|
34
|
-
write(chunk: T,
|
|
34
|
+
write(chunk: T, _, cb) {
|
|
35
35
|
// Push/fork to all sub-streams
|
|
36
36
|
// No backpressure is ensured here, it'll push regardless of the
|
|
37
37
|
readables.forEach(readable => readable.push(chunk))
|
|
@@ -8,7 +8,7 @@ export function writablePushToArray<IN>(arr: IN[], opt: TransformOptions = {}):
|
|
|
8
8
|
return new Writable({
|
|
9
9
|
objectMode: true,
|
|
10
10
|
...opt,
|
|
11
|
-
write(chunk: IN,
|
|
11
|
+
write(chunk: IN, _, cb) {
|
|
12
12
|
arr.push(chunk)
|
|
13
13
|
// callback to signal that we processed input, but not emitting any output
|
|
14
14
|
cb()
|
package/src/util/zip.util.ts
CHANGED
|
@@ -8,9 +8,10 @@ const gzip = promisify(zlib.gzip.bind(zlib))
|
|
|
8
8
|
const gunzip = promisify(zlib.gunzip.bind(zlib))
|
|
9
9
|
|
|
10
10
|
// string > zip
|
|
11
|
+
|
|
11
12
|
/**
|
|
12
13
|
* zipBuffer uses `deflate`.
|
|
13
|
-
* It's 9 bytes shorter than gzip
|
|
14
|
+
* It's 9 bytes shorter than `gzip`.
|
|
14
15
|
*/
|
|
15
16
|
export async function zipBuffer(buf: Buffer, options: ZlibOptions = {}): Promise<Buffer> {
|
|
16
17
|
return await deflate(buf, options)
|
|
@@ -18,7 +19,7 @@ export async function zipBuffer(buf: Buffer, options: ZlibOptions = {}): Promise
|
|
|
18
19
|
|
|
19
20
|
/**
|
|
20
21
|
* gzipBuffer uses `gzip`
|
|
21
|
-
* It's 9 bytes longer than deflate
|
|
22
|
+
* It's 9 bytes longer than `deflate`.
|
|
22
23
|
*/
|
|
23
24
|
export async function gzipBuffer(buf: Buffer, options: ZlibOptions = {}): Promise<Buffer> {
|
|
24
25
|
return await gzip(buf, options)
|
|
@@ -33,11 +34,18 @@ export async function gunzipBuffer(buf: Buffer, options: ZlibOptions = {}): Prom
|
|
|
33
34
|
return await gunzip(buf, options)
|
|
34
35
|
}
|
|
35
36
|
|
|
36
|
-
|
|
37
|
+
/**
|
|
38
|
+
* zipString uses `deflate`.
|
|
39
|
+
* It's 9 bytes shorter than `gzip`.
|
|
40
|
+
*/
|
|
37
41
|
export async function zipString(s: string, options?: ZlibOptions): Promise<Buffer> {
|
|
38
42
|
return await zipBuffer(Buffer.from(s), options)
|
|
39
43
|
}
|
|
40
44
|
|
|
45
|
+
/**
|
|
46
|
+
* gzipString uses `gzip`.
|
|
47
|
+
* It's 9 bytes longer than `deflate`.
|
|
48
|
+
*/
|
|
41
49
|
export async function gzipString(s: string, options?: ZlibOptions): Promise<Buffer> {
|
|
42
50
|
return await gzipBuffer(Buffer.from(s), options)
|
|
43
51
|
}
|