Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .talismanrc
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
fileignoreconfig:
- filename: pnpm-lock.yaml
checksum: 763c12b0555cbd63ca4015664e08de315f0e675125a34de2d9c8d1a73a3723e8
checksum: 3894686f64c8bf322cb7917c79193268344c68037ef1a41808f1509fc227087d
version: '1.0'
29 changes: 26 additions & 3 deletions packages/contentstack-utilities/src/logger/logger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ export default class Logger {
winston.format.printf((info) => {
// Apply minimal redaction for files (debugging info preserved)
const redactedInfo = this.redact(info, false);
return JSON.stringify(redactedInfo);
return this.safeStringify(redactedInfo);
}),
),
}),
Expand Down Expand Up @@ -117,6 +117,26 @@ export default class Logger {
}
}

/**
* Stringifies a log entry without throwing on circular references.
* `redact()` can fall back to the original (still-circular) object when
* cloning fails, so this must never assume the input is cycle-free.
*/
private safeStringify(value: any): string {
const seen = new WeakSet();
try {
return JSON.stringify(value, (_key, val) => {
if (typeof val === 'object' && val !== null) {
if (seen.has(val)) return '[Circular]';
seen.add(val);
}
return val;
});
} catch {
return JSON.stringify({ level: value?.level, message: value?.message ?? '[Unserializable log entry]' });
}
}

private shouldLog(level: LogType, target: 'console' | 'file'): boolean {
// If console logging is disabled, don't log to console
if (target === 'console' && this.config.consoleLoggingEnabled === false) {
Expand Down Expand Up @@ -186,9 +206,12 @@ export default class Logger {
this.loggers.error.error(logPayload);
}

// For console, use debug level if hidden, otherwise error level
// For console, use debug level if hidden, otherwise error level. Each level's
// winston logger instance bundles both the file and console transports, so only
// write again here when the target differs from the one already written above —
// otherwise this would duplicate both the console line and the file entry.
const consoleLevel: LogType = params.hidden ? 'debug' : 'error';
if (this.shouldLog(consoleLevel, 'console')) {
if (consoleLevel !== 'error' && this.shouldLog(consoleLevel, 'console')) {
this.loggers[consoleLevel].error(logPayload);
}
}
Expand Down
2 changes: 1 addition & 1 deletion packages/contentstack/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -162,4 +162,4 @@
}
},
"repository": "https://github.com/contentstack/cli"
}
}
Loading