/** * Logging Utilities * * Provides error serialization and structured logging utilities to prevent * [object Object] logs in production. All functions handle circular references * and properly serialize Error objects with their properties. * * Features: * - Error serialization with stack traces * - Circular reference detection and handling * - Convenient logging wrappers * - TypeScript-safe error handling */ /** * Serializes an error object to a JSON string. * Handles both Error instances and plain objects. * * @param error - Error object or unknown value to serialize * @returns JSON string representation of the error * * @example * ```typescript * const err = new Error('Something went wrong'); * const serialized = serializeError(err); * // Returns: '{"name": "Error", "message": "Something went wrong", "stack": "..."}' * ``` */ export function serializeError(error: unknown): string { if (error instanceof Error) { const errorObject: Record = { name: error.name, message: error.message, stack: error.stack }; // Add custom properties from the error object for (const key of Object.keys(error)) { if (!(key in errorObject)) { errorObject[key] = (error as any)[key]; } } return JSON.stringify(errorObject, null, 2); } return JSON.stringify(error, null, 2); } /** * Serializes an object to a JSON string with circular reference handling. * Prevents "Converting circular structure to JSON" errors. * * @param obj - Object to serialize * @param maxDepth - Maximum depth for nested objects (default: 10) * @returns JSON string representation of the object * * @example * ```typescript * const circular: any = { a: 1 }; * circular.self = circular; * const serialized = serializeObject(circular); * // Returns: '{"a": 1, "self": "[Circular]"}' * ``` */ export function serializeObject(obj: unknown, maxDepth: number = 10): string { const seen = new WeakSet(); const replacer = (key: string, value: any): any => { if (typeof value === 'object' && value !== null) { if (seen.has(value)) { return '[Circular]'; } seen.add(value); } return value; }; return JSON.stringify(obj, replacer, 2); } /** * Logs an error to console.error with proper serialization. * Convenience wrapper around serializeError(). * * @param prefix - Log prefix (e.g., '[ComponentName]') * @param error - Error object or unknown value to log * * @example * ```typescript * try { * // ... some operation * } catch (error) { * logError('[QueueProcessor]', error); * } * ``` */ export function logError(prefix: string, error: unknown): void { if (error instanceof Error) { console.error(prefix, error.message); if (error.stack) { console.error('Stack:', error.stack); } } else { console.error(prefix, serializeError(error)); } } /** * Logs an object to console.log with proper serialization. * Handles circular references automatically. * * @param prefix - Log prefix (e.g., '[ComponentName]') * @param obj - Object to log * * @example * ```typescript * const config = { url: 'https://example.com', timeout: 5000 }; * logObject('[Config]', config); * ``` */ export function logObject(prefix: string, obj: unknown): void { console.log(prefix, serializeObject(obj)); }