@naturalcycles/js-lib 15.89.0 → 15.91.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 +35 -28
- package/dist/log/commonLogger.js +51 -86
- 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 +2 -2
- 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 +78 -118
- 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,27 @@ 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
|
+
export type CommonLogFunction = (input: LogInput) => void;
|
|
26
38
|
/**
|
|
27
|
-
* Interface is inspired/compatible with `console.*`
|
|
28
|
-
* So, `console` is a valid CommonLogger implementation as-is.
|
|
29
|
-
*
|
|
30
39
|
* @experimental
|
|
31
40
|
*/
|
|
32
41
|
export interface CommonLogger {
|
|
@@ -34,32 +43,30 @@ export interface CommonLogger {
|
|
|
34
43
|
log: CommonLogFunction;
|
|
35
44
|
warn: CommonLogFunction;
|
|
36
45
|
error: CommonLogFunction;
|
|
46
|
+
/**
|
|
47
|
+
* Creates a logger that adds `context` to every entry.
|
|
48
|
+
*/
|
|
49
|
+
child: (context: LogData) => CommonLogger;
|
|
37
50
|
}
|
|
38
51
|
/**
|
|
39
|
-
*
|
|
52
|
+
* Creates a CommonLogger that writes every entry to `sink`.
|
|
53
|
+
* `context` is called on every log call, so it can return values that change
|
|
54
|
+
* after the logger is created (e.g a request context whose user is resolved later).
|
|
40
55
|
*/
|
|
41
|
-
export declare
|
|
56
|
+
export declare function commonLoggerCreate(sink: LogSink, context?: () => LogData): CommonLogger;
|
|
42
57
|
/**
|
|
43
|
-
*
|
|
58
|
+
* CommonLogger that logs to `console`.
|
|
44
59
|
*/
|
|
45
|
-
export declare
|
|
60
|
+
export declare const consoleLogger: CommonLogger;
|
|
46
61
|
/**
|
|
47
|
-
*
|
|
62
|
+
* CommonLogger that does nothing (noop).
|
|
48
63
|
*/
|
|
49
|
-
export declare
|
|
64
|
+
export declare const commonLoggerNoop: CommonLogger;
|
|
50
65
|
/**
|
|
51
|
-
* Creates a "
|
|
66
|
+
* Creates a CommonLogger that is "limited" to the specified CommonLogLevel.
|
|
52
67
|
*/
|
|
53
|
-
export declare function
|
|
54
|
-
export type CommonLogSink = CommonLogger | CommonLogWithLevelFunction;
|
|
55
|
-
export interface CommonLoggerWithContext extends CommonLogger {
|
|
56
|
-
child: (context: AnyObject) => CommonLoggerWithContext;
|
|
57
|
-
}
|
|
68
|
+
export declare function createCommonLoggerAtLevel(logger?: CommonLogger, minLevel?: CommonLogLevel): CommonLogger;
|
|
58
69
|
/**
|
|
59
|
-
* Creates a CommonLogger
|
|
60
|
-
*
|
|
61
|
-
* With a context, every call emits one object: plain-object args merged in, first Error as `err`,
|
|
62
|
-
* the rest joined into `msg`.
|
|
70
|
+
* Creates a "proxy" CommonLogger that pipes log entries to all provided sub-loggers.
|
|
63
71
|
*/
|
|
64
|
-
export declare function
|
|
65
|
-
export declare function commonLoggerCreate(sink: CommonLogSink, context: AnyObject): CommonLoggerWithContext;
|
|
72
|
+
export declare function commonLoggerPipe(loggers: CommonLogger[]): CommonLogger;
|
package/dist/log/commonLogger.js
CHANGED
|
@@ -1,117 +1,82 @@
|
|
|
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) => sink({ ...context?.(), ...toLogData(input), level });
|
|
16
|
+
return {
|
|
17
|
+
debug: input => emit('debug', input),
|
|
18
|
+
log: input => emit('log', input),
|
|
19
|
+
warn: input => emit('warn', input),
|
|
20
|
+
error: input => emit('error', input),
|
|
21
|
+
child: childContext => commonLoggerCreate(sink, () => ({ ...context?.(), ...childContext })),
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
function toLogData(input) {
|
|
25
|
+
if (typeof input === 'string')
|
|
26
|
+
return { 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: logger.error
|
|
65
|
+
log: level <= commonLogLevelNumber['log'] ? input => logger.log(input) : _noop,
|
|
66
|
+
warn: level <= commonLogLevelNumber['warn'] ? input => logger.warn(input) : _noop,
|
|
67
|
+
error: input => logger.error(input),
|
|
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 {
|
|
59
|
-
debug:
|
|
60
|
-
log:
|
|
61
|
-
warn:
|
|
62
|
-
error:
|
|
76
|
+
debug: input => loggers.forEach(logger => logger.debug(input)),
|
|
77
|
+
log: input => loggers.forEach(logger => logger.log(input)),
|
|
78
|
+
warn: input => loggers.forEach(logger => logger.warn(input)),
|
|
79
|
+
error: input => loggers.forEach(logger => logger.error(input)),
|
|
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 ctx = { ...context };
|
|
87
|
-
const logger = {
|
|
88
|
-
debug: (...args) => fn('debug', [toLogEntry(ctx, args)]),
|
|
89
|
-
log: (...args) => fn('log', [toLogEntry(ctx, args)]),
|
|
90
|
-
warn: (...args) => fn('warn', [toLogEntry(ctx, args)]),
|
|
91
|
-
error: (...args) => fn('error', [toLogEntry(ctx, args)]),
|
|
92
|
-
child: c => commonLoggerCreate(fn, { ...ctx, ...c }),
|
|
93
|
-
};
|
|
94
|
-
return logger;
|
|
95
|
-
}
|
|
96
|
-
function toLogEntry(context, args) {
|
|
97
|
-
const entry = { ...context };
|
|
98
|
-
let err;
|
|
99
|
-
let msg;
|
|
100
|
-
for (const arg of args) {
|
|
101
|
-
if (_isPlainObject(arg)) {
|
|
102
|
-
Object.assign(entry, arg);
|
|
103
|
-
}
|
|
104
|
-
else if (!err && arg instanceof Error) {
|
|
105
|
-
err = arg;
|
|
106
|
-
}
|
|
107
|
-
else {
|
|
108
|
-
const s = String(arg);
|
|
109
|
-
msg = msg === undefined ? s : `${msg} ${s}`;
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
if (err)
|
|
113
|
-
entry['err'] = err;
|
|
114
|
-
if (msg !== undefined)
|
|
115
|
-
entry['msg'] = msg;
|
|
116
|
-
return entry;
|
|
117
|
-
}
|
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;
|
package/dist/promise/pMap.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { ErrorMode } from '../error/errorMode.js';
|
|
2
|
+
import { consoleLogger } from '../log/commonLogger.js';
|
|
2
3
|
import { END, SKIP } from '../types.js';
|
|
3
4
|
/**
|
|
4
5
|
* Forked from https://github.com/sindresorhus/p-map
|
|
@@ -39,7 +40,7 @@ export async function pMap(iterable, mapper, opt = {}) {
|
|
|
39
40
|
const itemsLength = items.length;
|
|
40
41
|
if (itemsLength === 0)
|
|
41
42
|
return []; // short circuit
|
|
42
|
-
const { concurrency = Infinity, errorMode = ErrorMode.THROW_IMMEDIATELY, logger =
|
|
43
|
+
const { concurrency = Infinity, errorMode = ErrorMode.THROW_IMMEDIATELY, logger = consoleLogger, } = opt;
|
|
43
44
|
// Special cases that are able to preserve async stack traces
|
|
44
45
|
// Special case: serial execution
|
|
45
46
|
if (concurrency === 1) {
|
|
@@ -135,7 +136,7 @@ async function pMap1(items, mapper, errorMode, logger) {
|
|
|
135
136
|
}
|
|
136
137
|
else {
|
|
137
138
|
// otherwise, suppress (but still log via logger)
|
|
138
|
-
logger?.error(err);
|
|
139
|
+
logger?.error({ err });
|
|
139
140
|
}
|
|
140
141
|
}
|
|
141
142
|
}
|
|
@@ -165,7 +166,7 @@ async function pMapAll(items, mapper, errorMode, logger) {
|
|
|
165
166
|
}
|
|
166
167
|
else {
|
|
167
168
|
// otherwise, suppress (but still log via logger)
|
|
168
|
-
logger?.error(r.reason);
|
|
169
|
+
logger?.error({ err: r.reason });
|
|
169
170
|
}
|
|
170
171
|
}
|
|
171
172
|
if (errors.length) {
|