Files
insta-recipe/src/lib/server/utils/logger.ts
Giancarmine Salucci 49bccf8f15 simplify
2026-02-18 01:21:44 +01:00

125 lines
3.2 KiB
TypeScript

/**
* 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<string, any> = {
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));
}