@naturalcycles/js-lib 15.90.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.
Files changed (38) hide show
  1. package/dist/asyncManager.js +3 -2
  2. package/dist/decorators/asyncMemo.decorator.d.ts +1 -1
  3. package/dist/decorators/asyncMemo.decorator.js +4 -3
  4. package/dist/decorators/logMethod.decorator.d.ts +1 -1
  5. package/dist/decorators/logMethod.decorator.js +8 -3
  6. package/dist/decorators/memo.decorator.d.ts +1 -1
  7. package/dist/decorators/memo.decorator.js +3 -2
  8. package/dist/decorators/memoSimple.decorator.js +8 -1
  9. package/dist/decorators/memoized.js +3 -2
  10. package/dist/decorators/memoizedAsync.js +4 -3
  11. package/dist/error/tryCatch.d.ts +1 -1
  12. package/dist/error/tryCatch.js +3 -2
  13. package/dist/http/fetcher.js +18 -17
  14. package/dist/http/fetcher.model.d.ts +1 -1
  15. package/dist/log/commonLogger.d.ts +35 -34
  16. package/dist/log/commonLogger.js +51 -96
  17. package/dist/promise/pGradualQueue.d.ts +1 -1
  18. package/dist/promise/pMap.d.ts +2 -2
  19. package/dist/promise/pMap.js +4 -3
  20. package/dist/promise/pQueue.d.ts +1 -1
  21. package/dist/promise/pRetry.d.ts +1 -1
  22. package/dist/promise/pRetry.js +3 -2
  23. package/package.json +2 -2
  24. package/src/asyncManager.ts +3 -2
  25. package/src/decorators/asyncMemo.decorator.ts +5 -4
  26. package/src/decorators/logMethod.decorator.ts +9 -4
  27. package/src/decorators/memo.decorator.ts +4 -3
  28. package/src/decorators/memoSimple.decorator.ts +2 -1
  29. package/src/decorators/memoized.ts +3 -2
  30. package/src/decorators/memoizedAsync.ts +4 -3
  31. package/src/error/tryCatch.ts +4 -3
  32. package/src/http/fetcher.model.ts +1 -1
  33. package/src/http/fetcher.ts +9 -10
  34. package/src/log/commonLogger.ts +78 -138
  35. package/src/promise/pGradualQueue.ts +1 -1
  36. package/src/promise/pMap.ts +10 -5
  37. package/src/promise/pQueue.ts +1 -1
  38. package/src/promise/pRetry.ts +4 -3
@@ -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 = console } = opt;
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) {
@@ -12,7 +12,7 @@ export interface PQueueCfg {
12
12
  */
13
13
  errorMode?: ErrorMode;
14
14
  /**
15
- * Default to `console`
15
+ * Default to `consoleLogger`
16
16
  */
17
17
  logger?: CommonLogger;
18
18
  /**
@@ -67,7 +67,7 @@ export interface PRetryOptions {
67
67
  */
68
68
  logNone?: boolean;
69
69
  /**
70
- * Default to `console`
70
+ * Default to `consoleLogger`
71
71
  */
72
72
  logger?: CommonLogger;
73
73
  /**
@@ -1,5 +1,6 @@
1
1
  import { _since } from '../datetime/time.util.js';
2
2
  import { _errorDataAppend } from '../error/error.util.js';
3
+ import { consoleLogger } from '../log/commonLogger.js';
3
4
  import { pDelay } from './pDelay.js';
4
5
  import { pTimeout } from './pTimeout.js';
5
6
  /**
@@ -12,7 +13,7 @@ export function pRetryFn(fn, opt = {}) {
12
13
  };
13
14
  }
14
15
  export async function pRetry(fn, opt = {}) {
15
- const { maxAttempts = 4, delay: initialDelay = 1000, delayMultiplier = 2, predicate, logger = console, name, timeout, } = opt;
16
+ const { maxAttempts = 4, delay: initialDelay = 1000, delayMultiplier = 2, predicate, logger = consoleLogger, name, timeout, } = opt;
16
17
  const fakeError = timeout ? new Error('TimeoutError') : undefined;
17
18
  let { logFirstAttempt = false, logRetries = true, logFailures = true, logSuccess = false } = opt;
18
19
  if (opt.logAll) {
@@ -52,7 +53,7 @@ export async function pRetry(fn, opt = {}) {
52
53
  if (logFailures) {
53
54
  // Logger at warn (not error) level, because it's not a fatal error, but a retriable one
54
55
  // Fatal one is not logged either, because it's been thrown instead
55
- logger.warn(`${fname} attempt #${attempt} error in ${_since(started)}:`, err);
56
+ logger.warn({ msg: `${fname} attempt #${attempt} error in ${_since(started)}`, err });
56
57
  }
57
58
  if (attempt >= maxAttempts || (predicate && !predicate(err, attempt, maxAttempts))) {
58
59
  // Give up
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@naturalcycles/js-lib",
3
3
  "type": "module",
4
- "version": "15.90.0",
4
+ "version": "15.91.0",
5
5
  "dependencies": {
6
6
  "tslib": "^2"
7
7
  },
@@ -14,7 +14,7 @@
14
14
  }
15
15
  },
16
16
  "devDependencies": {
17
- "@naturalcycles/dev-lib": "0.0.0",
17
+ "@naturalcycles/dev-lib": "20.64.0",
18
18
  "@types/node": "^26",
19
19
  "@types/semver": "^7",
20
20
  "typescript": "^7",
@@ -1,8 +1,9 @@
1
+ import { consoleLogger } from './log/commonLogger.js'
1
2
  import type { CommonLogger } from './log/commonLogger.js'
2
3
  import type { NumberOfMilliseconds } from './types.js'
3
4
 
4
5
  class AsyncManagerImpl {
5
- logger: CommonLogger = console
6
+ logger: CommonLogger = consoleLogger
6
7
 
7
8
  pendingOps = new Set<Promise<unknown>>()
8
9
 
@@ -58,7 +59,7 @@ class AsyncManagerImpl {
58
59
  if (this.onErrorHooks.length) {
59
60
  this.onErrorHooks.forEach(hook => hook(err))
60
61
  } else {
61
- this.logger.error('AsyncManager unhandled rejection:', err)
62
+ this.logger.error({ msg: 'AsyncManager unhandled rejection', err })
62
63
  }
63
64
  }
64
65
  }
@@ -1,4 +1,5 @@
1
1
  import { _assert, _assertTypeOf } from '../error/assert.js'
2
+ import { consoleLogger } from '../log/commonLogger.js'
2
3
  import type { CommonLogger } from '../log/commonLogger.js'
3
4
  import type { AnyAsyncFunction, AnyFunction, AnyObject, MaybeParameters } from '../types.js'
4
5
  import { _objectAssign, MISS } from '../types.js'
@@ -20,7 +21,7 @@ export interface AsyncMemoOptions<FN> {
20
21
  cacheKeyFn?: (args: MaybeParameters<FN>) => any
21
22
 
22
23
  /**
23
- * Default to `console`
24
+ * Default to `consoleLogger`
24
25
  */
25
26
  logger?: CommonLogger
26
27
  }
@@ -64,7 +65,7 @@ export const _AsyncMemo =
64
65
  // After it's resolved - it's evicted from the cache and moved to the "proper" `instanceCache`
65
66
  const instancePromiseCache = new Map<AnyObject, Map<any, Promise<any>>>()
66
67
 
67
- const { logger = console, cacheFactory, cacheKeyFn = jsonMemoSerializer } = opt
68
+ const { logger = consoleLogger, cacheFactory, cacheKeyFn = jsonMemoSerializer } = opt
68
69
 
69
70
  const keyStr = String(key)
70
71
  const methodSignature = _getTargetMethodSignature(target, keyStr)
@@ -109,7 +110,7 @@ export const _AsyncMemo =
109
110
  },
110
111
  async err => {
111
112
  // Log the cache error and proceed "as cache Miss"
112
- logger.error(err)
113
+ logger.error({ err })
113
114
  return await onMiss()
114
115
  },
115
116
  )
@@ -130,7 +131,7 @@ export const _AsyncMemo =
130
131
  try {
131
132
  await cache!.set(cacheKey, value)
132
133
  } catch (err) {
133
- logger.error(err) // log and ignore the error
134
+ logger.error({ err }) // log and ignore the error
134
135
  } finally {
135
136
  // Clear the "in-flight" promise cache entry, as we now have a "permanent" cache entry
136
137
  promiseCache!.delete(cacheKey)
@@ -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 type { CommonLogger } from '../log/commonLogger.js'
4
5
  import { SimpleMovingAverage } from '../math/sma.js'
5
6
  import { _stringify } from '../string/stringify.js'
@@ -53,7 +54,7 @@ export interface LogMethodOptions {
53
54
  logResultFn?: LogResultFn
54
55
 
55
56
  /**
56
- * Defaults to `console`
57
+ * Defaults to `consoleLogger`
57
58
  */
58
59
  logger?: CommonLogger
59
60
  }
@@ -84,7 +85,7 @@ export function _LogMethod(opt: LogMethodOptions = {}): MethodDecorator {
84
85
  logStart,
85
86
  logResult,
86
87
  logResultLength = true,
87
- logger = console,
88
+ logger = consoleLogger,
88
89
  } = opt
89
90
  let { logResultFn } = opt
90
91
  if (!logResultFn) {
@@ -156,10 +157,14 @@ function logFinished(
156
157
  }
157
158
 
158
159
  if (err !== undefined) {
159
- t.push('ERROR:', err)
160
+ t.push('ERROR:')
160
161
  } else if (logResultFn) {
161
162
  t.push(...logResultFn(res))
162
163
  }
163
164
 
164
- logger.log(...t.filter(Boolean))
165
+ const msg = t
166
+ .filter(Boolean)
167
+ .map(part => _stringify(part))
168
+ .join(' ')
169
+ logger.log(err === undefined ? msg : { msg, err })
165
170
  }
@@ -1,4 +1,5 @@
1
1
  import { _assert, _assertTypeOf } from '../error/assert.js'
2
+ import { consoleLogger } from '../log/commonLogger.js'
2
3
  import type { CommonLogger } from '../log/commonLogger.js'
3
4
  import type { AnyFunction, AnyObject, MaybeParameters } from '../types.js'
4
5
  import { _objectAssign } from '../types.js'
@@ -21,7 +22,7 @@ export interface MemoOptions<FN> {
21
22
  cacheKeyFn?: (args: MaybeParameters<FN>) => any
22
23
 
23
24
  /**
24
- * Default to `console`
25
+ * Default to `consoleLogger`
25
26
  */
26
27
  logger?: CommonLogger
27
28
  }
@@ -78,7 +79,7 @@ export const _Memo =
78
79
  const instanceCache = new Map<AnyObject, MemoCache>()
79
80
 
80
81
  const {
81
- logger = console,
82
+ logger = consoleLogger,
82
83
  cacheFactory = () => new MapMemoCache(),
83
84
  cacheKeyFn = jsonMemoSerializer,
84
85
  } = opt
@@ -107,7 +108,7 @@ export const _Memo =
107
108
  try {
108
109
  cache.set(cacheKey, value)
109
110
  } catch (err) {
110
- logger.error(err)
111
+ logger.error({ err })
111
112
  }
112
113
 
113
114
  return value
@@ -11,6 +11,7 @@ Otherwise resorts to JSON.stringify.
11
11
  Benchmark shows similar perf for ObjectCache and MapCache.
12
12
  */
13
13
 
14
+ import { consoleLogger } from '../log/commonLogger.js'
14
15
  import type { CommonLogger } from '../log/commonLogger.js'
15
16
  import { _getTargetMethodSignature } from './decorator.util.js'
16
17
  import type { MemoCache } from './memo.util.js'
@@ -55,7 +56,7 @@ export const memoSimple =
55
56
  */
56
57
  const cache: MemoCache = new MapMemoCache()
57
58
 
58
- const { logger = console } = opt
59
+ const { logger = consoleLogger } = opt
59
60
  const keyStr = String(key)
60
61
  const methodSignature = _getTargetMethodSignature(target, keyStr)
61
62
 
@@ -1,3 +1,4 @@
1
+ import { consoleLogger } from '../log/commonLogger.js'
1
2
  import type { AnyFunction, MaybeParameters } from '../types.js'
2
3
  import type { MemoOptions } from './memo.decorator.js'
3
4
  import type { MemoCache } from './memo.util.js'
@@ -17,7 +18,7 @@ export function _memoized<FN extends AnyFunction>(
17
18
  opt: MemoOptions<FN> = {},
18
19
  ): FN & MemoizedFunction {
19
20
  const {
20
- logger = console,
21
+ logger = consoleLogger,
21
22
  cacheFactory = () => new MapMemoCache(),
22
23
  cacheKeyFn = jsonMemoSerializer,
23
24
  } = opt
@@ -37,7 +38,7 @@ export function _memoized<FN extends AnyFunction>(
37
38
  try {
38
39
  cache.set(cacheKey, value)
39
40
  } catch (err) {
40
- logger.error(err)
41
+ logger.error({ err })
41
42
  }
42
43
 
43
44
  return value
@@ -1,3 +1,4 @@
1
+ import { consoleLogger } from '../log/commonLogger.js'
1
2
  import type { AnyAsyncFunction, MaybeParameters } from '../types.js'
2
3
  import { MISS } from '../types.js'
3
4
  import type { AsyncMemoOptions } from './asyncMemo.decorator.js'
@@ -12,7 +13,7 @@ export function _memoizedAsync<FN extends AnyAsyncFunction>(
12
13
  fn: FN,
13
14
  opt: AsyncMemoOptions<FN>,
14
15
  ): FN & MemoizedAsyncFunction {
15
- const { logger = console, cacheFactory, cacheKeyFn = jsonMemoSerializer } = opt
16
+ const { logger = consoleLogger, cacheFactory, cacheKeyFn = jsonMemoSerializer } = opt
16
17
 
17
18
  const cache = cacheFactory()
18
19
 
@@ -24,7 +25,7 @@ export function _memoizedAsync<FN extends AnyAsyncFunction>(
24
25
  try {
25
26
  value = await cache.get(cacheKey)
26
27
  } catch (err) {
27
- logger.error(err)
28
+ logger.error({ err })
28
29
  }
29
30
 
30
31
  if (value !== MISS) {
@@ -37,7 +38,7 @@ export function _memoizedAsync<FN extends AnyAsyncFunction>(
37
38
  try {
38
39
  await cache.set(cacheKey, value)
39
40
  } catch (err) {
40
- logger.error(err)
41
+ logger.error({ err })
41
42
  }
42
43
  })()
43
44
 
@@ -1,4 +1,5 @@
1
1
  import { _since } from '../datetime/time.util.js'
2
+ import { consoleLogger } from '../log/commonLogger.js'
2
3
  import type { CommonLogger } from '../log/commonLogger.js'
3
4
  import type { AnyFunction, UnixTimestampMillis } from '../types.js'
4
5
  import { _anyToError } from './error.util.js'
@@ -21,7 +22,7 @@ export interface TryCatchOptions {
21
22
  logError?: boolean
22
23
 
23
24
  /**
24
- * Default to `console`
25
+ * Default to `consoleLogger`
25
26
  */
26
27
  logger?: CommonLogger
27
28
  }
@@ -35,7 +36,7 @@ export interface TryCatchOptions {
35
36
  * @experimental
36
37
  */
37
38
  export function _tryCatch<T extends AnyFunction>(fn: T, opt: TryCatchOptions = {}): T {
38
- const { onError, logError = true, logSuccess = false, logger = console } = opt
39
+ const { onError, logError = true, logSuccess = false, logger = consoleLogger } = opt
39
40
 
40
41
  const fname = fn.name || 'anonymous'
41
42
 
@@ -52,7 +53,7 @@ export function _tryCatch<T extends AnyFunction>(fn: T, opt: TryCatchOptions = {
52
53
  return r
53
54
  } catch (err) {
54
55
  if (logError) {
55
- logger.warn(`tryCatch.${fname} error in ${_since(started)}:`, err)
56
+ logger.warn({ msg: `tryCatch.${fname} error in ${_since(started)}`, err })
56
57
  }
57
58
 
58
59
  if (onError) {
@@ -162,7 +162,7 @@ export interface FetcherCfg {
162
162
  logWithSearchParams?: boolean
163
163
 
164
164
  /**
165
- * Defaults to `console`.
165
+ * Defaults to `consoleLogger`.
166
166
  */
167
167
  logger?: CommonLogger
168
168
 
@@ -16,6 +16,7 @@ import {
16
16
  HttpRequestError,
17
17
  UnexpectedPassError,
18
18
  } from '../error/error.util.js'
19
+ import { consoleLogger } from '../log/commonLogger.js'
19
20
  import { _clamp } from '../number/number.util.js'
20
21
  import {
21
22
  _filterFalsyValues,
@@ -30,7 +31,6 @@ import { pDelaySignal } from '../promise/pDelay.js'
30
31
  import { pTimeout } from '../promise/pTimeout.js'
31
32
  import { _toUrlOrNull } from '../string/index.js'
32
33
  import { _jsonParse, _jsonParseIfPossible } from '../string/json.util.js'
33
- import { _stringify } from '../string/stringify.js'
34
34
  import type {
35
35
  AnyObject,
36
36
  ErrorDataTuple,
@@ -416,7 +416,7 @@ export class Fetcher {
416
416
  .join(' '),
417
417
  )
418
418
  if (req.logRequestBody && req.init.body) {
419
- logger.log(req.init.body) // todo: check if we can _inspect it
419
+ logger.log({ body: req.init.body }) // todo: check if we can _inspect it
420
420
  }
421
421
  }
422
422
 
@@ -584,7 +584,7 @@ export class Fetcher {
584
584
  )
585
585
 
586
586
  if (req.logResponseBody && res.body !== undefined) {
587
- logger.log(res.body)
587
+ logger.log({ body: res.body })
588
588
  }
589
589
  }
590
590
  }
@@ -688,8 +688,8 @@ export class Fetcher {
688
688
  // lastError = retryStatus.retryStopped
689
689
  // We need to log the response "anyway" if logResponse is true
690
690
  if (res.err && (!retryStatus.retryStopped || res.req.logResponse)) {
691
- this.cfg.logger.error(
692
- [
691
+ this.cfg.logger.error({
692
+ msg: [
693
693
  ' <<',
694
694
  res.fetchResponse?.status || 0,
695
695
  res.signature,
@@ -699,10 +699,9 @@ export class Fetcher {
699
699
  _since(res.req.started),
700
700
  ]
701
701
  .filter(Boolean)
702
- .join(' ') + '\n',
703
- // We're stringifying the error here, otherwise Sentry shows it as [object Object]
704
- _stringify(res.err.cause || res.err),
705
- )
702
+ .join(' '),
703
+ err: res.err.cause || res.err,
704
+ })
706
705
  }
707
706
 
708
707
  if (retryStatus.retryStopped) return
@@ -847,7 +846,7 @@ export class Fetcher {
847
846
  }
848
847
 
849
848
  private normalizeCfg(cfg: FetcherCfg & FetcherOptions): FetcherNormalizedCfg {
850
- const { debug = false, logger = console } = cfg
849
+ const { debug = false, logger = consoleLogger } = cfg
851
850
 
852
851
  if (cfg.baseUrl?.endsWith('/')) {
853
852
  logger.warn(`Fetcher: baseUrl should not end with slash: ${cfg.baseUrl}`)