@veryfront/ext-content-mdx 0.1.1190 → 0.1.1192
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/esm/deno.d.ts +6 -0
- package/esm/deno.js +13 -7
- package/esm/src/errors/error-registry/module.d.ts +4 -0
- package/esm/src/errors/error-registry/module.d.ts.map +1 -1
- package/esm/src/errors/error-registry/module.js +16 -0
- package/esm/src/errors/error-registry.d.ts +2 -0
- package/esm/src/errors/error-registry.d.ts.map +1 -1
- package/esm/src/errors/types.d.ts.map +1 -1
- package/esm/src/errors/types.js +5 -2
- package/esm/src/platform/compat/error-introspection.d.ts +12 -1
- package/esm/src/platform/compat/error-introspection.d.ts.map +1 -1
- package/esm/src/platform/compat/error-introspection.js +40 -5
- package/esm/src/platform/compat/path/basic-operations.d.ts.map +1 -1
- package/esm/src/platform/compat/path/basic-operations.js +6 -2
- package/esm/src/platform/compat/path/portable.d.ts.map +1 -1
- package/esm/src/platform/compat/path/portable.js +98 -54
- package/esm/src/platform/compat/path/resolution.d.ts.map +1 -1
- package/esm/src/platform/compat/path/resolution.js +14 -5
- package/esm/src/platform/compat/primordials/array.d.ts +8 -0
- package/esm/src/platform/compat/primordials/array.d.ts.map +1 -0
- package/esm/src/platform/compat/primordials/array.js +33 -0
- package/esm/src/transforms/import-rewriter/url-builder.d.ts +6 -0
- package/esm/src/transforms/import-rewriter/url-builder.d.ts.map +1 -1
- package/esm/src/transforms/import-rewriter/url-builder.js +96 -29
- package/esm/src/utils/base64url.d.ts.map +1 -1
- package/esm/src/utils/base64url.js +10 -4
- package/esm/src/utils/bundle-manifest.d.ts +19 -1
- package/esm/src/utils/bundle-manifest.d.ts.map +1 -1
- package/esm/src/utils/bundle-manifest.js +124 -27
- package/esm/src/utils/constants/limits.d.ts +1 -1
- package/esm/src/utils/constants/limits.d.ts.map +1 -1
- package/esm/src/utils/constants/limits.js +1 -1
- package/esm/src/utils/hash-utils.d.ts.map +1 -1
- package/esm/src/utils/hash-utils.js +32 -6
- package/esm/src/utils/id.d.ts +16 -0
- package/esm/src/utils/id.d.ts.map +1 -0
- package/esm/src/utils/id.js +69 -0
- package/esm/src/utils/import-lockfile.d.ts +52 -1
- package/esm/src/utils/import-lockfile.d.ts.map +1 -1
- package/esm/src/utils/import-lockfile.js +1042 -58
- package/esm/src/utils/index.d.ts +1 -1
- package/esm/src/utils/index.d.ts.map +1 -1
- package/esm/src/utils/index.js +1 -1
- package/esm/src/utils/logger/logger.d.ts +1 -0
- package/esm/src/utils/logger/logger.d.ts.map +1 -1
- package/esm/src/utils/logger/logger.js +359 -78
- package/esm/src/utils/logger/redact.d.ts +4 -2
- package/esm/src/utils/logger/redact.d.ts.map +1 -1
- package/esm/src/utils/logger/redact.js +300 -112
- package/esm/src/utils/logger/serialization.d.ts +3 -0
- package/esm/src/utils/logger/serialization.d.ts.map +1 -0
- package/esm/src/utils/logger/serialization.js +81 -0
- package/esm/src/utils/memoize.d.ts +1 -1
- package/esm/src/utils/memoize.d.ts.map +1 -1
- package/esm/src/utils/memoize.js +16 -5
- package/esm/src/utils/path-utils.d.ts.map +1 -1
- package/esm/src/utils/path-utils.js +4 -2
- package/esm/src/utils/sleep.d.ts +8 -0
- package/esm/src/utils/sleep.d.ts.map +1 -1
- package/esm/src/utils/sleep.js +11 -2
- package/esm/src/utils/timer.d.ts +10 -0
- package/esm/src/utils/timer.d.ts.map +1 -0
- package/esm/src/utils/timer.js +19 -0
- package/esm/src/utils/version-constant.d.ts +1 -1
- package/esm/src/utils/version-constant.js +1 -1
- package/package.json +2 -2
|
@@ -3,7 +3,35 @@ import { isStdoutTTY } from "../../platform/compat/process/lifecycle.js";
|
|
|
3
3
|
import { isTruthyEnvValue } from "../constants/env.js";
|
|
4
4
|
import { RUNTIME_VERSION } from "../version.js";
|
|
5
5
|
import { ANSI, colorize, formatContextText, formatTimestamp, LEVEL_COLORS, LEVEL_GLYPHS, padTag, serializeError, } from "./core.js";
|
|
6
|
-
import { redactSensitive, sanitizeSerializedError, sanitizeUrlCredentials } from "./redact.js";
|
|
6
|
+
import { REDACTED, redactForSerialization, redactSensitive, sanitizeSerializedError, sanitizeUrlCredentials, } from "./redact.js";
|
|
7
|
+
import { stringifyRedactedJson } from "./serialization.js";
|
|
8
|
+
const apply = Reflect.apply;
|
|
9
|
+
const arrayPush = Array.prototype.push;
|
|
10
|
+
const arrayIsArray = Array.isArray;
|
|
11
|
+
const NativeConsole = console;
|
|
12
|
+
const NativeDate = Date;
|
|
13
|
+
const dateToISOString = Date.prototype.toISOString;
|
|
14
|
+
const NativePerformance = performance;
|
|
15
|
+
const performanceNow = Performance.prototype.now;
|
|
16
|
+
const numberRound = Math.round;
|
|
17
|
+
const objectCreate = Object.create;
|
|
18
|
+
const objectGetPrototypeOf = Object.getPrototypeOf;
|
|
19
|
+
const NativeSet = Set;
|
|
20
|
+
const setAdd = Set.prototype.add;
|
|
21
|
+
const setClear = Set.prototype.clear;
|
|
22
|
+
const setDelete = Set.prototype.delete;
|
|
23
|
+
const setValues = Set.prototype.values;
|
|
24
|
+
const setIteratorNext = objectGetPrototypeOf(new NativeSet().values()).next;
|
|
25
|
+
const stringToLowerCase = String.prototype.toLowerCase;
|
|
26
|
+
const stringToUpperCase = String.prototype.toUpperCase;
|
|
27
|
+
function readPerformanceNow() {
|
|
28
|
+
try {
|
|
29
|
+
return apply(performanceNow, NativePerformance, []);
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
return 0;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
7
35
|
export var LogLevel;
|
|
8
36
|
(function (LogLevel) {
|
|
9
37
|
LogLevel[LogLevel["DEBUG"] = 0] = "DEBUG";
|
|
@@ -21,7 +49,7 @@ const LOG_LEVEL_MAP = {
|
|
|
21
49
|
function parseLogLevel(levelString) {
|
|
22
50
|
if (!levelString)
|
|
23
51
|
return undefined;
|
|
24
|
-
return LOG_LEVEL_MAP[levelString
|
|
52
|
+
return LOG_LEVEL_MAP[apply(stringToUpperCase, levelString, [])];
|
|
25
53
|
}
|
|
26
54
|
/**
|
|
27
55
|
* Determine the log level based on environment variables.
|
|
@@ -55,7 +83,7 @@ function getDefaultFormat(envFormat = getHostEnv("LOG_FORMAT"), envMode = getHos
|
|
|
55
83
|
*/
|
|
56
84
|
let loggerConfig = null;
|
|
57
85
|
let legacyLogRecordEmitter = null;
|
|
58
|
-
const logRecordSubscribers = new
|
|
86
|
+
const logRecordSubscribers = new NativeSet();
|
|
59
87
|
/**
|
|
60
88
|
* Re-read logger configuration from environment variables.
|
|
61
89
|
* Call after loading .env files so the logger picks up any overrides.
|
|
@@ -95,15 +123,15 @@ export function __registerLogRecordEmitter(emitter) {
|
|
|
95
123
|
}
|
|
96
124
|
/** Subscribe to process-level structured log records. Returns an unregister function. */
|
|
97
125
|
export function __subscribeLogRecordEmitter(emitter) {
|
|
98
|
-
logRecordSubscribers
|
|
126
|
+
apply(setAdd, logRecordSubscribers, [emitter]);
|
|
99
127
|
return () => {
|
|
100
|
-
logRecordSubscribers
|
|
128
|
+
apply(setDelete, logRecordSubscribers, [emitter]);
|
|
101
129
|
};
|
|
102
130
|
}
|
|
103
131
|
/** Reset the process-level structured log emitter. Only intended for tests. */
|
|
104
132
|
export function __resetLogRecordEmitterForTests() {
|
|
105
133
|
legacyLogRecordEmitter = null;
|
|
106
|
-
logRecordSubscribers
|
|
134
|
+
apply(setClear, logRecordSubscribers, []);
|
|
107
135
|
}
|
|
108
136
|
function resolveLoggerConfig() {
|
|
109
137
|
if (loggerConfig === null) {
|
|
@@ -115,6 +143,28 @@ function resolveLoggerConfig() {
|
|
|
115
143
|
}
|
|
116
144
|
return loggerConfig;
|
|
117
145
|
}
|
|
146
|
+
function sanitizeLogString(value, fallback) {
|
|
147
|
+
try {
|
|
148
|
+
return sanitizeUrlCredentials(typeof value === "string" ? value : String(value));
|
|
149
|
+
}
|
|
150
|
+
catch {
|
|
151
|
+
return fallback;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
function currentIsoTimestamp() {
|
|
155
|
+
return apply(dateToISOString, new NativeDate(), []);
|
|
156
|
+
}
|
|
157
|
+
function snapshotLogContext(context) {
|
|
158
|
+
try {
|
|
159
|
+
const snapshot = redactForSerialization(context);
|
|
160
|
+
return typeof snapshot === "object" && snapshot !== null && !arrayIsArray(snapshot)
|
|
161
|
+
? snapshot
|
|
162
|
+
: {};
|
|
163
|
+
}
|
|
164
|
+
catch {
|
|
165
|
+
return {};
|
|
166
|
+
}
|
|
167
|
+
}
|
|
118
168
|
/**
|
|
119
169
|
* Extract context from variadic args.
|
|
120
170
|
* First object argument becomes context, errors are handled specially.
|
|
@@ -123,21 +173,27 @@ function extractContext(args) {
|
|
|
123
173
|
let context;
|
|
124
174
|
let error;
|
|
125
175
|
for (const arg of args) {
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
}
|
|
130
|
-
if (typeof arg === "object" && arg !== null && !Array.isArray(arg)) {
|
|
131
|
-
const contextArg = arg;
|
|
132
|
-
if (contextArg.error instanceof Error) {
|
|
133
|
-
const { error: contextError, ...rest } = contextArg;
|
|
134
|
-
error = serializeError(contextError);
|
|
135
|
-
if (Object.keys(rest).length > 0) {
|
|
136
|
-
context = { ...context, ...rest };
|
|
137
|
-
}
|
|
176
|
+
try {
|
|
177
|
+
if (arg instanceof Error) {
|
|
178
|
+
error = serializeError(arg);
|
|
138
179
|
continue;
|
|
139
180
|
}
|
|
140
|
-
|
|
181
|
+
if (typeof arg === "object" && arg !== null && !arrayIsArray(arg)) {
|
|
182
|
+
const contextArg = arg;
|
|
183
|
+
if (contextArg.error instanceof Error) {
|
|
184
|
+
const { error: contextError, ...rest } = contextArg;
|
|
185
|
+
error = serializeError(contextError);
|
|
186
|
+
if (Object.keys(rest).length > 0) {
|
|
187
|
+
context = { ...context, ...rest };
|
|
188
|
+
}
|
|
189
|
+
continue;
|
|
190
|
+
}
|
|
191
|
+
context = { ...context, ...contextArg };
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
catch {
|
|
195
|
+
// Logging accepts application-owned objects. Ignore an unreadable value
|
|
196
|
+
// rather than allowing proxy traps or getters to break the caller.
|
|
141
197
|
}
|
|
142
198
|
}
|
|
143
199
|
return { context, error };
|
|
@@ -196,6 +252,29 @@ function extractAliasToEntryField(entry, context, sourceKey, targetKey, coerce)
|
|
|
196
252
|
function sanitizeStringFieldValue(value) {
|
|
197
253
|
return sanitizeUrlCredentials(String(value));
|
|
198
254
|
}
|
|
255
|
+
function createFallbackLogEntry(entry) {
|
|
256
|
+
const fallback = objectCreate(null);
|
|
257
|
+
fallback.timestamp = entry.timestamp;
|
|
258
|
+
fallback.level = entry.level;
|
|
259
|
+
fallback.service = entry.service;
|
|
260
|
+
fallback.veryfrontVersion = entry.veryfrontVersion;
|
|
261
|
+
fallback.message = entry.message;
|
|
262
|
+
if (entry.component !== undefined)
|
|
263
|
+
fallback.component = entry.component;
|
|
264
|
+
const context = objectCreate(null);
|
|
265
|
+
context.unserializable_context = REDACTED;
|
|
266
|
+
fallback.context = context;
|
|
267
|
+
return fallback;
|
|
268
|
+
}
|
|
269
|
+
/**
|
|
270
|
+
* Serialize a log entry without letting caller-controlled values or inherited
|
|
271
|
+
* `toJSON` hooks escape the logging boundary. The redacted snapshot normalizes
|
|
272
|
+
* BigInt and deliberate serializers first, then shadows inherited hooks on
|
|
273
|
+
* every owned object and array before native JSON serialization.
|
|
274
|
+
*/
|
|
275
|
+
function stringifyLogEntry(entry) {
|
|
276
|
+
return stringifyRedactedJson(entry, createFallbackLogEntry(entry));
|
|
277
|
+
}
|
|
199
278
|
class ConsoleLogger {
|
|
200
279
|
prefix;
|
|
201
280
|
options;
|
|
@@ -204,24 +283,43 @@ class ConsoleLogger {
|
|
|
204
283
|
constructor(prefix, boundContext, componentName, options = {}) {
|
|
205
284
|
this.prefix = prefix;
|
|
206
285
|
this.options = options;
|
|
207
|
-
this.boundContext = boundContext ?? {};
|
|
208
|
-
this.componentName = componentName
|
|
286
|
+
this.boundContext = snapshotLogContext(boundContext ?? {});
|
|
287
|
+
this.componentName = componentName === undefined
|
|
288
|
+
? undefined
|
|
289
|
+
: sanitizeLogString(componentName, REDACTED);
|
|
209
290
|
}
|
|
210
291
|
child(context) {
|
|
211
|
-
|
|
292
|
+
const childContext = snapshotLogContext(context);
|
|
293
|
+
return new ConsoleLogger(this.prefix, { ...this.boundContext, ...childContext }, this.componentName, this.options);
|
|
212
294
|
}
|
|
213
295
|
component(name) {
|
|
214
296
|
return new ConsoleLogger(this.prefix, { ...this.boundContext }, name, this.options);
|
|
215
297
|
}
|
|
298
|
+
createEmergencyEntry(level) {
|
|
299
|
+
const entry = {
|
|
300
|
+
timestamp: currentIsoTimestamp(),
|
|
301
|
+
level,
|
|
302
|
+
service: apply(stringToLowerCase, sanitizeLogString(this.prefix, "veryfront"), []),
|
|
303
|
+
veryfrontVersion: RUNTIME_VERSION,
|
|
304
|
+
message: REDACTED,
|
|
305
|
+
context: { unserializable_context: REDACTED },
|
|
306
|
+
};
|
|
307
|
+
if (this.componentName)
|
|
308
|
+
entry.component = this.componentName;
|
|
309
|
+
return entry;
|
|
310
|
+
}
|
|
216
311
|
createEntry(level, message, args) {
|
|
217
312
|
const { context, error } = extractContext(args);
|
|
218
313
|
const mergedContext = { ...this.boundContext, ...context };
|
|
219
314
|
const entry = {
|
|
220
|
-
timestamp:
|
|
315
|
+
timestamp: currentIsoTimestamp(),
|
|
221
316
|
level,
|
|
222
|
-
service: this.prefix
|
|
317
|
+
service: apply(stringToLowerCase, this.prefix, []),
|
|
223
318
|
veryfrontVersion: RUNTIME_VERSION,
|
|
224
|
-
message,
|
|
319
|
+
// The message string bypasses the key-based context redactor, so scrub
|
|
320
|
+
// credential-shaped text (URL userinfo, ?access_token=, header dumps)
|
|
321
|
+
// embedded directly in the message before emission (#1989).
|
|
322
|
+
message: sanitizeLogString(message, REDACTED),
|
|
225
323
|
};
|
|
226
324
|
if (this.componentName)
|
|
227
325
|
entry.component = this.componentName;
|
|
@@ -308,18 +406,21 @@ class ConsoleLogger {
|
|
|
308
406
|
}
|
|
309
407
|
formatJson(level, message, args) {
|
|
310
408
|
const entry = this.createEntry(level, message, args);
|
|
311
|
-
return
|
|
409
|
+
return stringifyLogEntry(entry);
|
|
312
410
|
}
|
|
313
411
|
formatTextLine(level, message, args) {
|
|
314
412
|
const { context, error } = extractContext(args);
|
|
315
413
|
const mergedContext = { ...this.boundContext, ...context };
|
|
316
414
|
const enableColor = shouldUseColor();
|
|
415
|
+
// Mirror the JSON path: the message string bypasses the key-based context
|
|
416
|
+
// redactor, so scrub credential-shaped text before rendering (#1989).
|
|
417
|
+
const safeMessage = sanitizeLogString(message, REDACTED);
|
|
317
418
|
const contextText = formatContextText(redactSensitive(mergedContext), sanitizeSerializedError(error), enableColor);
|
|
318
419
|
const { preset } = resolveLoggerConfig();
|
|
319
420
|
if (preset === "cli") {
|
|
320
421
|
// CLI preset: no timestamp or tag — 2-space indent + glyph only.
|
|
321
422
|
const glyph = colorize(CLI_LEVEL_GLYPHS[level], LEVEL_COLORS[level], enableColor);
|
|
322
|
-
return ` ${glyph} ${
|
|
423
|
+
return ` ${glyph} ${safeMessage}${contextText}`;
|
|
323
424
|
}
|
|
324
425
|
const timestamp = colorize(formatTimestamp(), ANSI.dim, enableColor);
|
|
325
426
|
const tag = colorize(padTag(this.prefix), TAG_COLORS[this.prefix] ?? ANSI.cyan, enableColor);
|
|
@@ -327,63 +428,104 @@ class ConsoleLogger {
|
|
|
327
428
|
const componentTag = this.componentName
|
|
328
429
|
? ` ${colorize(`[${this.componentName}]`, ANSI.dim, enableColor)}`
|
|
329
430
|
: "";
|
|
330
|
-
return `${timestamp} ${tag} ${glyph}${componentTag} ${
|
|
331
|
-
}
|
|
332
|
-
log(level, logLevel,
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
entry = this.createEntry(level, message, args);
|
|
340
|
-
return JSON.stringify(entry);
|
|
341
|
-
})()
|
|
342
|
-
: this.formatTextLine(level, message, args);
|
|
343
|
-
const emittedEntry = entry ?? this.createEntry(level, message, args);
|
|
344
|
-
if (legacyLogRecordEmitter) {
|
|
431
|
+
return `${timestamp} ${tag} ${glyph}${componentTag} ${safeMessage}${contextText}`;
|
|
432
|
+
}
|
|
433
|
+
log(level, logLevel, consoleMethod, message, args) {
|
|
434
|
+
try {
|
|
435
|
+
const { level: resolvedLevel, format: resolvedFormat } = resolveLoggerConfig();
|
|
436
|
+
if (resolvedLevel > logLevel)
|
|
437
|
+
return;
|
|
438
|
+
let emittedEntry;
|
|
439
|
+
let line;
|
|
345
440
|
try {
|
|
346
|
-
|
|
441
|
+
if (resolvedFormat === "json") {
|
|
442
|
+
emittedEntry = this.createEntry(level, message, args);
|
|
443
|
+
line = stringifyLogEntry(emittedEntry);
|
|
444
|
+
}
|
|
445
|
+
else {
|
|
446
|
+
line = this.formatTextLine(level, message, args);
|
|
447
|
+
emittedEntry = this.createEntry(level, message, args);
|
|
448
|
+
}
|
|
347
449
|
}
|
|
348
|
-
catch
|
|
349
|
-
|
|
450
|
+
catch {
|
|
451
|
+
try {
|
|
452
|
+
emittedEntry = this.createEmergencyEntry(level);
|
|
453
|
+
line = resolvedFormat === "json"
|
|
454
|
+
? stringifyLogEntry(emittedEntry)
|
|
455
|
+
: `${apply(stringToUpperCase, level, [])}: ${REDACTED}`;
|
|
456
|
+
}
|
|
457
|
+
catch {
|
|
458
|
+
return;
|
|
459
|
+
}
|
|
350
460
|
}
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
461
|
+
if (legacyLogRecordEmitter) {
|
|
462
|
+
try {
|
|
463
|
+
legacyLogRecordEmitter(emittedEntry);
|
|
464
|
+
}
|
|
465
|
+
catch (_) {
|
|
466
|
+
/* do not let telemetry export failures affect application logging */
|
|
467
|
+
}
|
|
357
468
|
}
|
|
358
|
-
|
|
359
|
-
|
|
469
|
+
// Snapshot before invoking callbacks. Native Set iterators observe values
|
|
470
|
+
// deleted and reinserted during iteration, which can otherwise invoke one
|
|
471
|
+
// subscriber repeatedly (or keep a single log call alive indefinitely).
|
|
472
|
+
const subscribers = [];
|
|
473
|
+
const iterator = apply(setValues, logRecordSubscribers, []);
|
|
474
|
+
while (true) {
|
|
475
|
+
const next = apply(setIteratorNext, iterator, []);
|
|
476
|
+
if (next.done)
|
|
477
|
+
break;
|
|
478
|
+
apply(arrayPush, subscribers, [next.value]);
|
|
360
479
|
}
|
|
480
|
+
for (let index = 0; index < subscribers.length; index++) {
|
|
481
|
+
const subscriber = subscribers[index];
|
|
482
|
+
if (subscriber === legacyLogRecordEmitter)
|
|
483
|
+
continue;
|
|
484
|
+
try {
|
|
485
|
+
subscriber(emittedEntry);
|
|
486
|
+
}
|
|
487
|
+
catch (_) {
|
|
488
|
+
/* do not let telemetry export failures affect application logging */
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
const consoleFn = NativeConsole[consoleMethod];
|
|
492
|
+
if (typeof consoleFn === "function") {
|
|
493
|
+
try {
|
|
494
|
+
apply(consoleFn, NativeConsole, [line]);
|
|
495
|
+
}
|
|
496
|
+
catch (_) {
|
|
497
|
+
/* logging sink failures must not affect application control flow */
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
catch (_) {
|
|
502
|
+
/* every logging concern is contained by this final nonthrowing boundary */
|
|
361
503
|
}
|
|
362
|
-
consoleFn(line);
|
|
363
504
|
}
|
|
364
505
|
debug(message, ...args) {
|
|
365
|
-
this.log("debug", LogLevel.DEBUG,
|
|
506
|
+
this.log("debug", LogLevel.DEBUG, "debug", message, args);
|
|
366
507
|
}
|
|
367
508
|
info(message, ...args) {
|
|
368
|
-
this.log("info", LogLevel.INFO,
|
|
509
|
+
this.log("info", LogLevel.INFO, "log", message, args);
|
|
369
510
|
}
|
|
370
511
|
warn(message, ...args) {
|
|
371
|
-
this.log("warn", LogLevel.WARN,
|
|
512
|
+
this.log("warn", LogLevel.WARN, "warn", message, args);
|
|
372
513
|
}
|
|
373
514
|
error(message, ...args) {
|
|
374
|
-
this.log("error", LogLevel.ERROR,
|
|
515
|
+
this.log("error", LogLevel.ERROR, "error", message, args);
|
|
375
516
|
}
|
|
376
517
|
async time(label, fn) {
|
|
377
|
-
const
|
|
518
|
+
const safeLabel = sanitizeLogString(label, REDACTED);
|
|
519
|
+
const start = readPerformanceNow();
|
|
378
520
|
try {
|
|
379
521
|
const result = await fn();
|
|
380
|
-
const durationMs =
|
|
381
|
-
this.debug(`${
|
|
522
|
+
const durationMs = readPerformanceNow() - start;
|
|
523
|
+
this.debug(`${safeLabel} completed`, { durationMs: numberRound(durationMs) });
|
|
382
524
|
return result;
|
|
383
525
|
}
|
|
384
526
|
catch (error) {
|
|
385
|
-
const durationMs =
|
|
386
|
-
this.error(`${
|
|
527
|
+
const durationMs = readPerformanceNow() - start;
|
|
528
|
+
this.error(`${safeLabel} failed`, { durationMs: numberRound(durationMs) }, error);
|
|
387
529
|
throw error;
|
|
388
530
|
}
|
|
389
531
|
}
|
|
@@ -444,8 +586,147 @@ export function __resetTraceContextGetterForTests() {
|
|
|
444
586
|
traceContextGetter = null;
|
|
445
587
|
}
|
|
446
588
|
function withRequestLogger(base) {
|
|
447
|
-
|
|
448
|
-
|
|
589
|
+
try {
|
|
590
|
+
const ctx = requestContextGetter?.();
|
|
591
|
+
return ctx?.logger ?? base;
|
|
592
|
+
}
|
|
593
|
+
catch {
|
|
594
|
+
return base;
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
function selectContextLogger(base) {
|
|
598
|
+
return { selected: withRequestLogger(base), fallback: base };
|
|
599
|
+
}
|
|
600
|
+
function selectComponentLoggers(base, componentName) {
|
|
601
|
+
let fallback = base;
|
|
602
|
+
try {
|
|
603
|
+
fallback = base.component(componentName);
|
|
604
|
+
}
|
|
605
|
+
catch {
|
|
606
|
+
// The base logger itself is still a safe final fallback.
|
|
607
|
+
}
|
|
608
|
+
const requestLogger = withRequestLogger(base);
|
|
609
|
+
if (requestLogger === base)
|
|
610
|
+
return { selected: fallback, fallback };
|
|
611
|
+
try {
|
|
612
|
+
return { selected: requestLogger.component(componentName), fallback };
|
|
613
|
+
}
|
|
614
|
+
catch {
|
|
615
|
+
return { selected: fallback, fallback };
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
function invokeLoggerMethod(logger, method, message, args) {
|
|
619
|
+
try {
|
|
620
|
+
const callback = logger[method];
|
|
621
|
+
if (typeof callback !== "function")
|
|
622
|
+
return false;
|
|
623
|
+
const callArgs = [message];
|
|
624
|
+
for (let index = 0; index < args.length; index++)
|
|
625
|
+
callArgs[index + 1] = args[index];
|
|
626
|
+
apply(callback, logger, callArgs);
|
|
627
|
+
return true;
|
|
628
|
+
}
|
|
629
|
+
catch {
|
|
630
|
+
return false;
|
|
631
|
+
}
|
|
632
|
+
}
|
|
633
|
+
function invokeContextAwareLog(base, method, message, args) {
|
|
634
|
+
invokeSelectedLoggerMethod(selectContextLogger(base), method, message, args);
|
|
635
|
+
}
|
|
636
|
+
function invokeSelectedLoggerMethod(selection, method, message, args) {
|
|
637
|
+
if (invokeLoggerMethod(selection.selected, method, message, args))
|
|
638
|
+
return;
|
|
639
|
+
if (selection.selected !== selection.fallback) {
|
|
640
|
+
invokeLoggerMethod(selection.fallback, method, message, args);
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
function invokeContextAwareComponentLog(base, componentName, method, message, args) {
|
|
644
|
+
invokeSelectedLoggerMethod(selectComponentLoggers(base, componentName), method, message, args);
|
|
645
|
+
}
|
|
646
|
+
function invokeLoggerChild(logger, context) {
|
|
647
|
+
try {
|
|
648
|
+
const callback = logger.child;
|
|
649
|
+
if (typeof callback !== "function")
|
|
650
|
+
return undefined;
|
|
651
|
+
const child = apply(callback, logger, [context]);
|
|
652
|
+
if ((typeof child === "object" && child !== null) || typeof child === "function") {
|
|
653
|
+
return child;
|
|
654
|
+
}
|
|
655
|
+
}
|
|
656
|
+
catch {
|
|
657
|
+
// Request-scoped logger composition must not escape the logging boundary.
|
|
658
|
+
}
|
|
659
|
+
return undefined;
|
|
660
|
+
}
|
|
661
|
+
function invokeSelectedLoggerChild(selection, context) {
|
|
662
|
+
const fallback = invokeLoggerChild(selection.fallback, context) ?? selection.fallback;
|
|
663
|
+
const selected = selection.selected === selection.fallback
|
|
664
|
+
? fallback
|
|
665
|
+
: invokeLoggerChild(selection.selected, context) ?? fallback;
|
|
666
|
+
return createGuardedLogger({ selected, fallback });
|
|
667
|
+
}
|
|
668
|
+
function invokeLoggerComponent(logger, name) {
|
|
669
|
+
try {
|
|
670
|
+
const callback = logger.component;
|
|
671
|
+
if (typeof callback !== "function")
|
|
672
|
+
return undefined;
|
|
673
|
+
const component = apply(callback, logger, [name]);
|
|
674
|
+
if ((typeof component === "object" && component !== null) ||
|
|
675
|
+
typeof component === "function") {
|
|
676
|
+
return component;
|
|
677
|
+
}
|
|
678
|
+
}
|
|
679
|
+
catch {
|
|
680
|
+
// Component composition must remain inside the guarded facade.
|
|
681
|
+
}
|
|
682
|
+
return undefined;
|
|
683
|
+
}
|
|
684
|
+
function selectLoggerComponents(selection, name) {
|
|
685
|
+
const fallback = invokeLoggerComponent(selection.fallback, name) ?? selection.fallback;
|
|
686
|
+
const selected = selection.selected === selection.fallback
|
|
687
|
+
? fallback
|
|
688
|
+
: invokeLoggerComponent(selection.selected, name) ?? fallback;
|
|
689
|
+
return { selected, fallback };
|
|
690
|
+
}
|
|
691
|
+
async function invokeSelectedLoggerTime(selection, label, fn) {
|
|
692
|
+
const safeLabel = sanitizeLogString(label, REDACTED);
|
|
693
|
+
const start = readPerformanceNow();
|
|
694
|
+
try {
|
|
695
|
+
const result = await fn();
|
|
696
|
+
const durationMs = numberRound(readPerformanceNow() - start);
|
|
697
|
+
invokeSelectedLoggerMethod(selection, "debug", `${safeLabel} completed`, [{ durationMs }]);
|
|
698
|
+
return result;
|
|
699
|
+
}
|
|
700
|
+
catch (error) {
|
|
701
|
+
const durationMs = numberRound(readPerformanceNow() - start);
|
|
702
|
+
invokeSelectedLoggerMethod(selection, "error", `${safeLabel} failed`, [{ durationMs }, error]);
|
|
703
|
+
throw error;
|
|
704
|
+
}
|
|
705
|
+
}
|
|
706
|
+
function createGuardedLogger(selection) {
|
|
707
|
+
return {
|
|
708
|
+
debug(message, ...args) {
|
|
709
|
+
invokeSelectedLoggerMethod(selection, "debug", message, args);
|
|
710
|
+
},
|
|
711
|
+
info(message, ...args) {
|
|
712
|
+
invokeSelectedLoggerMethod(selection, "info", message, args);
|
|
713
|
+
},
|
|
714
|
+
warn(message, ...args) {
|
|
715
|
+
invokeSelectedLoggerMethod(selection, "warn", message, args);
|
|
716
|
+
},
|
|
717
|
+
error(message, ...args) {
|
|
718
|
+
invokeSelectedLoggerMethod(selection, "error", message, args);
|
|
719
|
+
},
|
|
720
|
+
time(label, fn) {
|
|
721
|
+
return invokeSelectedLoggerTime(selection, label, fn);
|
|
722
|
+
},
|
|
723
|
+
child(context) {
|
|
724
|
+
return invokeSelectedLoggerChild(selection, context);
|
|
725
|
+
},
|
|
726
|
+
component(name) {
|
|
727
|
+
return createGuardedLogger(selectLoggerComponents(selection, name));
|
|
728
|
+
},
|
|
729
|
+
};
|
|
449
730
|
}
|
|
450
731
|
/**
|
|
451
732
|
* Create a context-aware logger proxy that automatically uses
|
|
@@ -454,22 +735,22 @@ function withRequestLogger(base) {
|
|
|
454
735
|
function createContextAwareLogger(base) {
|
|
455
736
|
return {
|
|
456
737
|
debug(message, ...args) {
|
|
457
|
-
|
|
738
|
+
invokeContextAwareLog(base, "debug", message, args);
|
|
458
739
|
},
|
|
459
740
|
info(message, ...args) {
|
|
460
|
-
|
|
741
|
+
invokeContextAwareLog(base, "info", message, args);
|
|
461
742
|
},
|
|
462
743
|
warn(message, ...args) {
|
|
463
|
-
|
|
744
|
+
invokeContextAwareLog(base, "warn", message, args);
|
|
464
745
|
},
|
|
465
746
|
error(message, ...args) {
|
|
466
|
-
|
|
747
|
+
invokeContextAwareLog(base, "error", message, args);
|
|
467
748
|
},
|
|
468
749
|
time(label, fn) {
|
|
469
|
-
return
|
|
750
|
+
return invokeSelectedLoggerTime(selectContextLogger(base), label, fn);
|
|
470
751
|
},
|
|
471
752
|
child(context) {
|
|
472
|
-
return
|
|
753
|
+
return invokeSelectedLoggerChild(selectContextLogger(base), context);
|
|
473
754
|
},
|
|
474
755
|
component(name) {
|
|
475
756
|
return createComponentAwareLogger(base, name);
|
|
@@ -485,22 +766,22 @@ function createContextAwareLogger(base) {
|
|
|
485
766
|
function createComponentAwareLogger(base, componentName) {
|
|
486
767
|
return {
|
|
487
768
|
debug(message, ...args) {
|
|
488
|
-
|
|
769
|
+
invokeContextAwareComponentLog(base, componentName, "debug", message, args);
|
|
489
770
|
},
|
|
490
771
|
info(message, ...args) {
|
|
491
|
-
|
|
772
|
+
invokeContextAwareComponentLog(base, componentName, "info", message, args);
|
|
492
773
|
},
|
|
493
774
|
warn(message, ...args) {
|
|
494
|
-
|
|
775
|
+
invokeContextAwareComponentLog(base, componentName, "warn", message, args);
|
|
495
776
|
},
|
|
496
777
|
error(message, ...args) {
|
|
497
|
-
|
|
778
|
+
invokeContextAwareComponentLog(base, componentName, "error", message, args);
|
|
498
779
|
},
|
|
499
780
|
time(label, fn) {
|
|
500
|
-
return
|
|
781
|
+
return invokeSelectedLoggerTime(selectComponentLoggers(base, componentName), label, fn);
|
|
501
782
|
},
|
|
502
783
|
child(context) {
|
|
503
|
-
return
|
|
784
|
+
return invokeSelectedLoggerChild(selectComponentLoggers(base, componentName), context);
|
|
504
785
|
},
|
|
505
786
|
component(name) {
|
|
506
787
|
return createComponentAwareLogger(base, name);
|
|
@@ -525,7 +806,7 @@ export const logger = createContextAwareLogger(baseLogger);
|
|
|
525
806
|
* Use this when you need to create a request-scoped logger in middleware.
|
|
526
807
|
*/
|
|
527
808
|
export function getBaseLogger(prefix, options) {
|
|
528
|
-
const resolvedPrefix = prefix
|
|
809
|
+
const resolvedPrefix = apply(stringToUpperCase, prefix, []);
|
|
529
810
|
const validPrefix = resolvedPrefix in BASE_LOGGER_MAP ? resolvedPrefix : "VERYFRONT";
|
|
530
811
|
if (options?.injectTraceContext === false) {
|
|
531
812
|
return createLogger(validPrefix, options);
|
|
@@ -63,8 +63,10 @@ export declare function redactForSerialization(context: unknown): RedactedValue;
|
|
|
63
63
|
* {@link redactSensitive}, which is key-based, this scrubs secrets embedded in
|
|
64
64
|
* the *value* itself:
|
|
65
65
|
*
|
|
66
|
-
* - URL userinfo: `
|
|
67
|
-
* - sensitive query params: `?access_token=abc`
|
|
66
|
+
* - URL userinfo: `https://user:password@example.test/path` -> `https://user:[REDACTED]@example.test/path`
|
|
67
|
+
* - sensitive query params: `?access_token=abc` -> `?access_token=[REDACTED]`
|
|
68
|
+
* - credential assignments: `refreshToken=abc` -> `refreshToken=[REDACTED]`
|
|
69
|
+
* - common provider tokens: `Using token sk-...` -> `Using token [REDACTED]`
|
|
68
70
|
*
|
|
69
71
|
* It is intentionally tolerant: it operates on any string (a DSN, a Mongo URI,
|
|
70
72
|
* an axios error message containing a URL) via regex rather than requiring a
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"redact.d.ts","sourceRoot":"","sources":["../../../../src/src/utils/logger/redact.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,6DAA6D;AAC7D,eAAO,MAAM,QAAQ,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"redact.d.ts","sourceRoot":"","sources":["../../../../src/src/utils/logger/redact.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,6DAA6D;AAC7D,eAAO,MAAM,QAAQ,eAAe,CAAC;AA2KrC;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,MAAM,GAClB,MAAM,CAiDR;AAwDD;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAwBnD;AAED,MAAM,MAAM,aAAa,GACrB,MAAM,GACN,MAAM,GACN,OAAO,GACP,IAAI,GACJ,aAAa,EAAE,GACf;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,aAAa,CAAA;CAAE,CAAC;AA8MrC;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,GAAG,CAAC,CAKhD;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,OAAO,GAAG,aAAa,CAKtE;AAwVD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAyG5D;AAqBD;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CA+BxD;AAED;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CACrC,CAAC,SAAS;IAAE,IAAI,CAAC,EAAE,OAAO,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,SAAS,EAC5E,KAAK,EAAE,CAAC,GAAG,CAAC,CAOb"}
|