UNPKG

@baseplate-dev/sync

Version:

Library for syncing Baseplate descriptions

157 lines 5.3 kB
import { createTypedEventEmitter } from '@baseplate-dev/utils'; function serializeError(error) { const serialized = { type: error.constructor.name, message: error.message, }; if (error.stack) { serialized.stack = error.stack; } // Handle nested errors (cause property) if (error.cause && error.cause instanceof Error) { serialized.cause = serializeError(error.cause); } // Copy any additional enumerable properties for (const key of Object.getOwnPropertyNames(error)) { if (key !== 'name' && key !== 'message' && key !== 'stack' && key !== 'cause') { try { const descriptor = Object.getOwnPropertyDescriptor(error, key); if (descriptor?.enumerable) { serialized[key] = error[key]; } } catch { // Ignore properties that can't be accessed } } } return serialized; } function parseLogArgs(...args) { if (args.length === 1) { const arg = args[0]; if (typeof arg === 'string') { return { message: arg }; } else if (arg instanceof Error) { // Error object - serialize to metadata.err return { message: arg.message, metadata: { err: serializeError(arg) }, }; } else if (typeof arg === 'object' && arg !== null) { // Object - check for message/msg properties const obj = arg; const message = typeof obj.message === 'string' ? obj.message : typeof obj.msg === 'string' ? obj.msg : ''; // Create metadata without the message/msg properties const metadata = {}; for (const [key, value] of Object.entries(obj)) { if (key !== 'message' && key !== 'msg') { metadata[key] = value; } } return { message, metadata: Object.keys(metadata).length > 0 ? metadata : undefined, }; } else { return { message: String(arg) }; } } else { const [firstArg, stringMessage] = args; if (firstArg instanceof Error) { // Error with message override return { message: stringMessage ?? firstArg.message, metadata: { err: serializeError(firstArg) }, }; } else if (typeof firstArg === 'object' && firstArg !== null) { // Object with message override const obj = firstArg; const fallbackMessage = typeof obj.message === 'string' ? obj.message : typeof obj.msg === 'string' ? obj.msg : ''; // Create metadata without message/msg properties const metadata = {}; for (const [key, value] of Object.entries(obj)) { if (key !== 'message' && key !== 'msg') { metadata[key] = value; } } return { message: stringMessage ?? fallbackMessage, metadata: Object.keys(metadata).length > 0 ? metadata : undefined, }; } else { return { message: stringMessage ?? String(firstArg), metadata: undefined, }; } } } export function createEventedLogger() { const eventEmitter = createTypedEventEmitter(); return { error(...args) { const parsed = parseLogArgs(...args); eventEmitter.emit('error', parsed.message); eventEmitter.emit('message', { level: 'error', message: parsed.message, metadata: parsed.metadata, }); }, warn(...args) { const parsed = parseLogArgs(...args); eventEmitter.emit('log', parsed.message); eventEmitter.emit('message', { level: 'warn', message: parsed.message, metadata: parsed.metadata, }); }, info(...args) { const parsed = parseLogArgs(...args); eventEmitter.emit('log', parsed.message); eventEmitter.emit('message', { level: 'info', message: parsed.message, metadata: parsed.metadata, }); }, debug(...args) { const parsed = parseLogArgs(...args); eventEmitter.emit('log', parsed.message); eventEmitter.emit('message', { level: 'debug', message: parsed.message, metadata: parsed.metadata, }); }, onMessage(listener) { return eventEmitter.on('message', listener); }, onLog(listener) { return eventEmitter.on('log', listener); }, onError(listener) { return eventEmitter.on('error', listener); }, }; } //# sourceMappingURL=evented-logger.js.map