-
Notifications
You must be signed in to change notification settings - Fork 4
safeStringify & %c support #121
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 4 commits
9923bef
60b1630
3bcb512
a4fb9d8
a2abb83
e21d320
1edfe1d
6e4aca8
6249c1f
173096e
9d539b0
47cd3d9
0bb8a8c
76730de
a1244bc
991f49b
8ba75e1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -13,6 +13,73 @@ | |
| const consoleOutput: ConsoleLogEvent[] = []; | ||
| let isInitialized = false; | ||
|
|
||
| /** | ||
|
Check warning on line 16 in src/addons/consoleCatcher.ts
|
||
| * Safely stringifies objects handling circular references | ||
| */ | ||
| const safeStringify = (obj: unknown): string => { | ||
| const seen = new WeakSet(); | ||
|
|
||
| return JSON.stringify(obj, (key, value) => { | ||
|
|
||
| if (typeof value === 'object' && value !== null) { | ||
|
|
||
| if (seen.has(value)) { | ||
| return '[Circular]'; | ||
| } | ||
| seen.add(value); | ||
| } | ||
|
|
||
| return value; | ||
| }); | ||
| }; | ||
|
|
||
| /** | ||
|
Check warning on line 36 in src/addons/consoleCatcher.ts
|
||
| * Formats console arguments handling %c directives | ||
| */ | ||
| const formatConsoleArgs = ( | ||
| args: unknown[] | ||
| ): { message: string; styles: string[] } => { | ||
| if (args.length === 0) return { message: '', styles: [] }; | ||
|
Check warning on line 42 in src/addons/consoleCatcher.ts
|
||
|
|
||
| const firstArg = args[0]; | ||
| if (typeof firstArg !== 'string' || !firstArg.includes('%c')) { | ||
|
Check warning on line 45 in src/addons/consoleCatcher.ts
|
||
|
|
||
| return { | ||
| message: args | ||
| .map((arg) => (typeof arg === 'string' ? arg : safeStringify(arg))) | ||
|
||
| .join(' '), | ||
| styles: [], | ||
| }; | ||
| } | ||
|
|
||
| // Handle %c formatting | ||
| const message = args[0] as string; | ||
| const styles: string[] = []; | ||
|
|
||
| // Extract styles from arguments | ||
| let styleIndex = 0; | ||
|
|
||
| for (let i = 1; i < args.length; i++) { | ||
| const arg = args[i]; | ||
|
|
||
| if (typeof arg === 'string' && message.indexOf('%c', styleIndex) !== -1) { | ||
| styles.push(arg); | ||
| styleIndex = message.indexOf('%c', styleIndex) + 2; | ||
| } | ||
| } | ||
|
|
||
| // Add remaining arguments that aren't styles | ||
| const remainingArgs = args | ||
| .slice(styles.length + 1) | ||
| .map((arg) => (typeof arg === 'string' ? arg : safeStringify(arg))) | ||
| .join(' '); | ||
|
|
||
| return { | ||
| message: message + (remainingArgs ? ' ' + remainingArgs : ''), | ||
| styles, | ||
| }; | ||
| }; | ||
|
|
||
| const addToConsoleOutput = (logEvent: ConsoleLogEvent): void => { | ||
| if (consoleOutput.length >= MAX_LOGS) { | ||
| consoleOutput.shift(); | ||
|
|
@@ -22,8 +89,10 @@ | |
|
|
||
| const createConsoleEventFromError = ( | ||
| event: ErrorEvent | PromiseRejectionEvent | ||
| ): ConsoleLogEvent => { | ||
|
|
||
| if (event instanceof ErrorEvent) { | ||
|
|
||
| return { | ||
| method: 'error', | ||
| timestamp: new Date(), | ||
|
|
@@ -53,7 +122,13 @@ | |
| } | ||
|
|
||
| isInitialized = true; | ||
| const consoleMethods: string[] = ['log', 'warn', 'error', 'info', 'debug']; | ||
| const consoleMethods: string[] = [ | ||
| 'log', | ||
| 'warn', | ||
| 'error', | ||
| 'info', | ||
| 'debug', | ||
| ]; | ||
|
|
||
| consoleMethods.forEach((method) => { | ||
| if (typeof window.console[method] !== 'function') { | ||
|
|
@@ -63,15 +138,19 @@ | |
| const oldFunction = window.console[method].bind(window.console); | ||
|
|
||
| window.console[method] = function (...args: unknown[]): void { | ||
| const stack = new Error().stack?.split('\n').slice(2).join('\n') || ''; | ||
| const stack = | ||
| new Error().stack?.split('\n').slice(2) | ||
| .join('\n') || ''; | ||
| const { message, styles } = formatConsoleArgs(args); | ||
|
|
||
| const logEvent: ConsoleLogEvent = { | ||
| method, | ||
| timestamp: new Date(), | ||
| type: method, | ||
| message: args.map((arg) => typeof arg === 'string' ? arg : JSON.stringify(arg)).join(' '), | ||
| message, | ||
| stack, | ||
| fileLine: stack.split('\n')[0]?.trim(), | ||
| styles, | ||
| }; | ||
|
|
||
| addToConsoleOutput(logEvent); | ||
|
|
@@ -87,10 +166,12 @@ | |
| }, | ||
|
|
||
| getConsoleLogStack(): ConsoleLogEvent[] { | ||
|
|
||
| return [ ...consoleOutput ]; | ||
| }, | ||
| }; | ||
| }; | ||
|
|
||
| const consoleCatcher = createConsoleCatcher(); | ||
| export const { initConsoleCatcher, getConsoleLogStack, addErrorEvent } = consoleCatcher; | ||
| export const { initConsoleCatcher, getConsoleLogStack, addErrorEvent } = | ||
| consoleCatcher; | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd suggest using
safe-stringifysince it is almost the same, but covered by tests