@naturalcycles/nodejs-lib 13.16.0 → 13.18.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.
@@ -30,7 +30,7 @@ export declare function appendToGithubOutput(obj: AnyObject, prefix?: string): v
30
30
  /**
31
31
  * https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#adding-a-job-summary
32
32
  */
33
- export declare function appendToGithubSummary(str: string): void;
33
+ export declare function appendToGithubSummary(...lines: string[]): void;
34
34
  /**
35
35
  * Turns Object with keys/values into a *.sh script that exports all keys as values.
36
36
  *
@@ -81,10 +81,11 @@ exports.appendToGithubOutput = appendToGithubOutput;
81
81
  /**
82
82
  * https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#adding-a-job-summary
83
83
  */
84
- function appendToGithubSummary(str) {
84
+ function appendToGithubSummary(...lines) {
85
85
  const { GITHUB_STEP_SUMMARY } = process.env;
86
86
  if (GITHUB_STEP_SUMMARY) {
87
- node_fs_1.default.appendFileSync(GITHUB_STEP_SUMMARY, str + '\n');
87
+ const str = lines.join('\n') + '\n';
88
+ node_fs_1.default.appendFileSync(GITHUB_STEP_SUMMARY, str);
88
89
  console.log(`GITHUB_STEP_SUMMARY appended:\n${str}`);
89
90
  }
90
91
  }
@@ -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
  }
@@ -1,4 +1,4 @@
1
- import { AbortableAsyncMapper, AsyncPredicate, CommonLogger, END, ErrorMode, SKIP } 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
  *
@@ -61,6 +61,19 @@ export interface TransformMapStats {
61
61
  countErrors: number;
62
62
  countIn: number;
63
63
  countOut: number;
64
+ started: UnixTimestampMillisNumber;
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>;
64
77
  }
65
78
  /**
66
79
  * Like pMap, but for streams.
@@ -75,3 +88,8 @@ export interface TransformMapStats {
75
88
  * If an Array is returned by `mapper` - it will be flattened and multiple results will be emitted from it. Tested by Array.isArray().
76
89
  */
77
90
  export declare function transformMap<IN = any, OUT = IN>(mapper: AbortableAsyncMapper<IN, OUT | typeof SKIP | typeof END>, opt?: TransformMapOptions<IN, OUT>): TransformTyped<IN, OUT>;
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,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- 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");
@@ -22,6 +22,7 @@ const stream_util_1 = require("../stream.util");
22
22
  function transformMap(mapper, opt = {}) {
23
23
  const { concurrency = 16, predicate, // we now default to "no predicate" (meaning pass-everything)
24
24
  errorMode = js_lib_1.ErrorMode.THROW_IMMEDIATELY, flattenArrayOutput, onError, onDone, metric = 'stream', logger = console, } = opt;
25
+ const started = Date.now();
25
26
  let index = -1;
26
27
  let countOut = 0;
27
28
  let isSettled = false;
@@ -33,25 +34,37 @@ function transformMap(mapper, opt = {}) {
33
34
  // console.log('transformMap final')
34
35
  logErrorStats(true);
35
36
  if (collectedErrors.length) {
36
- onDone?.({
37
- ok: false,
38
- collectedErrors,
39
- countErrors: errors,
40
- countIn: index + 1,
41
- countOut,
42
- });
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
+ }
43
50
  // emit Aggregated error
44
51
  cb(new AggregateError(collectedErrors, `transformMap resulted in ${collectedErrors.length} error(s)`));
45
52
  }
46
53
  else {
47
54
  // emit no error
48
- onDone?.({
49
- ok: true,
50
- collectedErrors,
51
- countErrors: errors,
52
- countIn: index + 1,
53
- countOut,
54
- });
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
+ }
55
68
  cb();
56
69
  }
57
70
  },
@@ -89,13 +102,19 @@ function transformMap(mapper, opt = {}) {
89
102
  }
90
103
  if (errorMode === js_lib_1.ErrorMode.THROW_IMMEDIATELY) {
91
104
  isSettled = true;
92
- onDone?.({
93
- ok: false,
94
- collectedErrors,
95
- countErrors: errors,
96
- countIn: index + 1,
97
- countOut,
98
- });
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
+ }
99
118
  return cb(err); // Emit error immediately
100
119
  }
101
120
  if (errorMode === js_lib_1.ErrorMode.THROW_AGGREGATED) {
@@ -112,3 +131,20 @@ function transformMap(mapper, opt = {}) {
112
131
  }
113
132
  }
114
133
  exports.transformMap = transformMap;
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 [
141
+ `### ${name} summary\n`,
142
+ `${(0, js_lib_1._since)(started)} spent`,
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');
149
+ }
150
+ exports.transformMapStatsSummary = transformMapStatsSummary;
@@ -15,6 +15,7 @@ exports.TransformMapSync = TransformMapSync;
15
15
  function transformMapSync(mapper, opt = {}) {
16
16
  const { predicate, // defaults to "no predicate" (pass everything)
17
17
  errorMode = js_lib_1.ErrorMode.THROW_IMMEDIATELY, flattenArrayOutput = false, onError, onDone, metric = 'stream', objectMode = true, logger = console, } = opt;
18
+ const started = Date.now();
18
19
  let index = -1;
19
20
  let countOut = 0;
20
21
  let isSettled = false;
@@ -58,13 +59,19 @@ function transformMapSync(mapper, opt = {}) {
58
59
  }
59
60
  if (errorMode === js_lib_1.ErrorMode.THROW_IMMEDIATELY) {
60
61
  isSettled = true;
61
- onDone?.({
62
- ok: false,
63
- collectedErrors,
64
- countErrors: errors,
65
- countIn: index + 1,
66
- countOut,
67
- });
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
+ }
68
75
  // Emit error immediately
69
76
  return cb(err);
70
77
  }
@@ -78,25 +85,37 @@ function transformMapSync(mapper, opt = {}) {
78
85
  // console.log('transformMap final')
79
86
  logErrorStats(true);
80
87
  if (collectedErrors.length) {
81
- onDone?.({
82
- ok: false,
83
- collectedErrors,
84
- countErrors: errors,
85
- countIn: index + 1,
86
- countOut,
87
- });
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
+ }
88
101
  // emit Aggregated error
89
102
  cb(new AggregateError(collectedErrors, `transformMapSync resulted in ${collectedErrors.length} error(s)`));
90
103
  }
91
104
  else {
92
105
  // emit no error
93
- onDone?.({
94
- ok: true,
95
- collectedErrors,
96
- countErrors: errors,
97
- countIn: index + 1,
98
- countOut,
99
- });
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
+ }
100
119
  cb();
101
120
  }
102
121
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@naturalcycles/nodejs-lib",
3
- "version": "13.16.0",
3
+ "version": "13.18.0",
4
4
  "scripts": {
5
5
  "prepare": "husky",
6
6
  "docs-serve": "vuepress dev docs",
@@ -120,10 +120,11 @@ export function appendToGithubOutput(obj: AnyObject, prefix = ''): void {
120
120
  /**
121
121
  * https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#adding-a-job-summary
122
122
  */
123
- export function appendToGithubSummary(str: string): void {
123
+ export function appendToGithubSummary(...lines: string[]): void {
124
124
  const { GITHUB_STEP_SUMMARY } = process.env
125
125
  if (GITHUB_STEP_SUMMARY) {
126
- fs.appendFileSync(GITHUB_STEP_SUMMARY, str + '\n')
126
+ const str = lines.join('\n') + '\n'
127
+ fs.appendFileSync(GITHUB_STEP_SUMMARY, str)
127
128
  console.log(`GITHUB_STEP_SUMMARY appended:\n${str}`)
128
129
  }
129
130
  }
@@ -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
  }
@@ -1,12 +1,18 @@
1
1
  import {
2
2
  _anyToError,
3
+ _hc,
4
+ _since,
5
+ _stringify,
3
6
  AbortableAsyncMapper,
4
7
  AsyncPredicate,
5
8
  CommonLogger,
6
9
  END,
7
10
  ErrorMode,
8
11
  pFilter,
12
+ Promisable,
9
13
  SKIP,
14
+ StringMap,
15
+ UnixTimestampMillisNumber,
10
16
  } from '@naturalcycles/js-lib'
11
17
  import through2Concurrent = require('through2-concurrent')
12
18
  import { yellow } from '../../colors/colors'
@@ -57,9 +63,9 @@ export interface TransformMapOptions<IN = any, OUT = IN> {
57
63
  * Callback is called **before** [possible] Aggregated error is thrown,
58
64
  * and before [possible] THROW_IMMEDIATELY error.
59
65
  *
60
- * onDone callback will be called before Error is thrown.
66
+ * onDone callback will be awaited before Error is thrown.
61
67
  */
62
- onDone?: (stats: TransformMapStats) => any
68
+ onDone?: (stats: TransformMapStats) => Promisable<any>
63
69
 
64
70
  /**
65
71
  * Progress metric
@@ -83,6 +89,21 @@ export interface TransformMapStats {
83
89
  countErrors: number
84
90
  countIn: number
85
91
  countOut: number
92
+ started: UnixTimestampMillisNumber
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>
86
107
  }
87
108
 
88
109
  // doesn't work, cause here we don't construct our Transform instance ourselves
@@ -115,6 +136,7 @@ export function transformMap<IN = any, OUT = IN>(
115
136
  logger = console,
116
137
  } = opt
117
138
 
139
+ const started = Date.now()
118
140
  let index = -1
119
141
  let countOut = 0
120
142
  let isSettled = false
@@ -130,13 +152,18 @@ export function transformMap<IN = any, OUT = IN>(
130
152
  logErrorStats(true)
131
153
 
132
154
  if (collectedErrors.length) {
133
- onDone?.({
134
- ok: false,
135
- collectedErrors,
136
- countErrors: errors,
137
- countIn: index + 1,
138
- countOut,
139
- })
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
+ }
140
167
 
141
168
  // emit Aggregated error
142
169
  cb(
@@ -148,13 +175,18 @@ export function transformMap<IN = any, OUT = IN>(
148
175
  } else {
149
176
  // emit no error
150
177
 
151
- onDone?.({
152
- ok: true,
153
- collectedErrors,
154
- countErrors: errors,
155
- countIn: index + 1,
156
- countOut,
157
- })
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
+ }
158
190
 
159
191
  cb()
160
192
  }
@@ -201,13 +233,20 @@ export function transformMap<IN = any, OUT = IN>(
201
233
 
202
234
  if (errorMode === ErrorMode.THROW_IMMEDIATELY) {
203
235
  isSettled = true
204
- onDone?.({
205
- ok: false,
206
- collectedErrors,
207
- countErrors: errors,
208
- countIn: index + 1,
209
- countOut,
210
- })
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
+
211
250
  return cb(err) // Emit error immediately
212
251
  }
213
252
 
@@ -226,3 +265,21 @@ export function transformMap<IN = any, OUT = IN>(
226
265
  logger.log(`${metric} ${final ? 'final ' : ''}errors: ${yellow(errors)}`)
227
266
  }
228
267
  }
268
+
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')
285
+ }
@@ -88,6 +88,7 @@ export function transformMapSync<IN = any, OUT = IN>(
88
88
  logger = console,
89
89
  } = opt
90
90
 
91
+ const started = Date.now()
91
92
  let index = -1
92
93
  let countOut = 0
93
94
  let isSettled = false
@@ -138,13 +139,20 @@ export function transformMapSync<IN = any, OUT = IN>(
138
139
 
139
140
  if (errorMode === ErrorMode.THROW_IMMEDIATELY) {
140
141
  isSettled = true
141
- onDone?.({
142
- ok: false,
143
- collectedErrors,
144
- countErrors: errors,
145
- countIn: index + 1,
146
- countOut,
147
- })
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
+
148
156
  // Emit error immediately
149
157
  return cb(err as Error)
150
158
  }
@@ -162,13 +170,18 @@ export function transformMapSync<IN = any, OUT = IN>(
162
170
  logErrorStats(true)
163
171
 
164
172
  if (collectedErrors.length) {
165
- onDone?.({
166
- ok: false,
167
- collectedErrors,
168
- countErrors: errors,
169
- countIn: index + 1,
170
- countOut,
171
- })
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
+ }
172
185
 
173
186
  // emit Aggregated error
174
187
  cb(
@@ -180,13 +193,18 @@ export function transformMapSync<IN = any, OUT = IN>(
180
193
  } else {
181
194
  // emit no error
182
195
 
183
- onDone?.({
184
- ok: true,
185
- collectedErrors,
186
- countErrors: errors,
187
- countIn: index + 1,
188
- countOut,
189
- })
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
+ }
190
208
 
191
209
  cb()
192
210
  }