@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 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
- this.cfg.onProgressDone?.(o);
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 called before Error is thrown.
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
- export declare function appendTransformMapStatsToGithubSummary(stats: TransformMapStats & {
80
- name?: string;
81
- extra?: StringMap<any>;
82
- }): void;
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.appendTransformMapStatsToGithubSummary = exports.transformMap = void 0;
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
- onDone?.({
39
- ok: false,
40
- collectedErrors,
41
- countErrors: errors,
42
- countIn: index + 1,
43
- countOut,
44
- started,
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
- onDone?.({
52
- ok: true,
53
- collectedErrors,
54
- countErrors: errors,
55
- countIn: index + 1,
56
- countOut,
57
- started,
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
- onDone?.({
97
- ok: false,
98
- collectedErrors,
99
- countErrors: errors,
100
- countIn: index + 1,
101
- countOut,
102
- started,
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
- function appendTransformMapStatsToGithubSummary(stats) {
121
- const { countIn, countOut, countErrors, started, name = 'Transform', extra = {} } = stats;
122
- (0, json2env_1.appendToGithubSummary)(...[
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)} rows in / out`,
126
- countErrors ? `${countErrors} errors` : '',
127
- ...Object.entries(extra).map(([k, v]) => `${k}: ${v}`),
128
- ].filter(Boolean));
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.appendTransformMapStatsToGithubSummary = appendTransformMapStatsToGithubSummary;
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
- onDone?.({
63
- ok: false,
64
- collectedErrors,
65
- countErrors: errors,
66
- countIn: index + 1,
67
- countOut,
68
- started,
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
- onDone?.({
84
- ok: false,
85
- collectedErrors,
86
- countErrors: errors,
87
- countIn: index + 1,
88
- countOut,
89
- started,
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
- onDone?.({
97
- ok: true,
98
- collectedErrors,
99
- countErrors: errors,
100
- countIn: index + 1,
101
- countOut,
102
- started,
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@naturalcycles/nodejs-lib",
3
- "version": "13.17.0",
3
+ "version": "13.19.0",
4
4
  "scripts": {
5
5
  "prepare": "husky",
6
6
  "docs-serve": "vuepress dev docs",
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
- this.cfg.onProgressDone?.(o)
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 called before Error is thrown.
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
- onDone?.({
141
- ok: false,
142
- collectedErrors,
143
- countErrors: errors,
144
- countIn: index + 1,
145
- countOut,
146
- started,
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
- onDone?.({
160
- ok: true,
161
- collectedErrors,
162
- countErrors: errors,
163
- countIn: index + 1,
164
- countOut,
165
- started,
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
- onDone?.({
214
- ok: false,
215
- collectedErrors,
216
- countErrors: errors,
217
- countIn: index + 1,
218
- countOut,
219
- started,
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
- export function appendTransformMapStatsToGithubSummary(
241
- stats: TransformMapStats & { name?: string; extra?: StringMap<any> },
242
- ): void {
243
- const { countIn, countOut, countErrors, started, name = 'Transform', extra = {} } = stats
244
-
245
- appendToGithubSummary(
246
- ...[
247
- `### ${name} summary\n`,
248
- `${_since(started)} spent`,
249
- `${_hc(countIn)} / ${_hc(countOut)} rows in / out`,
250
- countErrors ? `${countErrors} errors` : '',
251
- ...Object.entries(extra).map(([k, v]) => `${k}: ${v}`),
252
- ].filter(Boolean),
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
- onDone?.({
143
- ok: false,
144
- collectedErrors,
145
- countErrors: errors,
146
- countIn: index + 1,
147
- countOut,
148
- started,
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
- onDone?.({
168
- ok: false,
169
- collectedErrors,
170
- countErrors: errors,
171
- countIn: index + 1,
172
- countOut,
173
- started,
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
- onDone?.({
187
- ok: true,
188
- collectedErrors,
189
- countErrors: errors,
190
- countIn: index + 1,
191
- countOut,
192
- started,
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
+ }