@naturalcycles/js-lib 15.90.0 → 15.92.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/asyncManager.js +3 -2
- package/dist/decorators/asyncMemo.decorator.d.ts +1 -1
- package/dist/decorators/asyncMemo.decorator.js +4 -3
- package/dist/decorators/logMethod.decorator.d.ts +1 -1
- package/dist/decorators/logMethod.decorator.js +8 -3
- package/dist/decorators/memo.decorator.d.ts +1 -1
- package/dist/decorators/memo.decorator.js +3 -2
- package/dist/decorators/memoSimple.decorator.js +8 -1
- package/dist/decorators/memoized.js +3 -2
- package/dist/decorators/memoizedAsync.js +4 -3
- package/dist/error/tryCatch.d.ts +1 -1
- package/dist/error/tryCatch.js +3 -2
- package/dist/http/fetcher.js +18 -17
- package/dist/http/fetcher.model.d.ts +1 -1
- package/dist/log/commonLogger.d.ts +40 -34
- package/dist/log/commonLogger.js +47 -92
- package/dist/promise/pGradualQueue.d.ts +1 -1
- package/dist/promise/pMap.d.ts +2 -2
- package/dist/promise/pMap.js +4 -3
- package/dist/promise/pQueue.d.ts +1 -1
- package/dist/promise/pRetry.d.ts +1 -1
- package/dist/promise/pRetry.js +3 -2
- package/package.json +1 -1
- package/src/asyncManager.ts +3 -2
- package/src/decorators/asyncMemo.decorator.ts +5 -4
- package/src/decorators/logMethod.decorator.ts +9 -4
- package/src/decorators/memo.decorator.ts +4 -3
- package/src/decorators/memoSimple.decorator.ts +2 -1
- package/src/decorators/memoized.ts +3 -2
- package/src/decorators/memoizedAsync.ts +4 -3
- package/src/error/tryCatch.ts +4 -3
- package/src/http/fetcher.model.ts +1 -1
- package/src/http/fetcher.ts +9 -10
- package/src/log/commonLogger.ts +80 -134
- package/src/promise/pGradualQueue.ts +1 -1
- package/src/promise/pMap.ts +10 -5
- package/src/promise/pQueue.ts +1 -1
- package/src/promise/pRetry.ts +4 -3
package/dist/asyncManager.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import { consoleLogger } from './log/commonLogger.js';
|
|
1
2
|
class AsyncManagerImpl {
|
|
2
|
-
logger =
|
|
3
|
+
logger = consoleLogger;
|
|
3
4
|
pendingOps = new Set();
|
|
4
5
|
onErrorHooks = [];
|
|
5
6
|
runInBackground(promise) {
|
|
@@ -48,7 +49,7 @@ class AsyncManagerImpl {
|
|
|
48
49
|
this.onErrorHooks.forEach(hook => hook(err));
|
|
49
50
|
}
|
|
50
51
|
else {
|
|
51
|
-
this.logger.error('AsyncManager unhandled rejection
|
|
52
|
+
this.logger.error({ msg: 'AsyncManager unhandled rejection', err });
|
|
52
53
|
}
|
|
53
54
|
}
|
|
54
55
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { _assert, _assertTypeOf } from '../error/assert.js';
|
|
2
|
+
import { consoleLogger } from '../log/commonLogger.js';
|
|
2
3
|
import { _objectAssign, MISS } from '../types.js';
|
|
3
4
|
import { _getTargetMethodSignature } from './decorator.util.js';
|
|
4
5
|
import { jsonMemoSerializer } from './memo.util.js';
|
|
@@ -20,7 +21,7 @@ export const _AsyncMemo = (opt) => (target, key, descriptor) => {
|
|
|
20
21
|
// It only holds values that are "in-flight", until Promise is resolved
|
|
21
22
|
// After it's resolved - it's evicted from the cache and moved to the "proper" `instanceCache`
|
|
22
23
|
const instancePromiseCache = new Map();
|
|
23
|
-
const { logger =
|
|
24
|
+
const { logger = consoleLogger, cacheFactory, cacheKeyFn = jsonMemoSerializer } = opt;
|
|
24
25
|
const keyStr = String(key);
|
|
25
26
|
const methodSignature = _getTargetMethodSignature(target, keyStr);
|
|
26
27
|
// oxlint-disable-next-line @typescript-eslint/promise-function-async
|
|
@@ -56,7 +57,7 @@ export const _AsyncMemo = (opt) => (target, key, descriptor) => {
|
|
|
56
57
|
return await onMiss();
|
|
57
58
|
}, async (err) => {
|
|
58
59
|
// Log the cache error and proceed "as cache Miss"
|
|
59
|
-
logger.error(err);
|
|
60
|
+
logger.error({ err });
|
|
60
61
|
return await onMiss();
|
|
61
62
|
});
|
|
62
63
|
promiseCache.set(cacheKey, promise);
|
|
@@ -73,7 +74,7 @@ export const _AsyncMemo = (opt) => (target, key, descriptor) => {
|
|
|
73
74
|
await cache.set(cacheKey, value);
|
|
74
75
|
}
|
|
75
76
|
catch (err) {
|
|
76
|
-
logger.error(err); // log and ignore the error
|
|
77
|
+
logger.error({ err }); // log and ignore the error
|
|
77
78
|
}
|
|
78
79
|
finally {
|
|
79
80
|
// Clear the "in-flight" promise cache entry, as we now have a "permanent" cache entry
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { _ms } from '../datetime/time.util.js';
|
|
2
2
|
import { _assert } from '../error/assert.js';
|
|
3
|
+
import { consoleLogger } from '../log/commonLogger.js';
|
|
3
4
|
import { SimpleMovingAverage } from '../math/sma.js';
|
|
4
5
|
import { _stringify } from '../string/stringify.js';
|
|
5
6
|
import { _getArgsSignature, _getMethodSignature } from './decorator.util.js';
|
|
@@ -21,7 +22,7 @@ export function _LogMethod(opt = {}) {
|
|
|
21
22
|
_assert(typeof descriptor.value === 'function', '@_LogMethod can be applied only to methods');
|
|
22
23
|
const originalFn = descriptor.value;
|
|
23
24
|
const keyStr = String(key);
|
|
24
|
-
const { avg, logArgs = true, logStart, logResult, logResultLength = true, logger =
|
|
25
|
+
const { avg, logArgs = true, logStart, logResult, logResultLength = true, logger = consoleLogger, } = opt;
|
|
25
26
|
let { logResultFn } = opt;
|
|
26
27
|
if (!logResultFn) {
|
|
27
28
|
if (logResult) {
|
|
@@ -77,10 +78,14 @@ function logFinished(logger, callSignature, started, sma, logResultFn, res, err)
|
|
|
77
78
|
t.push(`(avg ${_ms(sma.pushGetAvg(millis))})`);
|
|
78
79
|
}
|
|
79
80
|
if (err !== undefined) {
|
|
80
|
-
t.push('ERROR:'
|
|
81
|
+
t.push('ERROR:');
|
|
81
82
|
}
|
|
82
83
|
else if (logResultFn) {
|
|
83
84
|
t.push(...logResultFn(res));
|
|
84
85
|
}
|
|
85
|
-
|
|
86
|
+
const msg = t
|
|
87
|
+
.filter(Boolean)
|
|
88
|
+
.map(part => _stringify(part))
|
|
89
|
+
.join(' ');
|
|
90
|
+
logger.log(err === undefined ? msg : { msg, err });
|
|
86
91
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { _assert, _assertTypeOf } from '../error/assert.js';
|
|
2
|
+
import { consoleLogger } from '../log/commonLogger.js';
|
|
2
3
|
import { _objectAssign } from '../types.js';
|
|
3
4
|
import { _getTargetMethodSignature } from './decorator.util.js';
|
|
4
5
|
import { jsonMemoSerializer, MapMemoCache } from './memo.util.js';
|
|
@@ -33,7 +34,7 @@ export const _Memo = (opt = {}) => (target, key, descriptor) => {
|
|
|
33
34
|
// UPD: tests show that normal Map also doesn't leak (to be tested further)
|
|
34
35
|
// Normal Map is needed to allow .clear()
|
|
35
36
|
const instanceCache = new Map();
|
|
36
|
-
const { logger =
|
|
37
|
+
const { logger = consoleLogger, cacheFactory = () => new MapMemoCache(), cacheKeyFn = jsonMemoSerializer, } = opt;
|
|
37
38
|
const keyStr = String(key);
|
|
38
39
|
const methodSignature = _getTargetMethodSignature(target, keyStr);
|
|
39
40
|
descriptor.value = function (...args) {
|
|
@@ -54,7 +55,7 @@ export const _Memo = (opt = {}) => (target, key, descriptor) => {
|
|
|
54
55
|
cache.set(cacheKey, value);
|
|
55
56
|
}
|
|
56
57
|
catch (err) {
|
|
57
|
-
logger.error(err);
|
|
58
|
+
logger.error({ err });
|
|
58
59
|
}
|
|
59
60
|
return value;
|
|
60
61
|
};
|
|
@@ -3,6 +3,13 @@
|
|
|
3
3
|
// http://decodize.com/blog/2012/08/27/javascript-memoization-caching-results-for-better-performance/
|
|
4
4
|
// http://inlehmansterms.net/2015/03/01/javascript-memoization/
|
|
5
5
|
// https://community.risingstack.com/the-worlds-fastest-javascript-memoization-library/
|
|
6
|
+
/*
|
|
7
|
+
Optimized for 0 arguments (using SingleValueCache).
|
|
8
|
+
Optimized for 1 primitive argument (skips JSON.stringify).
|
|
9
|
+
Otherwise resorts to JSON.stringify.
|
|
10
|
+
Benchmark shows similar perf for ObjectCache and MapCache.
|
|
11
|
+
*/
|
|
12
|
+
import { consoleLogger } from '../log/commonLogger.js';
|
|
6
13
|
import { _getTargetMethodSignature } from './decorator.util.js';
|
|
7
14
|
import { jsonMemoSerializer, MapMemoCache } from './memo.util.js';
|
|
8
15
|
// memoSimple decorator is NOT exported. Only used in benchmarks currently
|
|
@@ -34,7 +41,7 @@ export const memoSimple = (opt = {}) => (target, key, descriptor) => {
|
|
|
34
41
|
}
|
|
35
42
|
*/
|
|
36
43
|
const cache = new MapMemoCache();
|
|
37
|
-
const { logger =
|
|
44
|
+
const { logger = consoleLogger } = opt;
|
|
38
45
|
const keyStr = String(key);
|
|
39
46
|
const methodSignature = _getTargetMethodSignature(target, keyStr);
|
|
40
47
|
descriptor.value = function (...args) {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { consoleLogger } from '../log/commonLogger.js';
|
|
1
2
|
import { jsonMemoSerializer, MapMemoCache } from './memo.util.js';
|
|
2
3
|
/**
|
|
3
4
|
* Only supports Sync functions.
|
|
@@ -5,7 +6,7 @@ import { jsonMemoSerializer, MapMemoCache } from './memo.util.js';
|
|
|
5
6
|
* Technically, you can use it with Async functions, but it'll return the Promise without awaiting it.
|
|
6
7
|
*/
|
|
7
8
|
export function _memoized(fn, opt = {}) {
|
|
8
|
-
const { logger =
|
|
9
|
+
const { logger = consoleLogger, cacheFactory = () => new MapMemoCache(), cacheKeyFn = jsonMemoSerializer, } = opt;
|
|
9
10
|
const cache = cacheFactory();
|
|
10
11
|
const memoizedFn = function (...args) {
|
|
11
12
|
const ctx = this;
|
|
@@ -18,7 +19,7 @@ export function _memoized(fn, opt = {}) {
|
|
|
18
19
|
cache.set(cacheKey, value);
|
|
19
20
|
}
|
|
20
21
|
catch (err) {
|
|
21
|
-
logger.error(err);
|
|
22
|
+
logger.error({ err });
|
|
22
23
|
}
|
|
23
24
|
return value;
|
|
24
25
|
};
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
+
import { consoleLogger } from '../log/commonLogger.js';
|
|
1
2
|
import { MISS } from '../types.js';
|
|
2
3
|
import { jsonMemoSerializer } from './memo.util.js';
|
|
3
4
|
export function _memoizedAsync(fn, opt) {
|
|
4
|
-
const { logger =
|
|
5
|
+
const { logger = consoleLogger, cacheFactory, cacheKeyFn = jsonMemoSerializer } = opt;
|
|
5
6
|
const cache = cacheFactory();
|
|
6
7
|
const memoizedFn = async function (...args) {
|
|
7
8
|
const ctx = this;
|
|
@@ -11,7 +12,7 @@ export function _memoizedAsync(fn, opt) {
|
|
|
11
12
|
value = await cache.get(cacheKey);
|
|
12
13
|
}
|
|
13
14
|
catch (err) {
|
|
14
|
-
logger.error(err);
|
|
15
|
+
logger.error({ err });
|
|
15
16
|
}
|
|
16
17
|
if (value !== MISS) {
|
|
17
18
|
return value;
|
|
@@ -22,7 +23,7 @@ export function _memoizedAsync(fn, opt) {
|
|
|
22
23
|
await cache.set(cacheKey, value);
|
|
23
24
|
}
|
|
24
25
|
catch (err) {
|
|
25
|
-
logger.error(err);
|
|
26
|
+
logger.error({ err });
|
|
26
27
|
}
|
|
27
28
|
})();
|
|
28
29
|
return value;
|
package/dist/error/tryCatch.d.ts
CHANGED
package/dist/error/tryCatch.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { _since } from '../datetime/time.util.js';
|
|
2
|
+
import { consoleLogger } from '../log/commonLogger.js';
|
|
2
3
|
import { _anyToError } from './error.util.js';
|
|
3
4
|
/**
|
|
4
5
|
* Decorates a function with "try/catch", so it'll never reject/throw.
|
|
@@ -9,7 +10,7 @@ import { _anyToError } from './error.util.js';
|
|
|
9
10
|
* @experimental
|
|
10
11
|
*/
|
|
11
12
|
export function _tryCatch(fn, opt = {}) {
|
|
12
|
-
const { onError, logError = true, logSuccess = false, logger =
|
|
13
|
+
const { onError, logError = true, logSuccess = false, logger = consoleLogger } = opt;
|
|
13
14
|
const fname = fn.name || 'anonymous';
|
|
14
15
|
return async function (...args) {
|
|
15
16
|
const started = Date.now();
|
|
@@ -22,7 +23,7 @@ export function _tryCatch(fn, opt = {}) {
|
|
|
22
23
|
}
|
|
23
24
|
catch (err) {
|
|
24
25
|
if (logError) {
|
|
25
|
-
logger.warn(`tryCatch.${fname} error in ${_since(started)}
|
|
26
|
+
logger.warn({ msg: `tryCatch.${fname} error in ${_since(started)}`, err });
|
|
26
27
|
}
|
|
27
28
|
if (onError) {
|
|
28
29
|
try {
|
package/dist/http/fetcher.js
CHANGED
|
@@ -6,13 +6,13 @@ import { _ms, _since } from '../datetime/time.util.js';
|
|
|
6
6
|
import { isServerSide } from '../env.js';
|
|
7
7
|
import { _assertErrorClassOrRethrow, _assertIsError } from '../error/assert.js';
|
|
8
8
|
import { _anyToError, _anyToErrorObject, _errorDataAppend, _errorLikeToErrorObject, HttpRequestError, UnexpectedPassError, } from '../error/error.util.js';
|
|
9
|
+
import { consoleLogger } from '../log/commonLogger.js';
|
|
9
10
|
import { _clamp } from '../number/number.util.js';
|
|
10
11
|
import { _filterFalsyValues, _filterNullishValues, _filterUndefinedValues, _mapKeys, _merge, _omit, _pick, } from '../object/object.util.js';
|
|
11
12
|
import { pDelaySignal } from '../promise/pDelay.js';
|
|
12
13
|
import { pTimeout } from '../promise/pTimeout.js';
|
|
13
14
|
import { _toUrlOrNull } from '../string/index.js';
|
|
14
15
|
import { _jsonParse, _jsonParseIfPossible } from '../string/json.util.js';
|
|
15
|
-
import { _stringify } from '../string/stringify.js';
|
|
16
16
|
import { HTTP_METHODS } from './http.model.js';
|
|
17
17
|
/**
|
|
18
18
|
* Experimental wrapper around Fetch.
|
|
@@ -326,7 +326,7 @@ export class Fetcher {
|
|
|
326
326
|
.filter(Boolean)
|
|
327
327
|
.join(' '));
|
|
328
328
|
if (req.logRequestBody && req.init.body) {
|
|
329
|
-
logger.log(req.init.body); // todo: check if we can _inspect it
|
|
329
|
+
logger.log({ body: req.init.body }); // todo: check if we can _inspect it
|
|
330
330
|
}
|
|
331
331
|
}
|
|
332
332
|
try {
|
|
@@ -473,7 +473,7 @@ export class Fetcher {
|
|
|
473
473
|
.filter(Boolean)
|
|
474
474
|
.join(' '));
|
|
475
475
|
if (req.logResponseBody && res.body !== undefined) {
|
|
476
|
-
logger.log(res.body);
|
|
476
|
+
logger.log({ body: res.body });
|
|
477
477
|
}
|
|
478
478
|
}
|
|
479
479
|
}
|
|
@@ -558,19 +558,20 @@ export class Fetcher {
|
|
|
558
558
|
// lastError = retryStatus.retryStopped
|
|
559
559
|
// We need to log the response "anyway" if logResponse is true
|
|
560
560
|
if (res.err && (!retryStatus.retryStopped || res.req.logResponse)) {
|
|
561
|
-
this.cfg.logger.error(
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
561
|
+
this.cfg.logger.error({
|
|
562
|
+
msg: [
|
|
563
|
+
' <<',
|
|
564
|
+
res.fetchResponse?.status || 0,
|
|
565
|
+
res.signature,
|
|
566
|
+
count &&
|
|
567
|
+
(retryStatus.retryAttempt || !retryStatus.retryStopped) &&
|
|
568
|
+
`try#${retryStatus.retryAttempt + 1}/${count + 1}`,
|
|
569
|
+
_since(res.req.started),
|
|
570
|
+
]
|
|
571
|
+
.filter(Boolean)
|
|
572
|
+
.join(' '),
|
|
573
|
+
err: res.err.cause || res.err,
|
|
574
|
+
});
|
|
574
575
|
}
|
|
575
576
|
if (retryStatus.retryStopped)
|
|
576
577
|
return;
|
|
@@ -704,7 +705,7 @@ export class Fetcher {
|
|
|
704
705
|
return shortUrl;
|
|
705
706
|
}
|
|
706
707
|
normalizeCfg(cfg) {
|
|
707
|
-
const { debug = false, logger =
|
|
708
|
+
const { debug = false, logger = consoleLogger } = cfg;
|
|
708
709
|
if (cfg.baseUrl?.endsWith('/')) {
|
|
709
710
|
logger.warn(`Fetcher: baseUrl should not end with slash: ${cfg.baseUrl}`);
|
|
710
711
|
cfg.baseUrl = cfg.baseUrl.slice(0, cfg.baseUrl.length - 1);
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import type { AnyObject, MutateOptions } from '../types.js';
|
|
2
1
|
/**
|
|
3
2
|
* These levels follow console.* naming,
|
|
4
3
|
* so you can use console[level] safely.
|
|
@@ -16,17 +15,32 @@ import type { AnyObject, MutateOptions } from '../types.js';
|
|
|
16
15
|
export type CommonLogLevel = 'debug' | 'log' | 'warn' | 'error';
|
|
17
16
|
export declare const commonLogLevelNumber: Record<CommonLogLevel, number>;
|
|
18
17
|
/**
|
|
19
|
-
*
|
|
20
|
-
* It is expected that logged arguments are separated by "space", like console.log does.
|
|
21
|
-
*
|
|
22
|
-
* @experimental
|
|
18
|
+
* Structured log data: a message, an error, and any other fields.
|
|
23
19
|
*/
|
|
24
|
-
export
|
|
25
|
-
|
|
20
|
+
export interface LogData {
|
|
21
|
+
msg?: string;
|
|
22
|
+
err?: unknown;
|
|
23
|
+
[field: string]: unknown;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* What a log call accepts: a string is `{ msg }`, an Error is `{ err }`.
|
|
27
|
+
* A non-Error error value (e.g an `unknown` from a catch) is passed as `{ err }`.
|
|
28
|
+
*/
|
|
29
|
+
export type LogInput = string | Error | LogData;
|
|
30
|
+
/**
|
|
31
|
+
* What a sink receives: the logger's context, the log data and the level.
|
|
32
|
+
*/
|
|
33
|
+
export interface LogEntry extends LogData {
|
|
34
|
+
level: CommonLogLevel;
|
|
35
|
+
}
|
|
36
|
+
export type LogSink = (entry: LogEntry) => void;
|
|
37
|
+
/**
|
|
38
|
+
* A log call is either one `LogInput`, or a message with the other fields:
|
|
39
|
+
* `logger.log('hey')`, `logger.error(err)`, `logger.warn({ msg, err })`, `logger.warn('failed', { err })`.
|
|
40
|
+
*/
|
|
41
|
+
export type CommonLogArgs = [input: LogInput] | [msg: string, data: LogData];
|
|
42
|
+
export type CommonLogFunction = (...args: CommonLogArgs) => void;
|
|
26
43
|
/**
|
|
27
|
-
* Interface is inspired/compatible with `console.*`
|
|
28
|
-
* So, `console` is a valid CommonLogger implementation as-is.
|
|
29
|
-
*
|
|
30
44
|
* @experimental
|
|
31
45
|
*/
|
|
32
46
|
export interface CommonLogger {
|
|
@@ -34,38 +48,30 @@ export interface CommonLogger {
|
|
|
34
48
|
log: CommonLogFunction;
|
|
35
49
|
warn: CommonLogFunction;
|
|
36
50
|
error: CommonLogFunction;
|
|
51
|
+
/**
|
|
52
|
+
* Creates a logger that adds `context` to every entry.
|
|
53
|
+
*/
|
|
54
|
+
child: (context: LogData) => CommonLogger;
|
|
37
55
|
}
|
|
38
56
|
/**
|
|
39
|
-
*
|
|
57
|
+
* Creates a CommonLogger that writes every entry to `sink`.
|
|
58
|
+
* `context` is called on every log call, so it can return values that change
|
|
59
|
+
* after the logger is created (e.g a request context whose user is resolved later).
|
|
40
60
|
*/
|
|
41
|
-
export declare
|
|
61
|
+
export declare function commonLoggerCreate(sink: LogSink, context?: () => LogData): CommonLogger;
|
|
42
62
|
/**
|
|
43
|
-
*
|
|
63
|
+
* CommonLogger that logs to `console`.
|
|
44
64
|
*/
|
|
45
|
-
export declare
|
|
46
|
-
/**
|
|
47
|
-
* Creates a "proxy" CommonLogger that pipes log messages to all provided sub-loggers.
|
|
48
|
-
*/
|
|
49
|
-
export declare function commonLoggerPipe(loggers: CommonLogger[]): CommonLogger;
|
|
65
|
+
export declare const consoleLogger: CommonLogger;
|
|
50
66
|
/**
|
|
51
|
-
*
|
|
67
|
+
* CommonLogger that does nothing (noop).
|
|
52
68
|
*/
|
|
53
|
-
export declare
|
|
54
|
-
export type CommonLogSink = CommonLogger | CommonLogWithLevelFunction;
|
|
69
|
+
export declare const commonLoggerNoop: CommonLogger;
|
|
55
70
|
/**
|
|
56
|
-
*
|
|
57
|
-
* A function is called on every log call, for context that changes after the logger is created
|
|
58
|
-
* (e.g a request context whose user is resolved later).
|
|
71
|
+
* Creates a CommonLogger that is "limited" to the specified CommonLogLevel.
|
|
59
72
|
*/
|
|
60
|
-
export
|
|
61
|
-
export interface CommonLoggerWithContext extends CommonLogger {
|
|
62
|
-
child: (context: CommonLogContext) => CommonLoggerWithContext;
|
|
63
|
-
}
|
|
73
|
+
export declare function createCommonLoggerAtLevel(logger?: CommonLogger, minLevel?: CommonLogLevel): CommonLogger;
|
|
64
74
|
/**
|
|
65
|
-
* Creates a CommonLogger
|
|
66
|
-
*
|
|
67
|
-
* With a context, every call emits one object: plain-object args merged in, first Error as `err`,
|
|
68
|
-
* the rest joined into `msg`.
|
|
75
|
+
* Creates a "proxy" CommonLogger that pipes log entries to all provided sub-loggers.
|
|
69
76
|
*/
|
|
70
|
-
export declare function
|
|
71
|
-
export declare function commonLoggerCreate(sink: CommonLogSink, context: CommonLogContext): CommonLoggerWithContext;
|
|
77
|
+
export declare function commonLoggerPipe(loggers: CommonLogger[]): CommonLogger;
|
package/dist/log/commonLogger.js
CHANGED
|
@@ -1,58 +1,75 @@
|
|
|
1
|
-
import { _isPlainObject } from '../is.util.js';
|
|
2
1
|
// copy-pasted to avoid weird circular dependency
|
|
3
2
|
const _noop = (..._args) => undefined;
|
|
4
3
|
export const commonLogLevelNumber = {
|
|
5
4
|
debug: 10,
|
|
6
5
|
log: 20,
|
|
7
|
-
warn:
|
|
8
|
-
error:
|
|
6
|
+
warn: 30,
|
|
7
|
+
error: 40,
|
|
9
8
|
};
|
|
10
9
|
/**
|
|
11
|
-
*
|
|
10
|
+
* Creates a CommonLogger that writes every entry to `sink`.
|
|
11
|
+
* `context` is called on every log call, so it can return values that change
|
|
12
|
+
* after the logger is created (e.g a request context whose user is resolved later).
|
|
13
|
+
*/
|
|
14
|
+
export function commonLoggerCreate(sink, context) {
|
|
15
|
+
const emit = (level, [input, data]) => sink({ ...context?.(), ...toLogData(input, data), level });
|
|
16
|
+
return {
|
|
17
|
+
debug: (...args) => emit('debug', args),
|
|
18
|
+
log: (...args) => emit('log', args),
|
|
19
|
+
warn: (...args) => emit('warn', args),
|
|
20
|
+
error: (...args) => emit('error', args),
|
|
21
|
+
child: childContext => commonLoggerCreate(sink, () => ({ ...context?.(), ...childContext })),
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
function toLogData(input, data) {
|
|
25
|
+
if (typeof input === 'string')
|
|
26
|
+
return { ...data, msg: input };
|
|
27
|
+
if (input instanceof Error)
|
|
28
|
+
return { err: input };
|
|
29
|
+
return input;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* CommonLogger that logs to `console`.
|
|
33
|
+
*/
|
|
34
|
+
export const consoleLogger = commonLoggerCreate(({ level, msg, err, ...fields }) => {
|
|
35
|
+
const args = [];
|
|
36
|
+
if (msg !== undefined)
|
|
37
|
+
args.push(msg);
|
|
38
|
+
if (err !== undefined)
|
|
39
|
+
args.push(err);
|
|
40
|
+
if (Object.keys(fields).length)
|
|
41
|
+
args.push(fields);
|
|
42
|
+
console[level](...args);
|
|
43
|
+
});
|
|
44
|
+
/**
|
|
45
|
+
* CommonLogger that does nothing (noop).
|
|
12
46
|
*/
|
|
13
47
|
export const commonLoggerNoop = {
|
|
14
48
|
debug: _noop,
|
|
15
49
|
log: _noop,
|
|
16
50
|
warn: _noop,
|
|
17
51
|
error: _noop,
|
|
52
|
+
child: () => commonLoggerNoop,
|
|
18
53
|
};
|
|
19
54
|
/**
|
|
20
|
-
* Creates a
|
|
55
|
+
* Creates a CommonLogger that is "limited" to the specified CommonLogLevel.
|
|
21
56
|
*/
|
|
22
|
-
export function createCommonLoggerAtLevel(logger =
|
|
57
|
+
export function createCommonLoggerAtLevel(logger = consoleLogger, minLevel = 'log') {
|
|
23
58
|
const level = commonLogLevelNumber[minLevel];
|
|
24
|
-
if (opt.mutate) {
|
|
25
|
-
if (level > commonLogLevelNumber['debug']) {
|
|
26
|
-
logger.debug = _noop;
|
|
27
|
-
if (level > commonLogLevelNumber['log']) {
|
|
28
|
-
logger.log = _noop;
|
|
29
|
-
if (level > commonLogLevelNumber['warn']) {
|
|
30
|
-
logger.warn = _noop;
|
|
31
|
-
if (level > commonLogLevelNumber['error']) {
|
|
32
|
-
logger.error = _noop;
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
return logger;
|
|
38
|
-
}
|
|
39
59
|
if (level <= commonLogLevelNumber['debug']) {
|
|
40
60
|
// All levels are kept
|
|
41
61
|
return logger;
|
|
42
62
|
}
|
|
43
|
-
if (level > commonLogLevelNumber['error']) {
|
|
44
|
-
// "Log nothing" logger
|
|
45
|
-
return commonLoggerNoop;
|
|
46
|
-
}
|
|
47
63
|
return {
|
|
48
64
|
debug: _noop, // otherwise it is "log everything" logger (same logger as input)
|
|
49
|
-
log: level <= commonLogLevelNumber['log'] ? logger.log
|
|
50
|
-
warn: level <= commonLogLevelNumber['warn'] ? logger.warn
|
|
51
|
-
error:
|
|
65
|
+
log: level <= commonLogLevelNumber['log'] ? (...args) => logger.log(...args) : _noop,
|
|
66
|
+
warn: level <= commonLogLevelNumber['warn'] ? (...args) => logger.warn(...args) : _noop,
|
|
67
|
+
error: (...args) => logger.error(...args),
|
|
68
|
+
child: context => createCommonLoggerAtLevel(logger.child(context), minLevel),
|
|
52
69
|
};
|
|
53
70
|
}
|
|
54
71
|
/**
|
|
55
|
-
* Creates a "proxy" CommonLogger that pipes log
|
|
72
|
+
* Creates a "proxy" CommonLogger that pipes log entries to all provided sub-loggers.
|
|
56
73
|
*/
|
|
57
74
|
export function commonLoggerPipe(loggers) {
|
|
58
75
|
return {
|
|
@@ -60,68 +77,6 @@ export function commonLoggerPipe(loggers) {
|
|
|
60
77
|
log: (...args) => loggers.forEach(logger => logger.log(...args)),
|
|
61
78
|
warn: (...args) => loggers.forEach(logger => logger.warn(...args)),
|
|
62
79
|
error: (...args) => loggers.forEach(logger => logger.error(...args)),
|
|
80
|
+
child: context => commonLoggerPipe(loggers.map(logger => logger.child(context))),
|
|
63
81
|
};
|
|
64
82
|
}
|
|
65
|
-
/**
|
|
66
|
-
* Creates a "child" CommonLogger with prefix (one or multiple).
|
|
67
|
-
*/
|
|
68
|
-
export function commonLoggerPrefix(logger, ...prefixes) {
|
|
69
|
-
return {
|
|
70
|
-
debug: (...args) => logger.debug(...prefixes, ...args),
|
|
71
|
-
log: (...args) => logger.log(...prefixes, ...args),
|
|
72
|
-
warn: (...args) => logger.warn(...prefixes, ...args),
|
|
73
|
-
error: (...args) => logger.error(...prefixes, ...args),
|
|
74
|
-
};
|
|
75
|
-
}
|
|
76
|
-
export function commonLoggerCreate(sink, context) {
|
|
77
|
-
const fn = typeof sink === 'function' ? sink : (level, args) => sink[level](...args);
|
|
78
|
-
if (!context) {
|
|
79
|
-
return {
|
|
80
|
-
debug: (...args) => fn('debug', args),
|
|
81
|
-
log: (...args) => fn('log', args),
|
|
82
|
-
warn: (...args) => fn('warn', args),
|
|
83
|
-
error: (...args) => fn('error', args),
|
|
84
|
-
};
|
|
85
|
-
}
|
|
86
|
-
const getContext = contextGetter(context);
|
|
87
|
-
const logger = {
|
|
88
|
-
debug: (...args) => fn('debug', [toLogEntry(getContext(), args)]),
|
|
89
|
-
log: (...args) => fn('log', [toLogEntry(getContext(), args)]),
|
|
90
|
-
warn: (...args) => fn('warn', [toLogEntry(getContext(), args)]),
|
|
91
|
-
error: (...args) => fn('error', [toLogEntry(getContext(), args)]),
|
|
92
|
-
child: c => {
|
|
93
|
-
const getChild = contextGetter(c);
|
|
94
|
-
return commonLoggerCreate(fn, () => ({ ...getContext(), ...getChild() }));
|
|
95
|
-
},
|
|
96
|
-
};
|
|
97
|
-
return logger;
|
|
98
|
-
}
|
|
99
|
-
function contextGetter(context) {
|
|
100
|
-
// AnyObject also admits functions, so typeof does not narrow the union
|
|
101
|
-
if (typeof context === 'function')
|
|
102
|
-
return context;
|
|
103
|
-
const copy = { ...context };
|
|
104
|
-
return () => copy;
|
|
105
|
-
}
|
|
106
|
-
function toLogEntry(context, args) {
|
|
107
|
-
const entry = { ...context };
|
|
108
|
-
let err;
|
|
109
|
-
let msg;
|
|
110
|
-
for (const arg of args) {
|
|
111
|
-
if (_isPlainObject(arg)) {
|
|
112
|
-
Object.assign(entry, arg);
|
|
113
|
-
}
|
|
114
|
-
else if (!err && arg instanceof Error) {
|
|
115
|
-
err = arg;
|
|
116
|
-
}
|
|
117
|
-
else {
|
|
118
|
-
const s = String(arg);
|
|
119
|
-
msg = msg === undefined ? s : `${msg} ${s}`;
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
if (err)
|
|
123
|
-
entry['err'] = err;
|
|
124
|
-
if (msg !== undefined)
|
|
125
|
-
entry['msg'] = msg;
|
|
126
|
-
return entry;
|
|
127
|
-
}
|
package/dist/promise/pMap.d.ts
CHANGED
|
@@ -14,11 +14,11 @@ export interface PMapOptions {
|
|
|
14
14
|
* When set to THROW_AGGREGATED, instead of stopping when a promise rejects, it will wait for all the promises to settle and then reject with an Aggregated error.
|
|
15
15
|
*
|
|
16
16
|
* When set to SUPPRESS - will ignore errors and return results from successful operations.
|
|
17
|
-
* When in SUPPRESS - errors are still logged via the `logger` (which defaults to
|
|
17
|
+
* When in SUPPRESS - errors are still logged via the `logger` (which defaults to consoleLogger).
|
|
18
18
|
*/
|
|
19
19
|
errorMode?: ErrorMode;
|
|
20
20
|
/**
|
|
21
|
-
* Default to `
|
|
21
|
+
* Default to `consoleLogger`.
|
|
22
22
|
* Pass `null` to skip logging completely.
|
|
23
23
|
*/
|
|
24
24
|
logger?: CommonLogger | null;
|