@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.
- 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 -34
- package/dist/log/commonLogger.js +51 -96
- 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 -138
- 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/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) {
|
package/dist/promise/pQueue.d.ts
CHANGED
package/dist/promise/pRetry.d.ts
CHANGED
package/dist/promise/pRetry.js
CHANGED
|
@@ -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 =
|
|
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)}
|
|
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.
|
|
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": "
|
|
17
|
+
"@naturalcycles/dev-lib": "20.64.0",
|
|
18
18
|
"@types/node": "^26",
|
|
19
19
|
"@types/semver": "^7",
|
|
20
20
|
"typescript": "^7",
|
package/src/asyncManager.ts
CHANGED
|
@@ -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 =
|
|
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
|
|
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 `
|
|
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 =
|
|
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 `
|
|
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 =
|
|
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:'
|
|
160
|
+
t.push('ERROR:')
|
|
160
161
|
} else if (logResultFn) {
|
|
161
162
|
t.push(...logResultFn(res))
|
|
162
163
|
}
|
|
163
164
|
|
|
164
|
-
|
|
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 `
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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
|
|
package/src/error/tryCatch.ts
CHANGED
|
@@ -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 `
|
|
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 =
|
|
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)}
|
|
56
|
+
logger.warn({ msg: `tryCatch.${fname} error in ${_since(started)}`, err })
|
|
56
57
|
}
|
|
57
58
|
|
|
58
59
|
if (onError) {
|
package/src/http/fetcher.ts
CHANGED
|
@@ -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(' ')
|
|
703
|
-
|
|
704
|
-
|
|
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 =
|
|
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}`)
|