@naturalcycles/nodejs-lib 12.64.0 → 12.65.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/fs/del.js CHANGED
@@ -55,14 +55,14 @@ async function del(_opt) {
55
55
  }));
56
56
  const dirnamesSorted = dirnames.sort().reverse();
57
57
  // console.log({ dirnamesSorted })
58
- const deletedDirs = await (0, js_lib_1.pFilter)(dirnamesSorted, async (dirpath) => {
58
+ const deletedDirs = [];
59
+ for await (const dirpath of dirnamesSorted) {
59
60
  if (await isEmptyDir(dirpath)) {
60
61
  // console.log(`empty dir: ${dirpath}`)
61
62
  await fs.remove(dirpath);
62
- return true;
63
+ deletedDirs.push(dirpath);
63
64
  }
64
- return false;
65
- }, { concurrency: 1 });
65
+ }
66
66
  if (verbose || debug)
67
67
  console.log({ deletedDirs });
68
68
  if (!silent) {
@@ -135,7 +135,23 @@ function gotErrorHook(opt = {}) {
135
135
  .join('\n');
136
136
  const stack = err.options.context?.err?.stack;
137
137
  if (stack) {
138
- err.stack += '\n --' + stack.replace('Error: RequestError', '');
138
+ const originalStack = err.stack.split('\n');
139
+ let originalStackIndex = originalStack.findIndex(line => line.includes(' at '));
140
+ if (originalStackIndex === -1)
141
+ originalStackIndex = originalStack.length - 1;
142
+ // Skipping first line as it has RequestError: ...
143
+ // Skipping second line as it's known to be from e.g at got_1.default.extend.handlers
144
+ const syntheticStack = stack.split('\n').slice(2);
145
+ let firstNonNodeModulesIndex = syntheticStack.findIndex(line => !line.includes('node_modules'));
146
+ if (firstNonNodeModulesIndex === -1)
147
+ firstNonNodeModulesIndex = 0;
148
+ err.stack = [
149
+ // First lines of original error
150
+ ...originalStack.slice(0, originalStackIndex),
151
+ // Other lines from "Synthetic error"
152
+ ...syntheticStack.slice(firstNonNodeModulesIndex),
153
+ ].join('\n');
154
+ // err.stack += '\n --' + stack.replace('Error: RequestError', '')
139
155
  }
140
156
  return err;
141
157
  };
@@ -196,7 +212,8 @@ function gotBeforeRetryHook(opt) {
196
212
  function gotAfterResponseHook(opt = {}) {
197
213
  return resp => {
198
214
  const success = resp.statusCode >= 200 && resp.statusCode < 400;
199
- if (opt.logFinished) {
215
+ // Errors are not logged here, as they're logged by gotErrorHook
216
+ if (opt.logFinished && success) {
200
217
  const { started, retryCount } = resp.request.options.context;
201
218
  const { url, prefixUrl, method } = resp.request.options;
202
219
  const shortUrl = getShortUrl(opt, url, prefixUrl);
@@ -26,5 +26,7 @@ export interface RunScriptOptions {
26
26
  * - No need to add `.catch(err => { console.error(err); process.exit(1) })`
27
27
  *
28
28
  * This function is kept light, dependency-free, exported separately.
29
+ *
30
+ * Set env DEBUG_RUN_SCRIPT for extra debugging.
29
31
  */
30
32
  export declare function runScript(fn: (...args: any[]) => any, opt?: RunScriptOptions): void;
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.runScript = void 0;
4
+ const { DEBUG_RUN_SCRIPT } = process.env;
4
5
  /**
5
6
  * Use it in your top-level scripts like this:
6
7
  *
@@ -16,6 +17,8 @@ exports.runScript = void 0;
16
17
  * - No need to add `.catch(err => { console.error(err); process.exit(1) })`
17
18
  *
18
19
  * This function is kept light, dependency-free, exported separately.
20
+ *
21
+ * Set env DEBUG_RUN_SCRIPT for extra debugging.
19
22
  */
20
23
  function runScript(fn, opt = {}) {
21
24
  const { logger = console, noExit } = opt;
@@ -25,9 +28,17 @@ function runScript(fn, opt = {}) {
25
28
  process.on('unhandledRejection', err => {
26
29
  logger.error('unhandledRejection:', err);
27
30
  });
31
+ if (DEBUG_RUN_SCRIPT) {
32
+ process.on('exit', code => logger.log(`process.exit event, code=${code}`));
33
+ process.on('beforeExit', code => logger.log(`process.beforeExit event, code=${code}`));
34
+ }
35
+ // fake timeout, to ensure node.js process won't exit until runScript main promise is resolved
36
+ const timeout = setTimeout(() => { }, 10000000);
28
37
  void (async () => {
29
38
  try {
30
39
  await fn();
40
+ if (DEBUG_RUN_SCRIPT)
41
+ logger.log(`runScript promise resolved`);
31
42
  if (!noExit) {
32
43
  setImmediate(() => process.exit(0));
33
44
  }
@@ -39,6 +50,9 @@ function runScript(fn, opt = {}) {
39
50
  setImmediate(() => process.exit(1));
40
51
  }
41
52
  }
53
+ finally {
54
+ clearTimeout(timeout);
55
+ }
42
56
  })();
43
57
  }
44
58
  exports.runScript = runScript;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@naturalcycles/nodejs-lib",
3
- "version": "12.64.0",
3
+ "version": "12.65.0",
4
4
  "scripts": {
5
5
  "prepare": "husky install",
6
6
  "docs-serve": "vuepress dev docs",
@@ -26,7 +26,7 @@
26
26
  "chalk": "^4.0.0",
27
27
  "cp-file": "^9.0.0",
28
28
  "debug": "^4.1.1",
29
- "dotenv": "^14.2.0",
29
+ "dotenv": "^16.0.0",
30
30
  "execa": "^5.0.0",
31
31
  "fs-extra": "^10.0.0",
32
32
  "globby": "^11.0.0",
package/src/fs/del.ts CHANGED
@@ -90,18 +90,14 @@ export async function del(_opt: DelOptions | DelSingleOption): Promise<void> {
90
90
 
91
91
  // console.log({ dirnamesSorted })
92
92
 
93
- const deletedDirs = await pFilter(
94
- dirnamesSorted,
95
- async dirpath => {
96
- if (await isEmptyDir(dirpath)) {
97
- // console.log(`empty dir: ${dirpath}`)
98
- await fs.remove(dirpath)
99
- return true
100
- }
101
- return false
102
- },
103
- { concurrency: 1 },
104
- )
93
+ const deletedDirs: string[] = []
94
+ for await (const dirpath of dirnamesSorted) {
95
+ if (await isEmptyDir(dirpath)) {
96
+ // console.log(`empty dir: ${dirpath}`)
97
+ await fs.remove(dirpath)
98
+ deletedDirs.push(dirpath)
99
+ }
100
+ }
105
101
 
106
102
  if (verbose || debug) console.log({ deletedDirs })
107
103
 
package/src/got/getGot.ts CHANGED
@@ -151,7 +151,25 @@ function gotErrorHook(opt: GetGotOptions = {}): BeforeErrorHook {
151
151
 
152
152
  const stack = (err.options.context as GotRequestContext)?.err?.stack
153
153
  if (stack) {
154
- err.stack += '\n --' + stack.replace('Error: RequestError', '')
154
+ const originalStack = err.stack.split('\n')
155
+ let originalStackIndex = originalStack.findIndex(line => line.includes(' at '))
156
+ if (originalStackIndex === -1) originalStackIndex = originalStack.length - 1
157
+
158
+ // Skipping first line as it has RequestError: ...
159
+ // Skipping second line as it's known to be from e.g at got_1.default.extend.handlers
160
+ const syntheticStack = stack.split('\n').slice(2)
161
+ let firstNonNodeModulesIndex = syntheticStack.findIndex(
162
+ line => !line.includes('node_modules'),
163
+ )
164
+ if (firstNonNodeModulesIndex === -1) firstNonNodeModulesIndex = 0
165
+
166
+ err.stack = [
167
+ // First lines of original error
168
+ ...originalStack.slice(0, originalStackIndex),
169
+ // Other lines from "Synthetic error"
170
+ ...syntheticStack.slice(firstNonNodeModulesIndex),
171
+ ].join('\n')
172
+ // err.stack += '\n --' + stack.replace('Error: RequestError', '')
155
173
  }
156
174
 
157
175
  return err
@@ -226,7 +244,8 @@ function gotAfterResponseHook(opt: GetGotOptions = {}): AfterResponseHook {
226
244
  return resp => {
227
245
  const success = resp.statusCode >= 200 && resp.statusCode < 400
228
246
 
229
- if (opt.logFinished) {
247
+ // Errors are not logged here, as they're logged by gotErrorHook
248
+ if (opt.logFinished && success) {
230
249
  const { started, retryCount } = resp.request.options.context as GotRequestContext
231
250
  const { url, prefixUrl, method } = resp.request.options
232
251
  const shortUrl = getShortUrl(opt, url, prefixUrl)
@@ -14,6 +14,8 @@ export interface RunScriptOptions {
14
14
  logger?: CommonLogger
15
15
  }
16
16
 
17
+ const { DEBUG_RUN_SCRIPT } = process.env
18
+
17
19
  /**
18
20
  * Use it in your top-level scripts like this:
19
21
  *
@@ -29,6 +31,8 @@ export interface RunScriptOptions {
29
31
  * - No need to add `.catch(err => { console.error(err); process.exit(1) })`
30
32
  *
31
33
  * This function is kept light, dependency-free, exported separately.
34
+ *
35
+ * Set env DEBUG_RUN_SCRIPT for extra debugging.
32
36
  */
33
37
  export function runScript(fn: (...args: any[]) => any, opt: RunScriptOptions = {}): void {
34
38
  const { logger = console, noExit } = opt
@@ -40,10 +44,20 @@ export function runScript(fn: (...args: any[]) => any, opt: RunScriptOptions = {
40
44
  logger.error('unhandledRejection:', err)
41
45
  })
42
46
 
47
+ if (DEBUG_RUN_SCRIPT) {
48
+ process.on('exit', code => logger.log(`process.exit event, code=${code}`))
49
+ process.on('beforeExit', code => logger.log(`process.beforeExit event, code=${code}`))
50
+ }
51
+
52
+ // fake timeout, to ensure node.js process won't exit until runScript main promise is resolved
53
+ const timeout = setTimeout(() => {}, 10000000)
54
+
43
55
  void (async () => {
44
56
  try {
45
57
  await fn()
46
58
 
59
+ if (DEBUG_RUN_SCRIPT) logger.log(`runScript promise resolved`)
60
+
47
61
  if (!noExit) {
48
62
  setImmediate(() => process.exit(0))
49
63
  }
@@ -53,6 +67,8 @@ export function runScript(fn: (...args: any[]) => any, opt: RunScriptOptions = {
53
67
  if (!noExit) {
54
68
  setImmediate(() => process.exit(1))
55
69
  }
70
+ } finally {
71
+ clearTimeout(timeout)
56
72
  }
57
73
  })()
58
74
  }