@naturalcycles/js-lib 14.76.0 → 14.79.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/decorators/logMethod.decorator.js +1 -1
- package/dist/decorators/memo.decorator.js +1 -1
- package/dist/decorators/memoFn.js +1 -1
- package/dist/error/try.js +0 -2
- package/dist/promise/pProps.d.ts +12 -3
- package/dist/promise/pProps.js +13 -17
- package/dist/promise/pRetry.d.ts +7 -2
- package/dist/promise/pRetry.js +4 -4
- package/dist/promise/pTimeout.d.ts +8 -0
- package/dist/promise/pTimeout.js +8 -2
- package/dist/types.d.ts +2 -2
- package/dist-esm/decorators/logMethod.decorator.js +1 -1
- package/dist-esm/decorators/memo.decorator.js +1 -1
- package/dist-esm/decorators/memoFn.js +1 -1
- package/dist-esm/error/try.js +0 -2
- package/dist-esm/promise/pProps.js +13 -17
- package/dist-esm/promise/pRetry.js +4 -4
- package/dist-esm/promise/pTimeout.js +8 -2
- package/package.json +4 -3
- package/src/decorators/logMethod.decorator.ts +1 -1
- package/src/decorators/memo.decorator.ts +1 -1
- package/src/decorators/memoFn.ts +1 -1
- package/src/error/try.ts +0 -3
- package/src/promise/pProps.ts +16 -24
- package/src/promise/pRetry.ts +13 -5
- package/src/promise/pTimeout.ts +16 -3
- package/src/types.ts +12 -3
package/dist/error/try.js
CHANGED
package/dist/promise/pProps.d.ts
CHANGED
|
@@ -1,10 +1,19 @@
|
|
|
1
|
-
import { PMapOptions } from './pMap';
|
|
2
1
|
/**
|
|
3
2
|
* Promise.all for Object instead of Array.
|
|
4
|
-
*
|
|
3
|
+
*
|
|
4
|
+
* Inspired by Bluebird Promise.props() and https://github.com/sindresorhus/p-props
|
|
5
|
+
*
|
|
6
|
+
* Improvements:
|
|
7
|
+
*
|
|
8
|
+
* - Exported as { pProps }, so IDE auto-completion works
|
|
9
|
+
* - Simpler: no support for Map, Mapper, Options
|
|
10
|
+
* - Included Typescript typings (no need for @types/p-props)
|
|
11
|
+
*
|
|
12
|
+
* Concurrency implementation via pMap was removed in favor of preserving async
|
|
13
|
+
* stack traces (more important!).
|
|
5
14
|
*/
|
|
6
15
|
export declare function pProps<T>(input: {
|
|
7
16
|
[K in keyof T]: T[K] | Promise<T[K]>;
|
|
8
|
-
}
|
|
17
|
+
}): Promise<{
|
|
9
18
|
[K in keyof T]: Awaited<T[K]>;
|
|
10
19
|
}>;
|
package/dist/promise/pProps.js
CHANGED
|
@@ -1,26 +1,22 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
/*
|
|
3
|
-
Inspired by Bluebird Promise.props() and https://github.com/sindresorhus/p-props
|
|
4
|
-
|
|
5
|
-
Improvements:
|
|
6
|
-
|
|
7
|
-
- Exported as { pProps }, so IDE auto-completion works
|
|
8
|
-
- Simpler: no support for Map, Mapper, Options
|
|
9
|
-
- Included Typescript typings (no need for @types/p-props)
|
|
10
|
-
*/
|
|
11
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
3
|
exports.pProps = void 0;
|
|
13
|
-
const pMap_1 = require("./pMap");
|
|
14
|
-
// todo: remove when eslint starts to know about Awaited
|
|
15
|
-
/* eslint-disable no-undef */
|
|
16
4
|
/**
|
|
17
5
|
* Promise.all for Object instead of Array.
|
|
18
|
-
*
|
|
6
|
+
*
|
|
7
|
+
* Inspired by Bluebird Promise.props() and https://github.com/sindresorhus/p-props
|
|
8
|
+
*
|
|
9
|
+
* Improvements:
|
|
10
|
+
*
|
|
11
|
+
* - Exported as { pProps }, so IDE auto-completion works
|
|
12
|
+
* - Simpler: no support for Map, Mapper, Options
|
|
13
|
+
* - Included Typescript typings (no need for @types/p-props)
|
|
14
|
+
*
|
|
15
|
+
* Concurrency implementation via pMap was removed in favor of preserving async
|
|
16
|
+
* stack traces (more important!).
|
|
19
17
|
*/
|
|
20
|
-
async function pProps(input
|
|
21
|
-
const r = {};
|
|
18
|
+
async function pProps(input) {
|
|
22
19
|
const keys = Object.keys(input);
|
|
23
|
-
|
|
24
|
-
return r;
|
|
20
|
+
return Object.fromEntries((await Promise.all(Object.values(input))).map((v, i) => [keys[i], v]));
|
|
25
21
|
}
|
|
26
22
|
exports.pProps = pProps;
|
package/dist/promise/pRetry.d.ts
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
|
-
import { CommonLogger } from '..';
|
|
1
|
+
import { AnyFunction, CommonLogger } from '..';
|
|
2
2
|
export interface PRetryOptions {
|
|
3
|
+
/**
|
|
4
|
+
* If set - will be included in the error message.
|
|
5
|
+
* Can be used to identify the place in the code that failed.
|
|
6
|
+
*/
|
|
7
|
+
name?: string;
|
|
3
8
|
/**
|
|
4
9
|
* How many attempts to try.
|
|
5
10
|
* First attempt is not a retry, but "initial try". It still counts.
|
|
@@ -62,4 +67,4 @@ export interface PRetryOptions {
|
|
|
62
67
|
* Returns a Function (!), enhanced with retry capabilities.
|
|
63
68
|
* Implements "Exponential back-off strategy" by multiplying the delay by `delayMultiplier` with each try.
|
|
64
69
|
*/
|
|
65
|
-
export declare function pRetry<T extends
|
|
70
|
+
export declare function pRetry<T extends AnyFunction>(fn: T, opt?: PRetryOptions): T;
|
package/dist/promise/pRetry.js
CHANGED
|
@@ -8,7 +8,7 @@ const __1 = require("..");
|
|
|
8
8
|
*/
|
|
9
9
|
// eslint-disable-next-line @typescript-eslint/ban-types
|
|
10
10
|
function pRetry(fn, opt = {}) {
|
|
11
|
-
const { maxAttempts = 4, delay: initialDelay = 1000, delayMultiplier = 2, predicate, logger = console, } = opt;
|
|
11
|
+
const { maxAttempts = 4, delay: initialDelay = 1000, delayMultiplier = 2, predicate, logger = console, name = fn.name, } = opt;
|
|
12
12
|
let { logFirstAttempt = false, logRetries = true, logFailures = false, logSuccess = false } = opt;
|
|
13
13
|
if (opt.logAll) {
|
|
14
14
|
logFirstAttempt = logRetries = logFailures = true;
|
|
@@ -16,7 +16,7 @@ function pRetry(fn, opt = {}) {
|
|
|
16
16
|
if (opt.logNone) {
|
|
17
17
|
logSuccess = logFirstAttempt = logRetries = logFailures = false;
|
|
18
18
|
}
|
|
19
|
-
const fname = ['pRetry',
|
|
19
|
+
const fname = ['pRetry', name].filter(Boolean).join('.');
|
|
20
20
|
return async function (...args) {
|
|
21
21
|
let delay = initialDelay;
|
|
22
22
|
let attempt = 0;
|
|
@@ -36,9 +36,9 @@ function pRetry(fn, opt = {}) {
|
|
|
36
36
|
}
|
|
37
37
|
catch (err) {
|
|
38
38
|
if (logFailures) {
|
|
39
|
-
logger.warn(`${fname} attempt #${attempt} error in ${(0, __1._since)(started)}
|
|
39
|
+
logger.warn(`${fname} attempt #${attempt} error in ${(0, __1._since)(started)}:`, (0, __1._stringifyAny)(err, {
|
|
40
40
|
includeErrorData: true,
|
|
41
|
-
})
|
|
41
|
+
}));
|
|
42
42
|
}
|
|
43
43
|
if (attempt >= maxAttempts || (predicate && !predicate(err, attempt, maxAttempts))) {
|
|
44
44
|
// Give up
|
|
@@ -17,6 +17,14 @@ export interface PTimeoutOptions {
|
|
|
17
17
|
* Can be used to thrown a custom error OR resolve a promise without throwing.
|
|
18
18
|
*/
|
|
19
19
|
onTimeout?: () => any;
|
|
20
|
+
/**
|
|
21
|
+
* Defaults to true.
|
|
22
|
+
* If true - preserves the stack trace in case of a Timeout (usually - very useful!).
|
|
23
|
+
* It has a certain perf cost.
|
|
24
|
+
*
|
|
25
|
+
* @experimental
|
|
26
|
+
*/
|
|
27
|
+
keepStackTrace?: boolean;
|
|
20
28
|
}
|
|
21
29
|
/**
|
|
22
30
|
* Decorates a Function with a timeout.
|
package/dist/promise/pTimeout.js
CHANGED
|
@@ -24,7 +24,8 @@ exports.pTimeoutFn = pTimeoutFn;
|
|
|
24
24
|
*/
|
|
25
25
|
async function pTimeout(promise, opt) {
|
|
26
26
|
// todo: check how we can automatically infer function name (only applicable to named functions)
|
|
27
|
-
const { timeout, name, onTimeout } = opt;
|
|
27
|
+
const { timeout, name, onTimeout, keepStackTrace = true } = opt;
|
|
28
|
+
const fakeError = keepStackTrace ? new Error('TimeoutError') : undefined;
|
|
28
29
|
// eslint-disable-next-line no-async-promise-executor
|
|
29
30
|
return await new Promise(async (resolve, reject) => {
|
|
30
31
|
// Prepare the timeout timer
|
|
@@ -34,11 +35,16 @@ async function pTimeout(promise, opt) {
|
|
|
34
35
|
resolve(onTimeout());
|
|
35
36
|
}
|
|
36
37
|
catch (err) {
|
|
38
|
+
if (fakeError)
|
|
39
|
+
err.stack = fakeError.stack; // keep original stack
|
|
37
40
|
reject(err);
|
|
38
41
|
}
|
|
39
42
|
return;
|
|
40
43
|
}
|
|
41
|
-
|
|
44
|
+
const err = new TimeoutError(`"${name || 'pTimeout function'}" timed out after ${timeout} ms`);
|
|
45
|
+
if (fakeError)
|
|
46
|
+
err.stack = fakeError.stack; // keep original stack
|
|
47
|
+
reject(err);
|
|
42
48
|
}, timeout);
|
|
43
49
|
// Execute the Function
|
|
44
50
|
try {
|
package/dist/types.d.ts
CHANGED
|
@@ -95,8 +95,8 @@ export declare type ValuesOf<T extends readonly any[]> = T[number];
|
|
|
95
95
|
*/
|
|
96
96
|
export declare type ValueOf<T> = T[keyof T];
|
|
97
97
|
export declare type KeyValueTuple<K, V> = [key: K, value: V];
|
|
98
|
-
export declare type ObjectMapper<OBJ, OUT> = (key: string, value: OBJ[keyof OBJ], obj: OBJ) => OUT;
|
|
99
|
-
export declare type ObjectPredicate<OBJ> = (key: keyof OBJ, value: OBJ[keyof OBJ], obj: OBJ) => boolean;
|
|
98
|
+
export declare type ObjectMapper<OBJ, OUT> = (key: string, value: Exclude<OBJ[keyof OBJ], undefined>, obj: OBJ) => OUT;
|
|
99
|
+
export declare type ObjectPredicate<OBJ> = (key: keyof OBJ, value: Exclude<OBJ[keyof OBJ], undefined>, obj: OBJ) => boolean;
|
|
100
100
|
/**
|
|
101
101
|
* Allows to identify instance of Class by `instanceId`.
|
|
102
102
|
*/
|
package/dist-esm/error/try.js
CHANGED
|
@@ -1,22 +1,18 @@
|
|
|
1
|
-
/*
|
|
2
|
-
Inspired by Bluebird Promise.props() and https://github.com/sindresorhus/p-props
|
|
3
|
-
|
|
4
|
-
Improvements:
|
|
5
|
-
|
|
6
|
-
- Exported as { pProps }, so IDE auto-completion works
|
|
7
|
-
- Simpler: no support for Map, Mapper, Options
|
|
8
|
-
- Included Typescript typings (no need for @types/p-props)
|
|
9
|
-
*/
|
|
10
|
-
import { pMap } from './pMap';
|
|
11
|
-
// todo: remove when eslint starts to know about Awaited
|
|
12
|
-
/* eslint-disable no-undef */
|
|
13
1
|
/**
|
|
14
2
|
* Promise.all for Object instead of Array.
|
|
15
|
-
*
|
|
3
|
+
*
|
|
4
|
+
* Inspired by Bluebird Promise.props() and https://github.com/sindresorhus/p-props
|
|
5
|
+
*
|
|
6
|
+
* Improvements:
|
|
7
|
+
*
|
|
8
|
+
* - Exported as { pProps }, so IDE auto-completion works
|
|
9
|
+
* - Simpler: no support for Map, Mapper, Options
|
|
10
|
+
* - Included Typescript typings (no need for @types/p-props)
|
|
11
|
+
*
|
|
12
|
+
* Concurrency implementation via pMap was removed in favor of preserving async
|
|
13
|
+
* stack traces (more important!).
|
|
16
14
|
*/
|
|
17
|
-
export async function pProps(input
|
|
18
|
-
const r = {};
|
|
15
|
+
export async function pProps(input) {
|
|
19
16
|
const keys = Object.keys(input);
|
|
20
|
-
await
|
|
21
|
-
return r;
|
|
17
|
+
return Object.fromEntries((await Promise.all(Object.values(input))).map((v, i) => [keys[i], v]));
|
|
22
18
|
}
|
|
@@ -5,7 +5,7 @@ import { _since, _stringifyAny } from '..';
|
|
|
5
5
|
*/
|
|
6
6
|
// eslint-disable-next-line @typescript-eslint/ban-types
|
|
7
7
|
export function pRetry(fn, opt = {}) {
|
|
8
|
-
const { maxAttempts = 4, delay: initialDelay = 1000, delayMultiplier = 2, predicate, logger = console, } = opt;
|
|
8
|
+
const { maxAttempts = 4, delay: initialDelay = 1000, delayMultiplier = 2, predicate, logger = console, name = fn.name, } = opt;
|
|
9
9
|
let { logFirstAttempt = false, logRetries = true, logFailures = false, logSuccess = false } = opt;
|
|
10
10
|
if (opt.logAll) {
|
|
11
11
|
logFirstAttempt = logRetries = logFailures = true;
|
|
@@ -13,7 +13,7 @@ export function pRetry(fn, opt = {}) {
|
|
|
13
13
|
if (opt.logNone) {
|
|
14
14
|
logSuccess = logFirstAttempt = logRetries = logFailures = false;
|
|
15
15
|
}
|
|
16
|
-
const fname = ['pRetry',
|
|
16
|
+
const fname = ['pRetry', name].filter(Boolean).join('.');
|
|
17
17
|
return async function (...args) {
|
|
18
18
|
let delay = initialDelay;
|
|
19
19
|
let attempt = 0;
|
|
@@ -33,9 +33,9 @@ export function pRetry(fn, opt = {}) {
|
|
|
33
33
|
}
|
|
34
34
|
catch (err) {
|
|
35
35
|
if (logFailures) {
|
|
36
|
-
logger.warn(`${fname} attempt #${attempt} error in ${_since(started)}
|
|
36
|
+
logger.warn(`${fname} attempt #${attempt} error in ${_since(started)}:`, _stringifyAny(err, {
|
|
37
37
|
includeErrorData: true,
|
|
38
|
-
})
|
|
38
|
+
}));
|
|
39
39
|
}
|
|
40
40
|
if (attempt >= maxAttempts || (predicate && !predicate(err, attempt, maxAttempts))) {
|
|
41
41
|
// Give up
|
|
@@ -19,7 +19,8 @@ export function pTimeoutFn(fn, opt) {
|
|
|
19
19
|
*/
|
|
20
20
|
export async function pTimeout(promise, opt) {
|
|
21
21
|
// todo: check how we can automatically infer function name (only applicable to named functions)
|
|
22
|
-
const { timeout, name, onTimeout } = opt;
|
|
22
|
+
const { timeout, name, onTimeout, keepStackTrace = true } = opt;
|
|
23
|
+
const fakeError = keepStackTrace ? new Error('TimeoutError') : undefined;
|
|
23
24
|
// eslint-disable-next-line no-async-promise-executor
|
|
24
25
|
return await new Promise(async (resolve, reject) => {
|
|
25
26
|
// Prepare the timeout timer
|
|
@@ -29,11 +30,16 @@ export async function pTimeout(promise, opt) {
|
|
|
29
30
|
resolve(onTimeout());
|
|
30
31
|
}
|
|
31
32
|
catch (err) {
|
|
33
|
+
if (fakeError)
|
|
34
|
+
err.stack = fakeError.stack; // keep original stack
|
|
32
35
|
reject(err);
|
|
33
36
|
}
|
|
34
37
|
return;
|
|
35
38
|
}
|
|
36
|
-
|
|
39
|
+
const err = new TimeoutError(`"${name || 'pTimeout function'}" timed out after ${timeout} ms`);
|
|
40
|
+
if (fakeError)
|
|
41
|
+
err.stack = fakeError.stack; // keep original stack
|
|
42
|
+
reject(err);
|
|
37
43
|
}, timeout);
|
|
38
44
|
// Execute the Function
|
|
39
45
|
try {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@naturalcycles/js-lib",
|
|
3
|
-
"version": "14.
|
|
3
|
+
"version": "14.79.0",
|
|
4
4
|
"scripts": {
|
|
5
5
|
"prepare": "husky install",
|
|
6
6
|
"build-prod": "build-prod-esm-cjs",
|
|
@@ -14,13 +14,14 @@
|
|
|
14
14
|
"@naturalcycles/bench-lib": "^1.5.0",
|
|
15
15
|
"@naturalcycles/dev-lib": "^12.0.0",
|
|
16
16
|
"@naturalcycles/nodejs-lib": "^12.33.4",
|
|
17
|
-
"@types/node": "^
|
|
17
|
+
"@types/node": "^17.0.4",
|
|
18
18
|
"jest": "^27.0.1",
|
|
19
19
|
"patch-package": "^6.2.1",
|
|
20
20
|
"prettier": "^2.1.2",
|
|
21
21
|
"rxjs": "^7.0.1",
|
|
22
22
|
"vuepress": "^1.7.1",
|
|
23
|
-
"vuepress-plugin-typescript": "^0.3.1"
|
|
23
|
+
"vuepress-plugin-typescript": "^0.3.1",
|
|
24
|
+
"weak-napi": "^2.0.2"
|
|
24
25
|
},
|
|
25
26
|
"files": [
|
|
26
27
|
"dist",
|
|
@@ -110,7 +110,7 @@ export function _LogMethod(opt: LogMethodOptions = {}): MethodDecorator {
|
|
|
110
110
|
})
|
|
111
111
|
.catch((err: any) => {
|
|
112
112
|
logFinished(logger, callSignature, started, sma, logResultFn, undefined, err)
|
|
113
|
-
|
|
113
|
+
throw err
|
|
114
114
|
})
|
|
115
115
|
} else {
|
|
116
116
|
// not a Promise
|
package/src/decorators/memoFn.ts
CHANGED
package/src/error/try.ts
CHANGED
package/src/promise/pProps.ts
CHANGED
|
@@ -1,28 +1,20 @@
|
|
|
1
|
-
/*
|
|
2
|
-
Inspired by Bluebird Promise.props() and https://github.com/sindresorhus/p-props
|
|
3
|
-
|
|
4
|
-
Improvements:
|
|
5
|
-
|
|
6
|
-
- Exported as { pProps }, so IDE auto-completion works
|
|
7
|
-
- Simpler: no support for Map, Mapper, Options
|
|
8
|
-
- Included Typescript typings (no need for @types/p-props)
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
import { pMap, PMapOptions } from './pMap'
|
|
12
|
-
|
|
13
|
-
// todo: remove when eslint starts to know about Awaited
|
|
14
|
-
/* eslint-disable no-undef */
|
|
15
|
-
|
|
16
1
|
/**
|
|
17
2
|
* Promise.all for Object instead of Array.
|
|
18
|
-
*
|
|
3
|
+
*
|
|
4
|
+
* Inspired by Bluebird Promise.props() and https://github.com/sindresorhus/p-props
|
|
5
|
+
*
|
|
6
|
+
* Improvements:
|
|
7
|
+
*
|
|
8
|
+
* - Exported as { pProps }, so IDE auto-completion works
|
|
9
|
+
* - Simpler: no support for Map, Mapper, Options
|
|
10
|
+
* - Included Typescript typings (no need for @types/p-props)
|
|
11
|
+
*
|
|
12
|
+
* Concurrency implementation via pMap was removed in favor of preserving async
|
|
13
|
+
* stack traces (more important!).
|
|
19
14
|
*/
|
|
20
|
-
export async function pProps<T>(
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
const keys = Object.keys(input) as (keyof T)[]
|
|
26
|
-
await pMap(Object.values(input), (v, i) => (r[keys[i]!] = v), opt)
|
|
27
|
-
return r
|
|
15
|
+
export async function pProps<T>(input: { [K in keyof T]: T[K] | Promise<T[K]> }): Promise<{
|
|
16
|
+
[K in keyof T]: Awaited<T[K]>
|
|
17
|
+
}> {
|
|
18
|
+
const keys = Object.keys(input)
|
|
19
|
+
return Object.fromEntries((await Promise.all(Object.values(input))).map((v, i) => [keys[i], v]))
|
|
28
20
|
}
|
package/src/promise/pRetry.ts
CHANGED
|
@@ -1,6 +1,12 @@
|
|
|
1
|
-
import { _since, _stringifyAny, CommonLogger } from '..'
|
|
1
|
+
import { _since, _stringifyAny, AnyFunction, CommonLogger } from '..'
|
|
2
2
|
|
|
3
3
|
export interface PRetryOptions {
|
|
4
|
+
/**
|
|
5
|
+
* If set - will be included in the error message.
|
|
6
|
+
* Can be used to identify the place in the code that failed.
|
|
7
|
+
*/
|
|
8
|
+
name?: string
|
|
9
|
+
|
|
4
10
|
/**
|
|
5
11
|
* How many attempts to try.
|
|
6
12
|
* First attempt is not a retry, but "initial try". It still counts.
|
|
@@ -75,13 +81,14 @@ export interface PRetryOptions {
|
|
|
75
81
|
* Implements "Exponential back-off strategy" by multiplying the delay by `delayMultiplier` with each try.
|
|
76
82
|
*/
|
|
77
83
|
// eslint-disable-next-line @typescript-eslint/ban-types
|
|
78
|
-
export function pRetry<T extends
|
|
84
|
+
export function pRetry<T extends AnyFunction>(fn: T, opt: PRetryOptions = {}): T {
|
|
79
85
|
const {
|
|
80
86
|
maxAttempts = 4,
|
|
81
87
|
delay: initialDelay = 1000,
|
|
82
88
|
delayMultiplier = 2,
|
|
83
89
|
predicate,
|
|
84
90
|
logger = console,
|
|
91
|
+
name = fn.name,
|
|
85
92
|
} = opt
|
|
86
93
|
|
|
87
94
|
let { logFirstAttempt = false, logRetries = true, logFailures = false, logSuccess = false } = opt
|
|
@@ -93,7 +100,7 @@ export function pRetry<T extends Function>(fn: T, opt: PRetryOptions = {}): T {
|
|
|
93
100
|
logSuccess = logFirstAttempt = logRetries = logFailures = false
|
|
94
101
|
}
|
|
95
102
|
|
|
96
|
-
const fname = ['pRetry',
|
|
103
|
+
const fname = ['pRetry', name].filter(Boolean).join('.')
|
|
97
104
|
|
|
98
105
|
return async function (this: any, ...args: any[]) {
|
|
99
106
|
let delay = initialDelay
|
|
@@ -118,9 +125,10 @@ export function pRetry<T extends Function>(fn: T, opt: PRetryOptions = {}): T {
|
|
|
118
125
|
} catch (err) {
|
|
119
126
|
if (logFailures) {
|
|
120
127
|
logger.warn(
|
|
121
|
-
`${fname} attempt #${attempt} error in ${_since(started)}
|
|
128
|
+
`${fname} attempt #${attempt} error in ${_since(started)}:`,
|
|
129
|
+
_stringifyAny(err, {
|
|
122
130
|
includeErrorData: true,
|
|
123
|
-
})
|
|
131
|
+
}),
|
|
124
132
|
)
|
|
125
133
|
}
|
|
126
134
|
|
package/src/promise/pTimeout.ts
CHANGED
|
@@ -20,6 +20,15 @@ export interface PTimeoutOptions {
|
|
|
20
20
|
* Can be used to thrown a custom error OR resolve a promise without throwing.
|
|
21
21
|
*/
|
|
22
22
|
onTimeout?: () => any
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Defaults to true.
|
|
26
|
+
* If true - preserves the stack trace in case of a Timeout (usually - very useful!).
|
|
27
|
+
* It has a certain perf cost.
|
|
28
|
+
*
|
|
29
|
+
* @experimental
|
|
30
|
+
*/
|
|
31
|
+
keepStackTrace?: boolean
|
|
23
32
|
}
|
|
24
33
|
|
|
25
34
|
/**
|
|
@@ -42,7 +51,8 @@ export function pTimeoutFn<T extends AnyFunction>(fn: T, opt: PTimeoutOptions):
|
|
|
42
51
|
*/
|
|
43
52
|
export async function pTimeout<T>(promise: Promise<T>, opt: PTimeoutOptions): Promise<T> {
|
|
44
53
|
// todo: check how we can automatically infer function name (only applicable to named functions)
|
|
45
|
-
const { timeout, name, onTimeout } = opt
|
|
54
|
+
const { timeout, name, onTimeout, keepStackTrace = true } = opt
|
|
55
|
+
const fakeError = keepStackTrace ? new Error('TimeoutError') : undefined
|
|
46
56
|
|
|
47
57
|
// eslint-disable-next-line no-async-promise-executor
|
|
48
58
|
return await new Promise(async (resolve, reject) => {
|
|
@@ -51,13 +61,16 @@ export async function pTimeout<T>(promise: Promise<T>, opt: PTimeoutOptions): Pr
|
|
|
51
61
|
if (onTimeout) {
|
|
52
62
|
try {
|
|
53
63
|
resolve(onTimeout())
|
|
54
|
-
} catch (err) {
|
|
64
|
+
} catch (err: any) {
|
|
65
|
+
if (fakeError) err.stack = fakeError.stack // keep original stack
|
|
55
66
|
reject(err)
|
|
56
67
|
}
|
|
57
68
|
return
|
|
58
69
|
}
|
|
59
70
|
|
|
60
|
-
|
|
71
|
+
const err = new TimeoutError(`"${name || 'pTimeout function'}" timed out after ${timeout} ms`)
|
|
72
|
+
if (fakeError) err.stack = fakeError.stack // keep original stack
|
|
73
|
+
reject(err)
|
|
61
74
|
}, timeout)
|
|
62
75
|
|
|
63
76
|
// Execute the Function
|
package/src/types.ts
CHANGED
|
@@ -122,9 +122,18 @@ export type ValueOf<T> = T[keyof T]
|
|
|
122
122
|
|
|
123
123
|
export type KeyValueTuple<K, V> = [key: K, value: V]
|
|
124
124
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
125
|
+
// Exclude<something, undefined> is used here to support StringMap<OBJ> (because values of StringMap add `undefined`)
|
|
126
|
+
export type ObjectMapper<OBJ, OUT> = (
|
|
127
|
+
key: string,
|
|
128
|
+
value: Exclude<OBJ[keyof OBJ], undefined>,
|
|
129
|
+
obj: OBJ,
|
|
130
|
+
) => OUT
|
|
131
|
+
|
|
132
|
+
export type ObjectPredicate<OBJ> = (
|
|
133
|
+
key: keyof OBJ,
|
|
134
|
+
value: Exclude<OBJ[keyof OBJ], undefined>,
|
|
135
|
+
obj: OBJ,
|
|
136
|
+
) => boolean
|
|
128
137
|
|
|
129
138
|
/**
|
|
130
139
|
* Allows to identify instance of Class by `instanceId`.
|