@naturalcycles/nodejs-lib 15.17.0 → 15.18.1

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.
@@ -47,6 +47,10 @@ export function arrayToCSVString(arr, cfg = {}) {
47
47
  */
48
48
  export function arrayToCSVColumns(arr) {
49
49
  const cols = new Set();
50
- arr.forEach(row => Object.keys(row).forEach(col => cols.add(col)));
50
+ for (const row of arr) {
51
+ for (const col of Object.keys(row)) {
52
+ cols.add(col);
53
+ }
54
+ }
51
55
  return [...cols];
52
56
  }
package/dist/fs/fs2.js CHANGED
@@ -192,7 +192,9 @@ class FS2 {
192
192
  this.ensureDir(dirPath);
193
193
  return;
194
194
  }
195
- items.forEach(item => this.removePath(path.join(dirPath, item)));
195
+ for (const item of items) {
196
+ this.removePath(path.join(dirPath, item));
197
+ }
196
198
  }
197
199
  async emptyDirAsync(dirPath) {
198
200
  let items;
package/dist/fs/kpy.js CHANGED
@@ -41,7 +41,7 @@ export function kpySync(opt) {
41
41
  });
42
42
  kpyLogFilenames(opt, filenames);
43
43
  const overwrite = !opt.noOverwrite;
44
- filenames.forEach(filename => {
44
+ for (const filename of filenames) {
45
45
  const basename = path.basename(filename);
46
46
  const srcFilename = path.resolve(opt.baseDir, filename);
47
47
  const destFilename = path.resolve(opt.outputDir, opt.flat ? basename : filename);
@@ -56,7 +56,7 @@ export function kpySync(opt) {
56
56
  if (opt.verbose) {
57
57
  console.log(grey(` ${filename}`));
58
58
  }
59
- });
59
+ }
60
60
  kpyLogResult(opt, filenames, started);
61
61
  }
62
62
  function kpyPrepare(opt) {
@@ -1,7 +1,7 @@
1
1
  import { _hc } from '@naturalcycles/js-lib';
2
2
  import { _since } from '@naturalcycles/js-lib/datetime/time.util.js';
3
3
  import { _anyToError, ErrorMode } from '@naturalcycles/js-lib/error';
4
- import { pFilter } from '@naturalcycles/js-lib/promise/pFilter.js';
4
+ import { pMap } from '@naturalcycles/js-lib/promise/pMap.js';
5
5
  import { _stringify } from '@naturalcycles/js-lib/string/stringify.js';
6
6
  import { END, SKIP, } from '@naturalcycles/js-lib/types';
7
7
  import through2Concurrent from 'through2-concurrent';
@@ -77,15 +77,40 @@ export function transformMap(mapper, opt = {}) {
77
77
  const currentIndex = ++index;
78
78
  try {
79
79
  const res = await mapper(chunk, currentIndex);
80
- const passedResults = await pFilter(flattenArrayOutput && Array.isArray(res) ? res : [res], async (r) => {
81
- if (r === END) {
82
- isSettled = true; // will be checked later
83
- return false;
80
+ // Check for isSettled again, as it may happen while mapper was running
81
+ if (isSettled)
82
+ return cb();
83
+ // todo: consider retiring flattenArrayOutput from here
84
+ // and implementing it as a separate .flat transform/operator
85
+ const resInput = (flattenArrayOutput && Array.isArray(res) ? res : [res]);
86
+ if (predicate) {
87
+ await pMap(resInput, async (r) => {
88
+ if (r === END) {
89
+ isSettled = true; // will be checked later
90
+ return END;
91
+ }
92
+ if (r === SKIP)
93
+ return;
94
+ if (await predicate(r, currentIndex)) {
95
+ if (isSettled)
96
+ return END; // isSettled could have happened in parallel
97
+ countOut++;
98
+ this.push(r);
99
+ }
100
+ });
101
+ }
102
+ else {
103
+ for (const r of resInput) {
104
+ if (r === END) {
105
+ isSettled = true; // will be checked later
106
+ break;
107
+ }
108
+ if (r === SKIP)
109
+ continue;
110
+ countOut++;
111
+ this.push(r);
84
112
  }
85
- return r !== SKIP && (!predicate || (await predicate(r, currentIndex)));
86
- });
87
- countOut += passedResults.length;
88
- passedResults.forEach(r => this.push(r));
113
+ }
89
114
  if (isSettled) {
90
115
  logger.log(`transformMap END received at index ${currentIndex}`);
91
116
  pipelineClose('transformMap', this, this.sourceReadable, this.streamDone, logger);
@@ -29,15 +29,18 @@ export function transformMapSync(mapper, opt = {}) {
29
29
  try {
30
30
  // map and pass through
31
31
  const v = mapper(chunk, currentIndex);
32
- const passedResults = (flattenArrayOutput && Array.isArray(v) ? v : [v]).filter(r => {
32
+ // todo: consider retiring flattenArrayOutput option
33
+ const vInput = (flattenArrayOutput && Array.isArray(v) ? v : [v]);
34
+ for (const r of vInput) {
33
35
  if (r === END) {
34
36
  isSettled = true; // will be checked later
35
- return false;
37
+ break;
36
38
  }
37
- return r !== SKIP && (!predicate || predicate(r, currentIndex));
38
- });
39
- countOut += passedResults.length;
40
- passedResults.forEach(r => this.push(r));
39
+ if (r !== SKIP && (!predicate || predicate(r, currentIndex))) {
40
+ countOut++;
41
+ this.push(r);
42
+ }
43
+ }
41
44
  if (isSettled) {
42
45
  logger.log(`transformMapSync END received at index ${currentIndex}`);
43
46
  pipelineClose('transformMapSync', this, this.sourceReadable, this.streamDone, logger);
@@ -59,7 +59,9 @@ export function transformMultiThreaded(opt) {
59
59
  async final(cb) {
60
60
  try {
61
61
  // Push null (complete) to all sub-streams
62
- workers.forEach(worker => worker.postMessage(null));
62
+ for (const worker of workers) {
63
+ worker.postMessage(null);
64
+ }
63
65
  console.log(`transformMultiThreaded.final is waiting for all chains to be done`);
64
66
  await Promise.all(workerDonePromises);
65
67
  console.log(`transformMultiThreaded.final all chains done`);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@naturalcycles/nodejs-lib",
3
3
  "type": "module",
4
- "version": "15.17.0",
4
+ "version": "15.18.1",
5
5
  "dependencies": {
6
6
  "@naturalcycles/js-lib": "^15",
7
7
  "@types/js-yaml": "^4",
@@ -23,7 +23,7 @@
23
23
  },
24
24
  "devDependencies": {
25
25
  "@types/through2-concurrent": "^2",
26
- "@naturalcycles/dev-lib": "18.4.2"
26
+ "@naturalcycles/dev-lib": "19.27.0"
27
27
  },
28
28
  "exports": {
29
29
  ".": "./dist/index.js",
@@ -78,6 +78,10 @@ export function arrayToCSVString(arr: AnyObject[], cfg: CSVWriterConfig = {}): s
78
78
  */
79
79
  export function arrayToCSVColumns(arr: AnyObject[]): string[] {
80
80
  const cols = new Set<string>()
81
- arr.forEach(row => Object.keys(row).forEach(col => cols.add(col)))
81
+ for (const row of arr) {
82
+ for (const col of Object.keys(row)) {
83
+ cols.add(col)
84
+ }
85
+ }
82
86
  return [...cols]
83
87
  }
package/src/fs/fs2.ts CHANGED
@@ -219,7 +219,9 @@ class FS2 {
219
219
  return
220
220
  }
221
221
 
222
- items.forEach(item => this.removePath(path.join(dirPath, item)))
222
+ for (const item of items) {
223
+ this.removePath(path.join(dirPath, item))
224
+ }
223
225
  }
224
226
 
225
227
  async emptyDirAsync(dirPath: string): Promise<void> {
package/src/fs/kpy.ts CHANGED
@@ -97,7 +97,7 @@ export function kpySync(opt: KpyOptions): void {
97
97
 
98
98
  const overwrite = !opt.noOverwrite
99
99
 
100
- filenames.forEach(filename => {
100
+ for (const filename of filenames) {
101
101
  const basename = path.basename(filename)
102
102
  const srcFilename = path.resolve(opt.baseDir, filename)
103
103
  const destFilename = path.resolve(opt.outputDir, opt.flat ? basename : filename)
@@ -113,7 +113,7 @@ export function kpySync(opt: KpyOptions): void {
113
113
  if (opt.verbose) {
114
114
  console.log(grey(` ${filename}`))
115
115
  }
116
- })
116
+ }
117
117
 
118
118
  kpyLogResult(opt, filenames, started)
119
119
  }
@@ -2,7 +2,7 @@ import { _hc } from '@naturalcycles/js-lib'
2
2
  import { _since } from '@naturalcycles/js-lib/datetime/time.util.js'
3
3
  import { _anyToError, ErrorMode } from '@naturalcycles/js-lib/error'
4
4
  import type { CommonLogger } from '@naturalcycles/js-lib/log'
5
- import { pFilter } from '@naturalcycles/js-lib/promise/pFilter.js'
5
+ import { pMap } from '@naturalcycles/js-lib/promise/pMap.js'
6
6
  import { _stringify } from '@naturalcycles/js-lib/string/stringify.js'
7
7
  import {
8
8
  type AbortableAsyncMapper,
@@ -203,20 +203,41 @@ export function transformMap<IN = any, OUT = IN>(
203
203
  const currentIndex = ++index
204
204
 
205
205
  try {
206
- const res = await mapper(chunk, currentIndex)
207
- const passedResults = await pFilter(
208
- flattenArrayOutput && Array.isArray(res) ? res : [res],
209
- async r => {
206
+ const res: OUT | typeof SKIP | typeof END = await mapper(chunk, currentIndex)
207
+ // Check for isSettled again, as it may happen while mapper was running
208
+ if (isSettled) return cb()
209
+ // todo: consider retiring flattenArrayOutput from here
210
+ // and implementing it as a separate .flat transform/operator
211
+ const resInput = (flattenArrayOutput && Array.isArray(res) ? res : [res]) as (
212
+ | OUT
213
+ | typeof SKIP
214
+ | typeof END
215
+ )[]
216
+
217
+ if (predicate) {
218
+ await pMap(resInput, async r => {
210
219
  if (r === END) {
211
220
  isSettled = true // will be checked later
212
- return false
221
+ return END
213
222
  }
214
- return r !== SKIP && (!predicate || (await predicate(r, currentIndex)))
215
- },
216
- )
217
-
218
- countOut += passedResults.length
219
- passedResults.forEach(r => this.push(r))
223
+ if (r === SKIP) return
224
+ if (await predicate(r, currentIndex)) {
225
+ if (isSettled) return END // isSettled could have happened in parallel
226
+ countOut++
227
+ this.push(r)
228
+ }
229
+ })
230
+ } else {
231
+ for (const r of resInput) {
232
+ if (r === END) {
233
+ isSettled = true // will be checked later
234
+ break
235
+ }
236
+ if (r === SKIP) continue
237
+ countOut++
238
+ this.push(r)
239
+ }
240
+ }
220
241
 
221
242
  if (isSettled) {
222
243
  logger.log(`transformMap END received at index ${currentIndex}`)
@@ -102,17 +102,23 @@ export function transformMapSync<IN = any, OUT = IN>(
102
102
  try {
103
103
  // map and pass through
104
104
  const v = mapper(chunk, currentIndex)
105
-
106
- const passedResults = (flattenArrayOutput && Array.isArray(v) ? v : [v]).filter(r => {
105
+ // todo: consider retiring flattenArrayOutput option
106
+ const vInput = (flattenArrayOutput && Array.isArray(v) ? v : [v]) as (
107
+ | OUT
108
+ | typeof SKIP
109
+ | typeof END
110
+ )[]
111
+
112
+ for (const r of vInput) {
107
113
  if (r === END) {
108
114
  isSettled = true // will be checked later
109
- return false
115
+ break
110
116
  }
111
- return r !== SKIP && (!predicate || predicate(r, currentIndex))
112
- })
113
-
114
- countOut += passedResults.length
115
- passedResults.forEach(r => this.push(r))
117
+ if (r !== SKIP && (!predicate || predicate(r, currentIndex))) {
118
+ countOut++
119
+ this.push(r)
120
+ }
121
+ }
116
122
 
117
123
  if (isSettled) {
118
124
  logger.log(`transformMapSync END received at index ${currentIndex}`)
@@ -104,7 +104,9 @@ export function transformMultiThreaded<IN, OUT>(
104
104
  async final(cb) {
105
105
  try {
106
106
  // Push null (complete) to all sub-streams
107
- workers.forEach(worker => worker.postMessage(null))
107
+ for (const worker of workers) {
108
+ worker.postMessage(null)
109
+ }
108
110
 
109
111
  console.log(`transformMultiThreaded.final is waiting for all chains to be done`)
110
112
  await Promise.all(workerDonePromises)