@oxog/log 1.0.0 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/logger.ts","../src/types.ts","../src/constants.ts","../src/utils/env.ts","../src/utils/format.ts","../src/transports/console.ts","../src/plugins/core/level.ts","../src/plugins/core/format.ts","../src/plugins/core/timestamp.ts","../src/errors.ts","../src/transports/file.ts","../src/transports/stream.ts","../src/transports/http.ts","../src/transports/localStorage.ts","../src/utils/redact.ts","../src/plugins/optional/redact.ts","../src/utils/source.ts","../src/plugins/optional/source.ts","../src/plugins/optional/timing.ts","../src/plugins/optional/correlation.ts","../src/plugins/optional/buffer.ts","../src/plugins/optional/browser.ts"],"sourcesContent":["/**\n * @oxog/log - Logger Factory\n *\n * Creates logger instances with plugin-based architecture.\n *\n * @packageDocumentation\n */\n\nimport { createKernel } from '@oxog/plugin';\nimport { createEmitter } from '@oxog/emitter';\nimport { pigment } from '@oxog/pigment';\nimport type { Plugin } from '@oxog/types';\nimport type {\n Logger,\n LoggerOptions,\n LogEntry,\n LogContext,\n LogEvents,\n LogLevelName,\n LogLevel,\n Transport,\n Format,\n Unsubscribe,\n} from './types.js';\nimport { LOG_LEVELS, LEVEL_NAMES, DEFAULT_NAME, DEFAULT_LEVEL, DEFAULT_FORMAT } from './constants.js';\nimport { getEnvironment, isNode } from './utils/env.js';\nimport { consoleTransport } from './transports/console.js';\nimport { levelPlugin } from './plugins/core/level.js';\nimport { formatPlugin } from './plugins/core/format.js';\nimport { timestampPlugin } from './plugins/core/timestamp.js';\nimport { ConfigError } from './errors.js';\n\n/**\n * Create a logger instance.\n *\n * @example\n * ```typescript\n * import { createLogger } from '@oxog/log';\n *\n * const logger = createLogger({\n * name: 'my-app',\n * level: 'debug',\n * transports: [consoleTransport()],\n * });\n *\n * logger.info('Hello, world!');\n * ```\n */\nexport function createLogger(options: LoggerOptions = {}): Logger {\n const {\n name = DEFAULT_NAME,\n level = DEFAULT_LEVEL,\n format = DEFAULT_FORMAT,\n colors = true,\n transports = [],\n redact = [],\n source = false,\n timestamp = true,\n sync = { fatal: true, error: true },\n buffer,\n context: initialContext = {},\n plugins = [],\n } = options;\n\n // Validate level\n if (!(level in LOG_LEVELS)) {\n throw new ConfigError(`Invalid log level: ${level}`, 'level');\n }\n\n // Create event emitter\n const emitter = createEmitter<LogEvents>();\n\n // Setup transports\n const activeTransports: Transport[] = [];\n const env = getEnvironment();\n\n // Add default console transport if none specified\n if (transports.length === 0) {\n activeTransports.push(consoleTransport({ colors }));\n } else {\n for (const transport of transports) {\n if (!transport.supports || transport.supports(env as 'node' | 'browser')) {\n activeTransports.push(transport);\n }\n }\n }\n\n // Create kernel context\n const kernelContext: LogContext = {\n name,\n level: LOG_LEVELS[level] as unknown as LogLevel,\n format: resolveFormat(format),\n colors,\n timestamp,\n source,\n transports: activeTransports,\n redactPaths: redact,\n bindings: { ...initialContext },\n correlationId: undefined,\n pigment,\n emitter,\n syncLevels: {\n trace: sync.trace ?? false,\n debug: sync.debug ?? false,\n info: sync.info ?? false,\n warn: sync.warn ?? false,\n error: sync.error ?? true,\n fatal: sync.fatal ?? true,\n },\n bufferOptions: buffer ?? {},\n timers: new Map(),\n buffer: [],\n flushTimerId: undefined,\n };\n\n // Create kernel with plugins\n const kernel = createKernel<LogContext>({ context: kernelContext });\n\n // Install core plugins\n kernel.use(levelPlugin());\n kernel.use(formatPlugin());\n kernel.use(timestampPlugin());\n\n // Install user plugins\n for (const plugin of plugins) {\n kernel.use(plugin);\n }\n\n // Track if logger is closed\n let closed = false;\n\n // Write to transports\n async function writeToTransports(entry: LogEntry): Promise<void> {\n if (closed) return;\n\n const promises: Promise<void>[] = [];\n\n for (const transport of activeTransports) {\n try {\n const result = transport.write(entry);\n if (result instanceof Promise) {\n promises.push(result);\n }\n } catch (err) {\n // Silently ignore transport errors\n }\n }\n\n if (promises.length > 0) {\n await Promise.all(promises).catch(() => {});\n }\n }\n\n // Create log entry\n function createEntry(\n levelNum: LogLevel,\n levelName: LogLevelName,\n msg: string,\n data?: Record<string, unknown>,\n error?: Error\n ): LogEntry {\n const ctx = kernel.getContext();\n\n const entry: LogEntry = {\n level: levelNum,\n levelName,\n time: Date.now(),\n msg,\n ...ctx.bindings,\n ...data,\n };\n\n // Add error if present\n if (error) {\n entry.err = {\n name: error.name,\n message: error.message,\n stack: error.stack,\n };\n }\n\n // Add correlation ID if set\n if (ctx.correlationId) {\n entry.correlationId = ctx.correlationId;\n }\n\n return entry;\n }\n\n // Check if level is enabled\n function isEnabled(levelNum: LogLevel): boolean {\n const ctx = kernel.getContext();\n return levelNum >= ctx.level;\n }\n\n // Should write sync\n function shouldSync(levelName: LogLevelName): boolean {\n const ctx = kernel.getContext();\n return ctx.syncLevels[levelName] ?? false;\n }\n\n // Generic log method\n function log(\n levelNum: LogLevel,\n levelName: LogLevelName,\n msgOrObj: string | object,\n msgOrUndefined?: string\n ): void {\n if (!isEnabled(levelNum)) return;\n\n let msg: string;\n let data: Record<string, unknown> | undefined;\n let error: Error | undefined;\n\n if (typeof msgOrObj === 'string') {\n msg = msgOrObj;\n } else if (msgOrObj instanceof Error) {\n msg = msgOrUndefined ?? msgOrObj.message;\n error = msgOrObj;\n } else {\n msg = msgOrUndefined ?? '';\n data = msgOrObj as Record<string, unknown>;\n }\n\n const entry = createEntry(levelNum, levelName, msg, data, error);\n\n // Emit events\n emitter.emit('log', entry);\n emitter.emit(`log:${levelName}` as keyof LogEvents, entry);\n\n if (shouldSync(levelName)) {\n // Sync write - fire and forget but block\n writeToTransports(entry).catch(() => {});\n } else {\n // Async write\n writeToTransports(entry).catch(() => {});\n }\n }\n\n // Create the logger object\n const logger: Logger = {\n // Log methods with overloads\n trace(msgOrObj: string | object, msg?: string): void {\n log(LOG_LEVELS.trace as unknown as LogLevel, 'trace', msgOrObj, msg);\n },\n\n debug(msgOrObj: string | object, msg?: string): void {\n log(LOG_LEVELS.debug as unknown as LogLevel, 'debug', msgOrObj, msg);\n },\n\n info(msgOrObj: string | object, msg?: string): void {\n log(LOG_LEVELS.info as unknown as LogLevel, 'info', msgOrObj, msg);\n },\n\n warn(msgOrObj: string | object, msg?: string): void {\n log(LOG_LEVELS.warn as unknown as LogLevel, 'warn', msgOrObj, msg);\n },\n\n error(msgOrObj: string | object | Error, msg?: string): void {\n log(LOG_LEVELS.error as unknown as LogLevel, 'error', msgOrObj, msg);\n },\n\n fatal(msgOrObj: string | object | Error, msg?: string): void {\n log(LOG_LEVELS.fatal as unknown as LogLevel, 'fatal', msgOrObj, msg);\n },\n\n // Level management\n getLevel(): LogLevelName {\n const ctx = kernel.getContext();\n return LEVEL_NAMES[ctx.level] ?? 'info';\n },\n\n setLevel(newLevel: LogLevelName): void {\n if (!(newLevel in LOG_LEVELS)) {\n throw new ConfigError(`Invalid log level: ${newLevel}`, 'level');\n }\n const ctx = kernel.getContext();\n ctx.level = LOG_LEVELS[newLevel] as unknown as LogLevel;\n },\n\n isLevelEnabled(levelName: LogLevelName): boolean {\n return isEnabled(LOG_LEVELS[levelName] as unknown as LogLevel);\n },\n\n // Child logger\n child(bindings: Record<string, unknown>): Logger {\n const ctx = kernel.getContext();\n return createLogger({\n ...options,\n context: { ...ctx.bindings, ...bindings },\n transports: activeTransports,\n });\n },\n\n // Correlation\n withCorrelation(id?: string): Logger {\n const ctx = kernel.getContext();\n const correlationId = id ?? generateCorrelationId();\n const childLogger = createLogger({\n ...options,\n context: { ...ctx.bindings },\n transports: activeTransports,\n });\n // Set correlation ID on child's context\n const childCtx = (childLogger as unknown as { _getContext: () => LogContext })._getContext?.();\n if (childCtx) {\n childCtx.correlationId = correlationId;\n }\n return childLogger;\n },\n\n // Timing\n time(label: string): void {\n const ctx = kernel.getContext();\n ctx.timers.set(label, performance.now());\n },\n\n timeEnd(label: string): void {\n const ctx = kernel.getContext();\n const start = ctx.timers.get(label);\n if (start === undefined) {\n logger.warn(`Timer '${label}' does not exist`);\n return;\n }\n\n const duration = performance.now() - start;\n ctx.timers.delete(label);\n\n logger.debug({ label, duration }, `${label}: ${duration.toFixed(2)}ms`);\n },\n\n async timeAsync<T>(label: string, fn: () => Promise<T>): Promise<T> {\n const start = performance.now();\n try {\n return await fn();\n } finally {\n const duration = performance.now() - start;\n logger.debug({ label, duration }, `${label}: ${duration.toFixed(2)}ms`);\n }\n },\n\n startTimer(label: string): () => void {\n const start = performance.now();\n return () => {\n const duration = performance.now() - start;\n logger.debug({ label, duration }, `${label}: ${duration.toFixed(2)}ms`);\n };\n },\n\n // Plugin management\n use(plugin: Plugin<LogContext>): Logger {\n kernel.use(plugin);\n return logger;\n },\n\n unregister(pluginName: string): boolean {\n return kernel.unregister(pluginName);\n },\n\n hasPlugin(pluginName: string): boolean {\n return kernel.has(pluginName);\n },\n\n listPlugins(): Plugin<LogContext>[] {\n return kernel.list();\n },\n\n // Event handling\n on<K extends keyof LogEvents>(event: K, handler: (payload: LogEvents[K]) => void): Unsubscribe {\n return emitter.on(event, handler as (payload: LogEvents[K]) => void);\n },\n\n // Lifecycle\n async flush(): Promise<void> {\n const promises: Promise<void>[] = [];\n\n for (const transport of activeTransports) {\n if (transport.flush) {\n try {\n const result = transport.flush();\n if (result instanceof Promise) {\n promises.push(result);\n }\n } catch {\n // Silently ignore flush errors\n }\n }\n }\n\n await Promise.all(promises);\n emitter.emit('flush', undefined as never);\n },\n\n async close(): Promise<void> {\n if (closed) return;\n closed = true;\n\n // Flush first\n await logger.flush();\n\n // Close transports\n const promises: Promise<void>[] = [];\n\n for (const transport of activeTransports) {\n if (transport.close) {\n try {\n const result = transport.close();\n if (result instanceof Promise) {\n promises.push(result);\n }\n } catch {\n // Silently ignore close errors\n }\n }\n }\n\n await Promise.all(promises);\n\n // Destroy kernel\n kernel.destroy();\n\n emitter.emit('close', undefined as never);\n },\n\n async destroy(): Promise<void> {\n return logger.close();\n },\n\n // Internal method for getting context\n _getContext(): LogContext {\n return kernel.getContext();\n },\n } as Logger & { _getContext(): LogContext };\n\n return logger;\n}\n\n/**\n * Resolve format option to concrete format.\n */\nfunction resolveFormat(format: Format): Format {\n if (format !== 'auto') {\n return format;\n }\n\n // Auto-detect based on environment\n if (isNode()) {\n // Use pretty for TTY, JSON otherwise\n return process.stdout?.isTTY ? 'pretty' : 'json';\n }\n\n // Browser - always pretty\n return 'pretty';\n}\n\n/**\n * Generate a unique correlation ID.\n */\nfunction generateCorrelationId(): string {\n // Simple UUID v4-like generation\n return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {\n const r = (Math.random() * 16) | 0;\n const v = c === 'x' ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n}\n\nexport default createLogger;\n","/**\n * @oxog/log - Type Definitions\n *\n * Core type definitions for the logging library.\n * Uses @oxog/types for Plugin and Kernel interfaces.\n *\n * @packageDocumentation\n */\n\nimport type { Plugin, MaybePromise } from '@oxog/types';\nimport type { Emitter } from '@oxog/emitter';\nimport type { Pigment } from '@oxog/pigment';\n\n// ============================================================================\n// Log Levels\n// ============================================================================\n\n/**\n * Log level numeric values for filtering.\n *\n * @example\n * ```typescript\n * import { LogLevel } from '@oxog/log';\n *\n * if (entry.level >= LogLevel.Error) {\n * alertTeam(entry);\n * }\n * ```\n */\nexport enum LogLevel {\n Trace = 10,\n Debug = 20,\n Info = 30,\n Warn = 40,\n Error = 50,\n Fatal = 60,\n}\n\n/**\n * Log level names as string literals.\n *\n * @example\n * ```typescript\n * const level: LogLevelName = 'info';\n * ```\n */\nexport type LogLevelName = 'trace' | 'debug' | 'info' | 'warn' | 'error' | 'fatal';\n\n/**\n * Output format options.\n *\n * - `'json'` - Structured JSON output (production)\n * - `'pretty'` - Human-readable colored output (development)\n * - `'auto'` - Auto-detect based on NODE_ENV and TTY\n *\n * @example\n * ```typescript\n * const log = createLogger({ format: 'pretty' });\n * ```\n */\nexport type Format = 'json' | 'pretty' | 'auto';\n\n// ============================================================================\n// Log Entry\n// ============================================================================\n\n/**\n * Structure of a log entry.\n *\n * @example\n * ```typescript\n * const entry: LogEntry = {\n * level: LogLevel.Info,\n * levelName: 'info',\n * time: Date.now(),\n * msg: 'User logged in',\n * userId: 123,\n * };\n * ```\n */\nexport interface LogEntry {\n /** Numeric log level value */\n level: LogLevel;\n\n /** Log level name */\n levelName: LogLevelName;\n\n /** Unix timestamp in milliseconds */\n time: number;\n\n /** Log message */\n msg: string;\n\n /** Additional data fields */\n [key: string]: unknown;\n\n // Optional standard fields\n /** Source file name (when source tracking enabled) */\n file?: string;\n\n /** Source line number (when source tracking enabled) */\n line?: number;\n\n /** Source column number (when source tracking enabled) */\n column?: number;\n\n /** Correlation ID for request tracing */\n correlationId?: string;\n\n /** Duration in milliseconds (for timing) */\n duration?: number;\n\n /** Error information */\n err?: {\n message: string;\n stack?: string;\n name: string;\n code?: string;\n };\n}\n\n// ============================================================================\n// Transport\n// ============================================================================\n\n/**\n * Transport interface for log output destinations.\n * Transports receive formatted log entries and write them to destinations.\n *\n * @example\n * ```typescript\n * const myTransport: Transport = {\n * name: 'my-transport',\n * write(entry) {\n * console.log(JSON.stringify(entry));\n * },\n * };\n * ```\n */\nexport interface Transport {\n /** Unique transport identifier */\n name: string;\n\n /**\n * Write a log entry to the destination.\n * Can be sync or async.\n */\n write(entry: LogEntry): MaybePromise<void>;\n\n /**\n * Flush any buffered entries.\n * Called before shutdown or on manual flush.\n */\n flush?(): MaybePromise<void>;\n\n /**\n * Close the transport and cleanup resources.\n */\n close?(): MaybePromise<void>;\n\n /**\n * Check if transport supports the current environment.\n */\n supports?(env: 'node' | 'browser'): boolean;\n}\n\n// ============================================================================\n// Logger Options\n// ============================================================================\n\n/**\n * Buffer configuration for async logging.\n *\n * @example\n * ```typescript\n * const log = createLogger({\n * buffer: { size: 100, flushInterval: 1000 }\n * });\n * ```\n */\nexport interface BufferOptions {\n /** Maximum number of entries to buffer before flush */\n size?: number;\n\n /** Flush interval in milliseconds */\n flushInterval?: number;\n}\n\n/**\n * Logger configuration options.\n *\n * @example\n * ```typescript\n * const log = createLogger({\n * level: 'debug',\n * format: 'pretty',\n * colors: true,\n * timestamp: true,\n * redact: ['password', 'token'],\n * });\n * ```\n */\nexport interface LoggerOptions {\n /**\n * Logger name, included in all entries.\n * @default 'app'\n */\n name?: string;\n\n /**\n * Minimum log level to output.\n * @default 'info'\n */\n level?: LogLevelName;\n\n /**\n * Output format.\n * @default 'auto'\n */\n format?: Format;\n\n /**\n * Enable colored output (uses @oxog/pigment).\n * @default true\n */\n colors?: boolean;\n\n /**\n * Include ISO 8601 timestamp in entries.\n * @default true\n */\n timestamp?: boolean;\n\n /**\n * Include source file and line number.\n * @default false\n */\n source?: boolean;\n\n /**\n * Fields to redact from output.\n * Supports dot notation for nested paths.\n * @example ['password', 'user.token', 'headers.authorization']\n */\n redact?: string[];\n\n /**\n * Output transports.\n * @default [consoleTransport()]\n */\n transports?: Transport[];\n\n /**\n * Additional plugins to load.\n */\n plugins?: Plugin<LogContext>[];\n\n /**\n * Sync/async mode per level.\n * Sync mode ensures log is written before continuing.\n * @default { fatal: true, error: true }\n */\n sync?: Partial<Record<LogLevelName, boolean>>;\n\n /**\n * Buffer configuration for async logging.\n */\n buffer?: BufferOptions;\n\n /**\n * Static context added to all entries.\n */\n context?: Record<string, unknown>;\n}\n\n// ============================================================================\n// Log Context\n// ============================================================================\n\n/**\n * Log context shared between plugins.\n * This is the kernel context type for @oxog/plugin.\n */\nexport interface LogContext {\n /** Logger name */\n name: string;\n\n /** Current minimum log level */\n level: LogLevel;\n\n /** Output format */\n format: Format;\n\n /** Colors enabled */\n colors: boolean;\n\n /** Timestamp enabled */\n timestamp: boolean;\n\n /** Source tracking enabled */\n source: boolean;\n\n /** Registered transports */\n transports: Transport[];\n\n /** Fields to redact */\n redactPaths: string[];\n\n /** Bound context (from child loggers) */\n bindings: Record<string, unknown>;\n\n /** Correlation ID (if set) */\n correlationId?: string;\n\n /** Pigment instance for colors */\n pigment: Pigment;\n\n /** Event emitter for log events */\n emitter: Emitter<LogEvents>;\n\n /** Sync settings per level */\n syncLevels: Record<LogLevelName, boolean>;\n\n /** Buffer settings */\n bufferOptions: BufferOptions;\n\n /** Active timers for timing plugin */\n timers: Map<string, number>;\n\n /** Buffered entries for async logging */\n buffer: LogEntry[];\n\n /** Flush interval timer ID */\n flushTimerId?: ReturnType<typeof setInterval>;\n}\n\n// ============================================================================\n// Log Events\n// ============================================================================\n\n/**\n * Log events for subscription via @oxog/emitter.\n *\n * @example\n * ```typescript\n * log.on('log:error', (entry) => {\n * alertTeam(entry);\n * });\n * ```\n */\nexport interface LogEvents {\n /** Index signature for EventMap compatibility */\n [key: string]: unknown;\n\n /** Emitted for every log entry */\n log: LogEntry;\n\n /** Emitted for trace level logs */\n 'log:trace': LogEntry;\n\n /** Emitted for debug level logs */\n 'log:debug': LogEntry;\n\n /** Emitted for info level logs */\n 'log:info': LogEntry;\n\n /** Emitted for warn level logs */\n 'log:warn': LogEntry;\n\n /** Emitted for error level logs */\n 'log:error': LogEntry;\n\n /** Emitted for fatal level logs */\n 'log:fatal': LogEntry;\n\n /** Emitted when buffer is flushed */\n flush: void;\n\n /** Emitted when logger is closed */\n close: void;\n}\n\n/**\n * Unsubscribe function returned by event subscription.\n */\nexport type Unsubscribe = () => void;\n\n// ============================================================================\n// Logger Interface\n// ============================================================================\n\n/**\n * Logger instance interface.\n * Provides logging methods, child loggers, and lifecycle management.\n *\n * @example\n * ```typescript\n * const log = createLogger();\n *\n * log.info('Server started');\n * log.info({ port: 3000 }, 'Listening');\n *\n * const dbLog = log.child({ module: 'database' });\n * dbLog.debug('Connected');\n *\n * await log.flush();\n * await log.close();\n * ```\n */\nexport interface Logger {\n // ─────────────────────────────────────────────────────────────────────────\n // Logging Methods\n // ─────────────────────────────────────────────────────────────────────────\n\n /**\n * Log at TRACE level (10).\n * Most verbose, for detailed debugging.\n */\n trace(msg: string): void;\n trace(obj: object, msg?: string): void;\n\n /**\n * Log at DEBUG level (20).\n * Debug information for developers.\n */\n debug(msg: string): void;\n debug(obj: object, msg?: string): void;\n\n /**\n * Log at INFO level (30).\n * General informational messages.\n */\n info(msg: string): void;\n info(obj: object, msg?: string): void;\n\n /**\n * Log at WARN level (40).\n * Warning conditions.\n */\n warn(msg: string): void;\n warn(obj: object, msg?: string): void;\n\n /**\n * Log at ERROR level (50).\n * Error conditions.\n */\n error(msg: string): void;\n error(obj: object, msg?: string): void;\n error(err: Error, msg?: string): void;\n\n /**\n * Log at FATAL level (60).\n * System is unusable.\n */\n fatal(msg: string): void;\n fatal(obj: object, msg?: string): void;\n fatal(err: Error, msg?: string): void;\n\n // ─────────────────────────────────────────────────────────────────────────\n // Child Loggers\n // ─────────────────────────────────────────────────────────────────────────\n\n /**\n * Create a child logger with bound context.\n * Child context is merged with parent context.\n *\n * @example\n * ```typescript\n * const dbLog = log.child({ module: 'database' });\n * dbLog.info('Connected'); // includes { module: 'database' }\n * ```\n */\n child(bindings: Record<string, unknown>): Logger;\n\n /**\n * Create a child logger with correlation ID.\n * Useful for request tracing.\n *\n * @example\n * ```typescript\n * const reqLog = log.withCorrelation('req-123');\n * reqLog.info('Request received');\n * ```\n */\n withCorrelation(id?: string): Logger;\n\n // ─────────────────────────────────────────────────────────────────────────\n // Timing\n // ─────────────────────────────────────────────────────────────────────────\n\n /**\n * Start a timer with the given label.\n *\n * @example\n * ```typescript\n * log.time('db-query');\n * await db.query('SELECT * FROM users');\n * log.timeEnd('db-query'); // logs duration\n * ```\n */\n time(label: string): void;\n\n /**\n * End a timer and log the duration.\n */\n timeEnd(label: string): void;\n\n /**\n * Time an async operation.\n *\n * @example\n * ```typescript\n * const result = await log.timeAsync('api-call', async () => {\n * return await fetch('/api/data');\n * });\n * ```\n */\n timeAsync<T>(label: string, fn: () => Promise<T>): Promise<T>;\n\n /**\n * Start a timer and return a stop function.\n *\n * @example\n * ```typescript\n * const stop = log.startTimer('process');\n * await doWork();\n * stop(); // logs duration\n * ```\n */\n startTimer(label: string): () => void;\n\n // ─────────────────────────────────────────────────────────────────────────\n // Events\n // ─────────────────────────────────────────────────────────────────────────\n\n /**\n * Subscribe to log events.\n *\n * @example\n * ```typescript\n * const unsub = log.on('log:error', (entry) => {\n * alertTeam(entry);\n * });\n *\n * // Later: unsub();\n * ```\n */\n on<K extends keyof LogEvents>(\n event: K,\n handler: (payload: LogEvents[K]) => void\n ): Unsubscribe;\n\n // ─────────────────────────────────────────────────────────────────────────\n // Plugin Management\n // ─────────────────────────────────────────────────────────────────────────\n\n /**\n * Register a plugin.\n */\n use(plugin: Plugin<LogContext>): this;\n\n /**\n * Unregister a plugin by name.\n */\n unregister(name: string): boolean;\n\n /**\n * Check if a plugin is registered.\n */\n hasPlugin(name: string): boolean;\n\n /**\n * List all registered plugins.\n */\n listPlugins(): Plugin<LogContext>[];\n\n // ─────────────────────────────────────────────────────────────────────────\n // Level Management\n // ─────────────────────────────────────────────────────────────────────────\n\n /**\n * Set the minimum log level.\n */\n setLevel(level: LogLevelName): void;\n\n /**\n * Get the current minimum log level.\n */\n getLevel(): LogLevelName;\n\n /**\n * Check if a level is enabled.\n */\n isLevelEnabled(level: LogLevelName): boolean;\n\n // ─────────────────────────────────────────────────────────────────────────\n // Lifecycle\n // ─────────────────────────────────────────────────────────────────────────\n\n /**\n * Flush all buffered entries.\n */\n flush(): Promise<void>;\n\n /**\n * Close the logger and cleanup resources.\n */\n close(): Promise<void>;\n\n /**\n * Alias for close().\n */\n destroy(): Promise<void>;\n}\n\n// ============================================================================\n// Transport Options\n// ============================================================================\n\n/**\n * Console transport options.\n */\nexport interface ConsoleTransportOptions {\n /** Enable colors */\n colors?: boolean;\n\n /** Show timestamp */\n timestamp?: boolean;\n\n /** Custom level colors */\n levelColors?: Partial<Record<LogLevelName, string>>;\n}\n\n/**\n * File transport options.\n */\nexport interface FileTransportOptions {\n /** File path */\n path: string;\n\n /** Rotation interval ('1d', '1h', etc.) */\n rotate?: string;\n\n /** Max file size ('10MB', '1GB', etc.) */\n maxSize?: string;\n\n /** Max number of files to keep */\n maxFiles?: number;\n\n /** Compress rotated files */\n compress?: boolean;\n}\n\n/**\n * HTTP transport options.\n */\nexport interface HttpTransportOptions {\n /** Endpoint URL */\n url: string;\n\n /** HTTP method */\n method?: 'POST' | 'PUT';\n\n /** Custom headers */\n headers?: Record<string, string>;\n\n /** Batch size before sending */\n batch?: number;\n\n /** Flush interval in milliseconds */\n interval?: number;\n\n /** Retry attempts on failure */\n retry?: number;\n}\n\n/**\n * Stream transport options.\n */\nexport interface StreamTransportOptions {\n /** Node.js writable stream */\n stream: NodeJS.WritableStream;\n}\n\n/**\n * LocalStorage transport options (browser only).\n */\nexport interface LocalStorageTransportOptions {\n /** Storage key prefix */\n key: string;\n\n /** Max storage size ('1MB', etc.) */\n maxSize?: string;\n\n /** Only store these levels */\n levels?: LogLevelName[];\n}\n","/**\n * @oxog/log - Constants\n *\n * Log levels, default values, and configuration constants.\n *\n * @packageDocumentation\n */\n\nimport { LogLevel, type LogLevelName, type Format, type BufferOptions } from './types.js';\n\n// ============================================================================\n// Log Levels\n// ============================================================================\n\n/**\n * Mapping of log level names to numeric values.\n *\n * @example\n * ```typescript\n * const level = LOG_LEVELS.info; // 30\n * ```\n */\nexport const LOG_LEVELS: Record<LogLevelName, LogLevel> = {\n trace: LogLevel.Trace,\n debug: LogLevel.Debug,\n info: LogLevel.Info,\n warn: LogLevel.Warn,\n error: LogLevel.Error,\n fatal: LogLevel.Fatal,\n} as const;\n\n/**\n * Mapping of numeric values to log level names.\n *\n * @example\n * ```typescript\n * const name = LEVEL_NAMES[30]; // 'info'\n * ```\n */\nexport const LEVEL_NAMES: Record<LogLevel, LogLevelName> = {\n [LogLevel.Trace]: 'trace',\n [LogLevel.Debug]: 'debug',\n [LogLevel.Info]: 'info',\n [LogLevel.Warn]: 'warn',\n [LogLevel.Error]: 'error',\n [LogLevel.Fatal]: 'fatal',\n} as const;\n\n/**\n * Array of all log level names in order of severity.\n */\nexport const LEVEL_ORDER: LogLevelName[] = [\n 'trace',\n 'debug',\n 'info',\n 'warn',\n 'error',\n 'fatal',\n] as const;\n\n// ============================================================================\n// Default Configuration\n// ============================================================================\n\n/**\n * Default logger name.\n */\nexport const DEFAULT_NAME = 'app';\n\n/**\n * Default log level.\n */\nexport const DEFAULT_LEVEL: LogLevelName = 'info';\n\n/**\n * Default output format.\n */\nexport const DEFAULT_FORMAT: Format = 'auto';\n\n/**\n * Default colors setting.\n */\nexport const DEFAULT_COLORS = true;\n\n/**\n * Default timestamp setting.\n */\nexport const DEFAULT_TIMESTAMP = true;\n\n/**\n * Default source tracking setting.\n */\nexport const DEFAULT_SOURCE = false;\n\n/**\n * Default sync levels (fatal and error are sync by default).\n */\nexport const DEFAULT_SYNC_LEVELS: Record<LogLevelName, boolean> = {\n trace: false,\n debug: false,\n info: false,\n warn: false,\n error: true,\n fatal: true,\n} as const;\n\n/**\n * Default buffer options.\n */\nexport const DEFAULT_BUFFER_OPTIONS: Required<BufferOptions> = {\n size: 100,\n flushInterval: 1000,\n} as const;\n\n// ============================================================================\n// Level Colors\n// ============================================================================\n\n/**\n * Default colors for each log level (used with @oxog/pigment).\n */\nexport const LEVEL_COLORS: Record<LogLevelName, string> = {\n trace: 'gray',\n debug: 'cyan',\n info: 'blue',\n warn: 'yellow',\n error: 'red',\n fatal: 'magenta',\n} as const;\n\n/**\n * Level label display strings (padded for alignment).\n */\nexport const LEVEL_LABELS: Record<LogLevelName, string> = {\n trace: 'TRACE',\n debug: 'DEBUG',\n info: 'INFO ',\n warn: 'WARN ',\n error: 'ERROR',\n fatal: 'FATAL',\n} as const;\n\n// ============================================================================\n// Redaction\n// ============================================================================\n\n/**\n * Default redaction placeholder.\n */\nexport const REDACTED_VALUE = '[REDACTED]';\n\n/**\n * Common sensitive field names.\n */\nexport const COMMON_SENSITIVE_FIELDS = [\n 'password',\n 'token',\n 'secret',\n 'apiKey',\n 'api_key',\n 'apikey',\n 'authorization',\n 'auth',\n 'credential',\n 'credentials',\n 'ssn',\n 'creditCard',\n 'credit_card',\n 'creditcard',\n 'cvv',\n 'pin',\n] as const;\n\n// ============================================================================\n// Size Constants\n// ============================================================================\n\n/**\n * Parse size string to bytes.\n *\n * @example\n * ```typescript\n * parseSize('10MB'); // 10485760\n * parseSize('1GB'); // 1073741824\n * ```\n */\nexport function parseSize(size: string): number {\n const match = size.match(/^(\\d+(?:\\.\\d+)?)\\s*(B|KB|MB|GB|TB)?$/i);\n if (!match) {\n throw new Error(`Invalid size format: ${size}`);\n }\n\n const value = parseFloat(match[1]!);\n const unit = (match[2] || 'B').toUpperCase();\n\n const units: Record<string, number> = {\n B: 1,\n KB: 1024,\n MB: 1024 * 1024,\n GB: 1024 * 1024 * 1024,\n TB: 1024 * 1024 * 1024 * 1024,\n };\n\n return Math.floor(value * (units[unit] ?? 1));\n}\n\n/**\n * Parse rotation interval string to milliseconds.\n *\n * @example\n * ```typescript\n * parseRotation('1d'); // 86400000\n * parseRotation('1h'); // 3600000\n * ```\n */\nexport function parseRotation(rotation: string): number {\n const match = rotation.match(/^(\\d+)\\s*(s|m|h|d|w)?$/i);\n if (!match) {\n throw new Error(`Invalid rotation format: ${rotation}`);\n }\n\n const value = parseInt(match[1]!, 10);\n const unit = (match[2] || 's').toLowerCase();\n\n const units: Record<string, number> = {\n s: 1000,\n m: 60 * 1000,\n h: 60 * 60 * 1000,\n d: 24 * 60 * 60 * 1000,\n w: 7 * 24 * 60 * 60 * 1000,\n };\n\n return value * (units[unit] ?? 1000);\n}\n\n// ============================================================================\n// Environment\n// ============================================================================\n\n/**\n * Check if running in Node.js.\n */\nexport const IS_NODE =\n typeof process !== 'undefined' &&\n process.versions != null &&\n process.versions.node != null;\n\n/**\n * Check if running in browser.\n */\nexport const IS_BROWSER =\n typeof window !== 'undefined' && typeof window.document !== 'undefined';\n\n/**\n * Check if running in development mode.\n */\nexport const IS_DEV =\n IS_NODE && process.env['NODE_ENV'] !== 'production';\n\n/**\n * Check if stdout is a TTY (terminal).\n */\nexport const IS_TTY = IS_NODE && process.stdout?.isTTY === true;\n","/**\n * @oxog/log - Environment Detection Utilities\n *\n * Detect runtime environment and capabilities.\n *\n * @packageDocumentation\n */\n\n/**\n * Check if running in Node.js environment.\n *\n * @example\n * ```typescript\n * if (isNode()) {\n * // Use Node.js APIs\n * }\n * ```\n */\nexport function isNode(): boolean {\n return (\n typeof process !== 'undefined' &&\n process.versions != null &&\n process.versions.node != null\n );\n}\n\n/**\n * Check if running in browser environment.\n *\n * @example\n * ```typescript\n * if (isBrowser()) {\n * // Use browser APIs\n * }\n * ```\n */\nexport function isBrowser(): boolean {\n return typeof window !== 'undefined' && typeof window.document !== 'undefined';\n}\n\n/**\n * Check if running in development mode.\n * Returns true if NODE_ENV is not 'production'.\n *\n * @example\n * ```typescript\n * if (isDev()) {\n * log.setLevel('debug');\n * }\n * ```\n */\nexport function isDev(): boolean {\n if (!isNode()) return false;\n return process.env['NODE_ENV'] !== 'production';\n}\n\n/**\n * Check if stdout is a TTY (terminal).\n *\n * @example\n * ```typescript\n * if (isTTY()) {\n * // Use colors\n * }\n * ```\n */\nexport function isTTY(): boolean {\n if (!isNode()) return false;\n return process.stdout?.isTTY === true;\n}\n\n/**\n * Check if colors should be enabled by default.\n * Returns true if running in TTY or browser.\n *\n * @example\n * ```typescript\n * const colors = shouldUseColors();\n * ```\n */\nexport function shouldUseColors(): boolean {\n if (isBrowser()) return true;\n if (!isNode()) return false;\n\n // Check for NO_COLOR environment variable\n if (process.env['NO_COLOR'] !== undefined) return false;\n\n // Check for FORCE_COLOR environment variable\n if (process.env['FORCE_COLOR'] !== undefined) return true;\n\n // Check if running in CI\n if (process.env['CI'] !== undefined) return true;\n\n // Default to TTY detection\n return isTTY();\n}\n\n/**\n * Get the current environment name.\n *\n * @example\n * ```typescript\n * const env = getEnvironment(); // 'development' | 'production' | 'test'\n * ```\n */\nexport function getEnvironment(): string {\n if (!isNode()) return 'browser';\n return process.env['NODE_ENV'] || 'development';\n}\n\n/**\n * Get the current working directory.\n * Returns undefined in browser.\n *\n * @example\n * ```typescript\n * const cwd = getCwd(); // '/path/to/project'\n * ```\n */\nexport function getCwd(): string | undefined {\n if (!isNode()) return undefined;\n return process.cwd();\n}\n\n/**\n * Get a safe reference to globalThis.\n */\nexport function getGlobalThis(): typeof globalThis {\n if (typeof globalThis !== 'undefined') return globalThis;\n if (typeof window !== 'undefined') return window as unknown as typeof globalThis;\n if (typeof global !== 'undefined') return global as unknown as typeof globalThis;\n if (typeof self !== 'undefined') return self as unknown as typeof globalThis;\n return {} as typeof globalThis;\n}\n","/**\n * @oxog/log - Formatting Utilities\n *\n * JSON and pretty formatting for log entries.\n *\n * @packageDocumentation\n */\n\nimport type { LogEntry, LogLevelName } from '../types.js';\nimport { LEVEL_LABELS, LEVEL_COLORS } from '../constants.js';\nimport type { Pigment } from '@oxog/pigment';\n\n/**\n * Format a log entry as JSON string.\n *\n * @example\n * ```typescript\n * const json = formatJson(entry);\n * // {\"level\":30,\"time\":1234567890,\"msg\":\"Hello\"}\n * ```\n */\nexport function formatJson(entry: LogEntry): string {\n return JSON.stringify(entry, jsonReplacer);\n}\n\n/**\n * JSON replacer function to handle special values.\n */\nfunction jsonReplacer(_key: string, value: unknown): unknown {\n // Handle BigInt\n if (typeof value === 'bigint') {\n return value.toString();\n }\n\n // Handle Error objects\n if (value instanceof Error) {\n const errorObj = value as Error & Record<string, unknown>;\n const result: Record<string, unknown> = {\n name: value.name,\n message: value.message,\n stack: value.stack,\n };\n // Copy any additional enumerable properties\n for (const key of Object.keys(errorObj)) {\n if (!(key in result)) {\n result[key] = errorObj[key];\n }\n }\n return result;\n }\n\n // Handle circular references and special objects\n if (typeof value === 'object' && value !== null) {\n // Handle RegExp\n if (value instanceof RegExp) {\n return value.toString();\n }\n\n // Handle Date (already handled by JSON.stringify, but explicit for clarity)\n if (value instanceof Date) {\n return value.toISOString();\n }\n\n // Handle Map\n if (value instanceof Map) {\n return Object.fromEntries(value);\n }\n\n // Handle Set\n if (value instanceof Set) {\n return Array.from(value);\n }\n }\n\n return value;\n}\n\n/**\n * Safe JSON stringify with circular reference handling.\n *\n * @example\n * ```typescript\n * const obj = { a: 1 };\n * obj.self = obj; // circular\n * safeStringify(obj); // {\"a\":1,\"self\":\"[Circular]\"}\n * ```\n */\nexport function safeStringify(value: unknown, indent?: number): string {\n const seen = new WeakSet<object>();\n\n return JSON.stringify(\n value,\n (_key, val) => {\n // First apply the standard replacer\n const replaced = jsonReplacer(_key, val);\n\n // Then check for circular references\n if (typeof replaced === 'object' && replaced !== null) {\n if (seen.has(replaced)) {\n return '[Circular]';\n }\n seen.add(replaced);\n }\n\n return replaced;\n },\n indent\n );\n}\n\n/**\n * Format a log entry as pretty string with colors.\n *\n * @example\n * ```typescript\n * const pretty = formatPretty(entry, pigment);\n * // [14:30:22] INFO Hello world\n * ```\n */\nexport function formatPretty(\n entry: LogEntry,\n pigment?: Pigment,\n options: { timestamp?: boolean; source?: boolean } = {}\n): string {\n const parts: string[] = [];\n const { timestamp = true, source = true } = options;\n\n // Timestamp\n if (timestamp && entry.time) {\n const time = formatTime(entry.time);\n parts.push(pigment ? pigment.gray(`[${time}]`) : `[${time}]`);\n }\n\n // Level\n const levelLabel = LEVEL_LABELS[entry.levelName] || entry.levelName.toUpperCase();\n const levelColor = LEVEL_COLORS[entry.levelName] || 'white';\n\n if (pigment) {\n const colorFn = (pigment as unknown as Record<string, (s: string) => string>)[levelColor];\n parts.push(colorFn ? colorFn(levelLabel) : levelLabel);\n } else {\n parts.push(levelLabel);\n }\n\n // Source location\n if (source && entry.file) {\n const location = entry.line ? `${entry.file}:${entry.line}` : entry.file;\n parts.push(pigment ? pigment.dim(`(${location})`) : `(${location})`);\n }\n\n // Message\n if (entry.msg) {\n parts.push(entry.msg);\n }\n\n // Extra data (excluding standard fields)\n const extra = getExtraFields(entry);\n if (Object.keys(extra).length > 0) {\n const extraStr = safeStringify(extra);\n parts.push(pigment ? pigment.dim(extraStr) : extraStr);\n }\n\n // Error stack\n if (entry.err?.stack) {\n parts.push('\\n' + (pigment ? pigment.red(entry.err.stack) : entry.err.stack));\n }\n\n return parts.join(' ');\n}\n\n/**\n * Get extra fields from entry (excluding standard fields).\n */\nfunction getExtraFields(entry: LogEntry): Record<string, unknown> {\n const standardFields = new Set([\n 'level',\n 'levelName',\n 'time',\n 'msg',\n 'file',\n 'line',\n 'column',\n 'correlationId',\n 'duration',\n 'err',\n 'name',\n ]);\n\n const extra: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(entry)) {\n if (!standardFields.has(key)) {\n extra[key] = value;\n }\n }\n return extra;\n}\n\n/**\n * Format timestamp as HH:MM:SS.\n */\nexport function formatTime(timestamp: number): string {\n const date = new Date(timestamp);\n const hours = date.getHours().toString().padStart(2, '0');\n const minutes = date.getMinutes().toString().padStart(2, '0');\n const seconds = date.getSeconds().toString().padStart(2, '0');\n return `${hours}:${minutes}:${seconds}`;\n}\n\n/**\n * Format timestamp as ISO 8601 string.\n */\nexport function formatIso(timestamp: number): string {\n return new Date(timestamp).toISOString();\n}\n\n/**\n * Format duration in human-readable format.\n *\n * @example\n * ```typescript\n * formatDuration(45); // '45ms'\n * formatDuration(1500); // '1.50s'\n * formatDuration(90000); // '1m 30s'\n * ```\n */\nexport function formatDuration(ms: number): string {\n if (ms < 1000) {\n return `${ms}ms`;\n }\n\n if (ms < 60000) {\n return `${(ms / 1000).toFixed(2)}s`;\n }\n\n const minutes = Math.floor(ms / 60000);\n const seconds = Math.round((ms % 60000) / 1000);\n return `${minutes}m ${seconds}s`;\n}\n\n/**\n * Format bytes in human-readable format.\n *\n * @example\n * ```typescript\n * formatBytes(1024); // '1 KB'\n * formatBytes(1048576); // '1 MB'\n * ```\n */\nexport function formatBytes(bytes: number): string {\n const units = ['B', 'KB', 'MB', 'GB', 'TB'];\n let unitIndex = 0;\n let value = bytes;\n\n while (value >= 1024 && unitIndex < units.length - 1) {\n value /= 1024;\n unitIndex++;\n }\n\n return `${value.toFixed(unitIndex > 0 ? 2 : 0)} ${units[unitIndex]}`;\n}\n\n/**\n * Truncate a string to a maximum length.\n *\n * @example\n * ```typescript\n * truncate('Hello world', 8); // 'Hello...'\n * ```\n */\nexport function truncate(str: string, maxLength: number, suffix = '...'): string {\n if (str.length <= maxLength) return str;\n return str.slice(0, maxLength - suffix.length) + suffix;\n}\n\n/**\n * Indent a multi-line string.\n */\nexport function indent(str: string, spaces = 2): string {\n const pad = ' '.repeat(spaces);\n return str\n .split('\\n')\n .map((line) => pad + line)\n .join('\\n');\n}\n","/**\n * @oxog/log - Console Transport\n *\n * Output logs to console with optional colors.\n *\n * @packageDocumentation\n */\n\nimport type { Transport, LogEntry, ConsoleTransportOptions, LogLevelName } from '../types.js';\nimport { formatJson, formatPretty } from '../utils/format.js';\nimport { isBrowser, isTTY, shouldUseColors } from '../utils/env.js';\nimport type { Pigment } from '@oxog/pigment';\n\n/**\n * Default level colors for console output.\n */\nconst DEFAULT_LEVEL_COLORS: Record<LogLevelName, string> = {\n trace: 'gray',\n debug: 'cyan',\n info: 'blue',\n warn: 'yellow',\n error: 'red',\n fatal: 'magenta',\n};\n\n/**\n * Create a console transport.\n *\n * @example\n * ```typescript\n * import { consoleTransport } from '@oxog/log/transports';\n *\n * const transport = consoleTransport({ colors: true });\n * ```\n */\nexport function consoleTransport(options: ConsoleTransportOptions = {}): Transport {\n const {\n colors = shouldUseColors(),\n timestamp = true,\n levelColors = {},\n } = options;\n\n // Merge level colors\n const mergedColors = { ...DEFAULT_LEVEL_COLORS, ...levelColors };\n\n // Store pigment instance (set by logger)\n let pigment: Pigment | undefined;\n\n return {\n name: 'console',\n\n write(entry: LogEntry): void {\n // Format the entry\n let output: string;\n\n if (isBrowser()) {\n // In browser, use console methods directly\n writeToBrowserConsole(entry, colors);\n return;\n }\n\n // In Node.js, format and write to stdout/stderr\n if (colors && pigment) {\n output = formatPretty(entry, pigment, { timestamp, source: true });\n } else if (colors) {\n // Simple colored output without pigment\n output = formatWithAnsi(entry, mergedColors, timestamp);\n } else {\n output = formatJson(entry);\n }\n\n // Write to appropriate stream\n if (entry.level >= 50) {\n // Error and Fatal to stderr\n process.stderr.write(output + '\\n');\n } else {\n process.stdout.write(output + '\\n');\n }\n },\n\n flush(): void {\n // Console doesn't need flushing\n },\n\n close(): void {\n // Console doesn't need closing\n },\n\n supports(env: 'node' | 'browser'): boolean {\n return true; // Works in both environments\n },\n };\n}\n\n/**\n * Format entry with ANSI colors (without pigment).\n */\nfunction formatWithAnsi(\n entry: LogEntry,\n levelColors: Record<LogLevelName, string>,\n showTimestamp: boolean\n): string {\n const parts: string[] = [];\n\n // Timestamp\n if (showTimestamp && entry.time) {\n const time = formatTime(entry.time);\n parts.push(`\\x1b[90m[${time}]\\x1b[0m`);\n }\n\n // Level with color\n const color = getAnsiColor(levelColors[entry.levelName] || 'white');\n const levelLabel = entry.levelName.toUpperCase().padEnd(5);\n parts.push(`${color}${levelLabel}\\x1b[0m`);\n\n // Source location\n if (entry.file) {\n const location = entry.line ? `${entry.file}:${entry.line}` : entry.file;\n parts.push(`\\x1b[90m(${location})\\x1b[0m`);\n }\n\n // Message\n if (entry.msg) {\n parts.push(entry.msg);\n }\n\n // Extra data\n const extra = getExtraFields(entry);\n if (Object.keys(extra).length > 0) {\n parts.push(`\\x1b[90m${JSON.stringify(extra)}\\x1b[0m`);\n }\n\n // Error stack\n if (entry.err?.stack) {\n parts.push('\\n\\x1b[31m' + entry.err.stack + '\\x1b[0m');\n }\n\n return parts.join(' ');\n}\n\n/**\n * Get ANSI color code for a color name.\n */\nfunction getAnsiColor(colorName: string): string {\n const colors: Record<string, string> = {\n black: '\\x1b[30m',\n red: '\\x1b[31m',\n green: '\\x1b[32m',\n yellow: '\\x1b[33m',\n blue: '\\x1b[34m',\n magenta: '\\x1b[35m',\n cyan: '\\x1b[36m',\n white: '\\x1b[37m',\n gray: '\\x1b[90m',\n grey: '\\x1b[90m',\n };\n return colors[colorName] || '\\x1b[0m';\n}\n\n/**\n * Format timestamp as HH:MM:SS.\n */\nfunction formatTime(timestamp: number): string {\n const date = new Date(timestamp);\n return date.toTimeString().slice(0, 8);\n}\n\n/**\n * Get extra fields from entry (excluding standard fields).\n */\nfunction getExtraFields(entry: LogEntry): Record<string, unknown> {\n const standardFields = new Set([\n 'level',\n 'levelName',\n 'time',\n 'msg',\n 'file',\n 'line',\n 'column',\n 'correlationId',\n 'duration',\n 'err',\n 'name',\n ]);\n\n const extra: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(entry)) {\n if (!standardFields.has(key)) {\n extra[key] = value;\n }\n }\n return extra;\n}\n\n/**\n * Write to browser console with styling.\n */\nfunction writeToBrowserConsole(entry: LogEntry, styled: boolean): void {\n const method = getConsoleMethod(entry.levelName);\n const consoleObj = console as unknown as Record<string, (...args: unknown[]) => void>;\n\n if (styled) {\n const styles = getBrowserStyles(entry.levelName);\n const label = `%c[${entry.levelName.toUpperCase()}]`;\n\n const extra = getExtraFields(entry);\n if (Object.keys(extra).length > 0) {\n consoleObj[method](label, styles, entry.msg, extra);\n } else {\n consoleObj[method](label, styles, entry.msg);\n }\n } else {\n consoleObj[method](`[${entry.levelName.toUpperCase()}]`, entry.msg, entry);\n }\n}\n\n/**\n * Get console method for level.\n */\nfunction getConsoleMethod(levelName: LogLevelName): string {\n switch (levelName) {\n case 'trace':\n case 'debug':\n return 'debug';\n case 'info':\n return 'info';\n case 'warn':\n return 'warn';\n case 'error':\n case 'fatal':\n return 'error';\n default:\n return 'log';\n }\n}\n\n/**\n * Get browser CSS styles for level.\n */\nfunction getBrowserStyles(levelName: LogLevelName): string {\n const colors: Record<LogLevelName, string> = {\n trace: '#888888',\n debug: '#00bcd4',\n info: '#2196f3',\n warn: '#ff9800',\n error: '#f44336',\n fatal: '#9c27b0',\n };\n return `color: ${colors[levelName]}; font-weight: bold;`;\n}\n\nexport default consoleTransport;\n","/**\n * @oxog/log - Level Plugin\n *\n * Manages log level filtering and configuration.\n *\n * @packageDocumentation\n */\n\nimport type { Plugin } from '@oxog/types';\nimport type { LogContext, LogLevelName } from '../../types.js';\nimport { LOG_LEVELS, LEVEL_NAMES } from '../../constants.js';\n\n/**\n * Level plugin for log level management.\n *\n * This plugin:\n * - Filters log entries by level\n * - Provides level checking utilities\n * - Allows runtime level changes\n *\n * @example\n * ```typescript\n * import { levelPlugin } from '@oxog/log/plugins';\n *\n * logger.use(levelPlugin());\n *\n * // Only logs at or above 'warn' level will be processed\n * logger.setLevel('warn');\n * ```\n */\nexport function levelPlugin(): Plugin<LogContext> {\n return {\n name: 'level',\n version: '1.0.0',\n\n install(kernel) {\n const ctx = kernel.getContext();\n\n // Ensure level is set\n if (ctx.level === undefined) {\n ctx.level = LOG_LEVELS.info;\n }\n },\n };\n}\n\n/**\n * Check if a log level is enabled.\n *\n * @example\n * ```typescript\n * if (isLevelEnabled(context, 'debug')) {\n * // Process debug log\n * }\n * ```\n */\nexport function isLevelEnabled(ctx: LogContext, levelName: LogLevelName): boolean {\n const levelValue = LOG_LEVELS[levelName];\n return levelValue >= ctx.level;\n}\n\n/**\n * Get the current level name from context.\n */\nexport function getLevelName(ctx: LogContext): LogLevelName {\n return LEVEL_NAMES[ctx.level] ?? 'info';\n}\n\n/**\n * Set the log level on context.\n */\nexport function setLevel(ctx: LogContext, levelName: LogLevelName): void {\n const levelValue = LOG_LEVELS[levelName];\n if (levelValue !== undefined) {\n ctx.level = levelValue;\n }\n}\n\n/**\n * Parse a level name or number to LogLevel.\n */\nexport function parseLevel(level: LogLevelName | number): number {\n if (typeof level === 'number') {\n return level;\n }\n return LOG_LEVELS[level] ?? LOG_LEVELS.info;\n}\n\nexport default levelPlugin;\n","/**\n * @oxog/log - Format Plugin\n *\n * Handles output format selection and formatting.\n *\n * @packageDocumentation\n */\n\nimport type { Plugin } from '@oxog/types';\nimport type { LogContext, LogEntry, Format } from '../../types.js';\nimport { formatJson, formatPretty } from '../../utils/format.js';\nimport { isDev, isTTY } from '../../utils/env.js';\n\n/**\n * Format plugin for output formatting.\n *\n * This plugin:\n * - Selects format based on configuration\n * - Provides JSON and Pretty formatters\n * - Auto-detects format based on environment\n *\n * @example\n * ```typescript\n * import { formatPlugin } from '@oxog/log/plugins';\n *\n * logger.use(formatPlugin());\n *\n * // Format is auto-detected or can be set explicitly\n * ```\n */\nexport function formatPlugin(): Plugin<LogContext> {\n return {\n name: 'format',\n version: '1.0.0',\n\n install(kernel) {\n const ctx = kernel.getContext();\n\n // Set default format if not set\n if (ctx.format === undefined) {\n ctx.format = detectFormat();\n }\n // Auto-detect format if set to 'auto'\n else if (ctx.format === 'auto') {\n ctx.format = detectFormat();\n }\n },\n };\n}\n\n/**\n * Auto-detect the best format based on environment.\n *\n * - Development + TTY = 'pretty'\n * - Production or non-TTY = 'json'\n */\nexport function detectFormat(): 'json' | 'pretty' {\n if (isDev() && isTTY()) {\n return 'pretty';\n }\n return 'json';\n}\n\n/**\n * Format a log entry based on context settings.\n */\nexport function formatEntry(ctx: LogContext, entry: LogEntry): string {\n const format = ctx.format === 'auto' ? detectFormat() : ctx.format;\n\n if (format === 'pretty') {\n return formatPretty(entry, ctx.pigment, {\n timestamp: ctx.timestamp,\n source: ctx.source,\n });\n }\n\n return formatJson(entry);\n}\n\n/**\n * Get the effective format (resolving 'auto').\n */\nexport function getEffectiveFormat(ctx: LogContext): 'json' | 'pretty' {\n if (ctx.format === 'auto') {\n return detectFormat();\n }\n return ctx.format as 'json' | 'pretty';\n}\n\nexport default formatPlugin;\n","/**\n * @oxog/log - Timestamp Plugin\n *\n * Adds timestamp to log entries.\n *\n * @packageDocumentation\n */\n\nimport type { Plugin } from '@oxog/types';\nimport type { LogContext, LogEntry } from '../../types.js';\n\n/**\n * Timestamp plugin for adding timestamps to log entries.\n *\n * This plugin:\n * - Adds Unix timestamp (ms) to entries\n * - Optionally adds ISO 8601 timestamp\n *\n * @example\n * ```typescript\n * import { timestampPlugin } from '@oxog/log/plugins';\n *\n * logger.use(timestampPlugin());\n *\n * // Entries will have: { time: 1234567890123, ... }\n * ```\n */\nexport function timestampPlugin(): Plugin<LogContext> {\n return {\n name: 'timestamp',\n version: '1.0.0',\n\n install(kernel) {\n const ctx = kernel.getContext();\n // Set default timestamp setting if not set\n if (ctx.timestamp === undefined) {\n ctx.timestamp = true;\n }\n },\n };\n}\n\n/**\n * Get current Unix timestamp in milliseconds.\n */\nexport function now(): number {\n return Date.now();\n}\n\n/**\n * Get current ISO 8601 timestamp string.\n */\nexport function nowIso(): string {\n return new Date().toISOString();\n}\n\n/**\n * Format a Unix timestamp as ISO 8601 string.\n */\nexport function toIso(timestamp: number): string {\n return new Date(timestamp).toISOString();\n}\n\n/**\n * Parse an ISO 8601 string to Unix timestamp.\n */\nexport function fromIso(isoString: string): number {\n return new Date(isoString).getTime();\n}\n\n/**\n * Add timestamp to a log entry.\n */\nexport function addTimestamp(entry: LogEntry): LogEntry {\n if (entry.time === undefined) {\n entry.time = Date.now();\n }\n return entry;\n}\n\n/**\n * Format timestamp for display.\n */\nexport function formatTimestamp(timestamp: number): string {\n return new Date(timestamp).toISOString();\n}\n\nexport default timestampPlugin;\n","/**\n * @oxog/log - Error Classes\n *\n * Custom error classes for the logging library.\n *\n * @packageDocumentation\n */\n\n/**\n * Base error class for @oxog/log.\n *\n * @example\n * ```typescript\n * try {\n * log.info({ nested: circular });\n * } catch (err) {\n * if (err instanceof LogError) {\n * console.error('Log error:', err.code);\n * }\n * }\n * ```\n */\nexport class LogError extends Error {\n /** Error code for programmatic handling */\n readonly code: string;\n\n /** Original error if wrapping another error */\n override readonly cause?: Error;\n\n constructor(message: string, code: string, cause?: Error) {\n super(message);\n this.name = 'LogError';\n this.code = code;\n this.cause = cause;\n\n // Maintain proper stack trace in V8\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, this.constructor);\n }\n }\n}\n\n/**\n * Error thrown when a plugin fails to install or operate.\n *\n * @example\n * ```typescript\n * throw new PluginError('Failed to initialize plugin', 'my-plugin');\n * ```\n */\nexport class PluginError extends LogError {\n /** Name of the plugin that caused the error */\n readonly pluginName: string;\n\n constructor(message: string, pluginName: string, cause?: Error) {\n super(`[Plugin: ${pluginName}] ${message}`, 'PLUGIN_ERROR', cause);\n this.name = 'PluginError';\n this.pluginName = pluginName;\n }\n}\n\n/**\n * Error thrown when a transport fails to write or operate.\n *\n * @example\n * ```typescript\n * throw new TransportError('Failed to write to file', 'file-transport');\n * ```\n */\nexport class TransportError extends LogError {\n /** Name of the transport that caused the error */\n readonly transportName: string;\n\n constructor(message: string, transportName: string, cause?: Error) {\n super(`[Transport: ${transportName}] ${message}`, 'TRANSPORT_ERROR', cause);\n this.name = 'TransportError';\n this.transportName = transportName;\n }\n}\n\n/**\n * Error thrown when configuration is invalid.\n *\n * @example\n * ```typescript\n * throw new ConfigError('Invalid log level: verbose');\n * ```\n */\nexport class ConfigError extends LogError {\n /** Configuration option that caused the error */\n readonly option?: string;\n\n constructor(message: string, option?: string, cause?: Error) {\n super(message, 'CONFIG_ERROR', cause);\n this.name = 'ConfigError';\n this.option = option;\n }\n}\n\n/**\n * Error thrown when serialization fails (e.g., circular references).\n *\n * @example\n * ```typescript\n * throw new SerializationError('Circular reference detected');\n * ```\n */\nexport class SerializationError extends LogError {\n constructor(message: string, cause?: Error) {\n super(message, 'SERIALIZATION_ERROR', cause);\n this.name = 'SerializationError';\n }\n}\n\n/**\n * Error thrown when a required feature is not available in the current environment.\n *\n * @example\n * ```typescript\n * throw new EnvironmentError('File transport is not available in browser');\n * ```\n */\nexport class EnvironmentError extends LogError {\n /** Required environment */\n readonly requiredEnv: 'node' | 'browser';\n\n constructor(message: string, requiredEnv: 'node' | 'browser', cause?: Error) {\n super(message, 'ENVIRONMENT_ERROR', cause);\n this.name = 'EnvironmentError';\n this.requiredEnv = requiredEnv;\n }\n}\n\n/**\n * Error thrown when buffer operations fail.\n *\n * @example\n * ```typescript\n * throw new BufferError('Buffer overflow: max size exceeded');\n * ```\n */\nexport class BufferError extends LogError {\n constructor(message: string, cause?: Error) {\n super(message, 'BUFFER_ERROR', cause);\n this.name = 'BufferError';\n }\n}\n\n/**\n * Create an error from an unknown caught value.\n * Ensures we always have a proper Error object.\n *\n * @example\n * ```typescript\n * try {\n * riskyOperation();\n * } catch (err) {\n * throw ensureError(err);\n * }\n * ```\n */\nexport function ensureError(value: unknown): Error {\n if (value instanceof Error) {\n return value;\n }\n\n if (typeof value === 'string') {\n return new Error(value);\n }\n\n if (typeof value === 'object' && value !== null) {\n const obj = value as Record<string, unknown>;\n if (typeof obj['message'] === 'string') {\n const err = new Error(obj['message']);\n if (typeof obj['name'] === 'string') {\n err.name = obj['name'];\n }\n return err;\n }\n }\n\n return new Error(String(value));\n}\n\n/**\n * Wrap an error with additional context.\n *\n * @example\n * ```typescript\n * try {\n * writeToFile(data);\n * } catch (err) {\n * throw wrapError(err, 'Failed to write log file');\n * }\n * ```\n */\nexport function wrapError(error: unknown, message: string): LogError {\n const cause = ensureError(error);\n return new LogError(`${message}: ${cause.message}`, 'WRAPPED_ERROR', cause);\n}\n","/**\n * @oxog/log - File Transport\n *\n * Output logs to files with optional rotation.\n * Node.js only.\n *\n * @packageDocumentation\n */\n\nimport type { Transport, LogEntry, FileTransportOptions } from '../types.js';\nimport { formatJson } from '../utils/format.js';\nimport { isNode } from '../utils/env.js';\nimport { parseSize, parseRotation } from '../constants.js';\nimport { TransportError, EnvironmentError } from '../errors.js';\n\n/**\n * Create a file transport.\n *\n * @example\n * ```typescript\n * import { fileTransport } from '@oxog/log/transports';\n *\n * const transport = fileTransport({\n * path: './logs/app.log',\n * rotate: '1d',\n * maxSize: '10MB',\n * maxFiles: 7,\n * });\n * ```\n */\nexport function fileTransport(options: FileTransportOptions): Transport {\n if (!isNode()) {\n throw new EnvironmentError('File transport is only available in Node.js', 'node');\n }\n\n const {\n path: filePath,\n rotate,\n maxSize,\n maxFiles = 5,\n compress = false,\n } = options;\n\n // Parse size and rotation settings\n const maxSizeBytes = maxSize ? parseSize(maxSize) : undefined;\n const rotationMs = rotate ? parseRotation(rotate) : undefined;\n\n // Track current file state\n let currentSize = 0;\n let lastRotation = Date.now();\n let writeStream: NodeJS.WritableStream | null = null;\n let fs: typeof import('fs') | null = null;\n let path: typeof import('path') | null = null;\n let zlib: typeof import('zlib') | null = null;\n\n // Lazy load Node.js modules\n async function ensureModules(): Promise<void> {\n if (!fs) {\n fs = await import('fs');\n path = await import('path');\n if (compress) {\n zlib = await import('zlib');\n }\n }\n }\n\n // Open write stream\n async function ensureStream(): Promise<NodeJS.WritableStream> {\n await ensureModules();\n\n if (!writeStream) {\n // Ensure directory exists\n const dir = path!.dirname(filePath);\n if (!fs!.existsSync(dir)) {\n fs!.mkdirSync(dir, { recursive: true });\n }\n\n // Get current file size if exists\n if (fs!.existsSync(filePath)) {\n const stats = fs!.statSync(filePath);\n currentSize = stats.size;\n }\n\n writeStream = fs!.createWriteStream(filePath, { flags: 'a' });\n }\n\n return writeStream;\n }\n\n // Check if rotation is needed\n function shouldRotate(): boolean {\n // Size-based rotation\n if (maxSizeBytes && currentSize >= maxSizeBytes) {\n return true;\n }\n\n // Time-based rotation\n if (rotationMs && Date.now() - lastRotation >= rotationMs) {\n return true;\n }\n\n return false;\n }\n\n // Perform rotation\n async function performRotation(): Promise<void> {\n await ensureModules();\n\n if (!writeStream) return;\n\n // Close current stream\n await new Promise<void>((resolve, reject) => {\n writeStream!.once('finish', resolve);\n writeStream!.once('error', reject);\n writeStream!.end();\n });\n writeStream = null;\n\n // Generate rotation timestamp\n const timestamp = new Date().toISOString().replace(/[:.]/g, '-');\n const ext = path!.extname(filePath);\n const base = filePath.slice(0, -ext.length);\n const rotatedPath = `${base}.${timestamp}${ext}`;\n\n // Rename current file\n fs!.renameSync(filePath, rotatedPath);\n\n // Compress if enabled\n if (compress && zlib) {\n const gzPath = `${rotatedPath}.gz`;\n const input = fs!.createReadStream(rotatedPath);\n const output = fs!.createWriteStream(gzPath);\n const gzip = zlib.createGzip();\n\n await new Promise<void>((resolve, reject) => {\n input.pipe(gzip).pipe(output);\n output.on('finish', () => {\n fs!.unlinkSync(rotatedPath);\n resolve();\n });\n output.on('error', reject);\n });\n }\n\n // Cleanup old files\n await cleanupOldFiles();\n\n // Reset state\n currentSize = 0;\n lastRotation = Date.now();\n }\n\n // Cleanup old rotated files\n async function cleanupOldFiles(): Promise<void> {\n await ensureModules();\n\n const dir = path!.dirname(filePath);\n const baseName = path!.basename(filePath);\n const ext = path!.extname(filePath);\n const prefix = baseName.slice(0, -ext.length);\n\n const files = fs!.readdirSync(dir)\n .filter((f) => f.startsWith(prefix) && f !== baseName)\n .map((f) => ({\n name: f,\n path: path!.join(dir, f),\n mtime: fs!.statSync(path!.join(dir, f)).mtime.getTime(),\n }))\n .sort((a, b) => b.mtime - a.mtime);\n\n // Remove excess files\n while (files.length > maxFiles) {\n const file = files.pop()!;\n fs!.unlinkSync(file.path);\n }\n }\n\n return {\n name: 'file',\n\n async write(entry: LogEntry): Promise<void> {\n // Check rotation\n if (shouldRotate()) {\n await performRotation();\n }\n\n // Get stream\n const stream = await ensureStream();\n\n // Format entry\n const line = formatJson(entry) + '\\n';\n const bytes = Buffer.byteLength(line, 'utf8');\n\n // Write\n return new Promise((resolve, reject) => {\n stream.write(line, (err) => {\n if (err) {\n reject(new TransportError(`Failed to write to file: ${err.message}`, 'file', err));\n } else {\n currentSize += bytes;\n resolve();\n }\n });\n });\n },\n\n async flush(): Promise<void> {\n if (writeStream && 'flush' in writeStream) {\n return new Promise<void>((resolve) => {\n (writeStream as NodeJS.WritableStream & { flush: (cb: () => void) => void }).flush(resolve);\n });\n }\n },\n\n async close(): Promise<void> {\n if (writeStream) {\n await new Promise<void>((resolve, reject) => {\n writeStream!.once('finish', resolve);\n writeStream!.once('error', reject);\n writeStream!.end();\n });\n writeStream = null;\n }\n },\n\n supports(env: 'node' | 'browser'): boolean {\n return env === 'node';\n },\n };\n}\n\nexport default fileTransport;\n","/**\n * @oxog/log - Stream Transport\n *\n * Output logs to Node.js writable streams.\n * Node.js only.\n *\n * @packageDocumentation\n */\n\nimport type { Transport, LogEntry, StreamTransportOptions } from '../types.js';\nimport { formatJson } from '../utils/format.js';\nimport { isNode } from '../utils/env.js';\nimport { TransportError, EnvironmentError } from '../errors.js';\n\n/**\n * Create a stream transport.\n *\n * @example\n * ```typescript\n * import { streamTransport } from '@oxog/log/transports';\n * import { createWriteStream } from 'fs';\n *\n * const transport = streamTransport({\n * stream: createWriteStream('./app.log'),\n * });\n * ```\n */\nexport function streamTransport(options: StreamTransportOptions): Transport {\n if (!isNode()) {\n throw new EnvironmentError('Stream transport is only available in Node.js', 'node');\n }\n\n const { stream } = options;\n\n if (!stream) {\n throw new TransportError('Stream is required', 'stream');\n }\n\n let closed = false;\n\n return {\n name: 'stream',\n\n write(entry: LogEntry): Promise<void> {\n if (closed) {\n return Promise.reject(new TransportError('Stream is closed', 'stream'));\n }\n\n const line = formatJson(entry) + '\\n';\n\n return new Promise((resolve, reject) => {\n const canWrite = stream.write(line, (err) => {\n if (err) {\n reject(new TransportError(`Failed to write to stream: ${err.message}`, 'stream', err));\n } else {\n resolve();\n }\n });\n\n // Handle backpressure\n if (!canWrite) {\n stream.once('drain', () => {\n resolve();\n });\n }\n });\n },\n\n flush(): Promise<void> {\n // Most streams don't have explicit flush\n return Promise.resolve();\n },\n\n async close(): Promise<void> {\n if (closed) return;\n closed = true;\n\n return new Promise((resolve, reject) => {\n stream.once('finish', resolve);\n stream.once('error', (err) => {\n reject(new TransportError(`Failed to close stream: ${err.message}`, 'stream', err));\n });\n stream.end();\n });\n },\n\n supports(env: 'node' | 'browser'): boolean {\n return env === 'node';\n },\n };\n}\n\nexport default streamTransport;\n","/**\n * @oxog/log - HTTP Transport\n *\n * Send logs to HTTP endpoints with batching and retry.\n *\n * @packageDocumentation\n */\n\nimport type { Transport, LogEntry, HttpTransportOptions } from '../types.js';\nimport { TransportError } from '../errors.js';\n\n/**\n * Create an HTTP transport.\n *\n * @example\n * ```typescript\n * import { httpTransport } from '@oxog/log/transports';\n *\n * const transport = httpTransport({\n * url: 'https://logs.example.com/ingest',\n * batch: 100,\n * interval: 5000,\n * headers: { 'X-API-Key': 'xxx' },\n * });\n * ```\n */\nexport function httpTransport(options: HttpTransportOptions): Transport {\n const {\n url,\n method = 'POST',\n headers = {},\n batch = 100,\n interval = 5000,\n retry = 3,\n } = options;\n\n if (!url) {\n throw new TransportError('URL is required', 'http');\n }\n\n // Buffer for batching\n let buffer: LogEntry[] = [];\n let flushTimer: ReturnType<typeof setInterval> | null = null;\n let isFlushing = false;\n let closed = false;\n\n // Start flush interval\n function startFlushInterval(): void {\n if (flushTimer) return;\n if (interval > 0) {\n flushTimer = setInterval(() => {\n flushBuffer().catch(() => {\n // Silently ignore interval flush errors\n });\n }, interval);\n }\n }\n\n // Stop flush interval\n function stopFlushInterval(): void {\n if (flushTimer) {\n clearInterval(flushTimer);\n flushTimer = null;\n }\n }\n\n // Flush the buffer\n async function flushBuffer(): Promise<void> {\n if (isFlushing || buffer.length === 0) return;\n isFlushing = true;\n\n // Take current buffer\n const entries = buffer;\n buffer = [];\n\n try {\n await sendWithRetry(entries);\n } catch (err) {\n // Put entries back in buffer if send fails\n buffer = [...entries, ...buffer].slice(0, batch * 2); // Limit buffer size\n throw err;\n } finally {\n isFlushing = false;\n }\n }\n\n // Send entries with retry\n async function sendWithRetry(entries: LogEntry[]): Promise<void> {\n let lastError: Error | null = null;\n\n for (let attempt = 0; attempt <= retry; attempt++) {\n try {\n await sendEntries(entries);\n return;\n } catch (err) {\n lastError = err instanceof Error ? err : new Error(String(err));\n\n // Exponential backoff\n if (attempt < retry) {\n const delay = Math.min(1000 * Math.pow(2, attempt), 30000);\n await sleep(delay);\n }\n }\n }\n\n throw new TransportError(\n `Failed to send logs after ${retry + 1} attempts: ${lastError?.message}`,\n 'http',\n lastError || undefined\n );\n }\n\n // Send entries to endpoint\n async function sendEntries(entries: LogEntry[]): Promise<void> {\n const body = JSON.stringify(entries);\n\n const response = await fetch(url, {\n method,\n headers: {\n 'Content-Type': 'application/json',\n ...headers,\n },\n body,\n });\n\n if (!response.ok) {\n throw new Error(`HTTP ${response.status}: ${response.statusText}`);\n }\n }\n\n // Sleep utility\n function sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n }\n\n // Start interval on first write\n let started = false;\n\n return {\n name: 'http',\n\n async write(entry: LogEntry): Promise<void> {\n if (closed) {\n throw new TransportError('Transport is closed', 'http');\n }\n\n // Start interval on first write\n if (!started) {\n started = true;\n startFlushInterval();\n }\n\n // Add to buffer\n buffer.push(entry);\n\n // Flush if buffer is full\n if (buffer.length >= batch) {\n await flushBuffer();\n }\n },\n\n async flush(): Promise<void> {\n await flushBuffer();\n },\n\n async close(): Promise<void> {\n if (closed) return;\n closed = true;\n\n stopFlushInterval();\n\n // Final flush\n if (buffer.length > 0) {\n try {\n await flushBuffer();\n } catch {\n // Ignore errors on close\n }\n }\n },\n\n supports(_env: 'node' | 'browser'): boolean {\n // Works in both environments with fetch\n return typeof fetch !== 'undefined';\n },\n };\n}\n\nexport default httpTransport;\n","/**\n * @oxog/log - LocalStorage Transport\n *\n * Persist logs to browser localStorage.\n * Browser only.\n *\n * @packageDocumentation\n */\n\nimport type { Transport, LogEntry, LocalStorageTransportOptions, LogLevelName } from '../types.js';\nimport { isBrowser } from '../utils/env.js';\nimport { parseSize } from '../constants.js';\nimport { TransportError, EnvironmentError } from '../errors.js';\nimport { LOG_LEVELS } from '../constants.js';\n\n/**\n * Create a localStorage transport.\n *\n * @example\n * ```typescript\n * import { localStorageTransport } from '@oxog/log/transports';\n *\n * const transport = localStorageTransport({\n * key: 'app-logs',\n * maxSize: '1MB',\n * levels: ['error', 'fatal'],\n * });\n * ```\n */\nexport function localStorageTransport(options: LocalStorageTransportOptions): Transport {\n if (!isBrowser()) {\n throw new EnvironmentError('LocalStorage transport is only available in browser', 'browser');\n }\n\n const {\n key,\n maxSize = '1MB',\n levels,\n } = options;\n\n if (!key) {\n throw new TransportError('Key is required', 'localStorage');\n }\n\n const maxBytes = parseSize(maxSize);\n const allowedLevels = levels\n ? new Set(levels.map((l) => LOG_LEVELS[l]))\n : null;\n\n // Get storage\n function getStorage(): Storage {\n return window.localStorage;\n }\n\n // Load existing logs\n function loadLogs(): LogEntry[] {\n try {\n const data = getStorage().getItem(key);\n if (!data) return [];\n return JSON.parse(data) as LogEntry[];\n } catch {\n return [];\n }\n }\n\n // Save logs\n function saveLogs(logs: LogEntry[]): void {\n const data = JSON.stringify(logs);\n\n // Check size\n while (data.length > maxBytes && logs.length > 0) {\n logs.shift(); // Remove oldest\n }\n\n try {\n getStorage().setItem(key, JSON.stringify(logs));\n } catch (err) {\n // Storage full - try to clear some space\n if (logs.length > 10) {\n logs.splice(0, Math.floor(logs.length / 2));\n saveLogs(logs);\n }\n }\n }\n\n // Check if level is allowed\n function isLevelAllowed(level: number): boolean {\n if (!allowedLevels) return true;\n return allowedLevels.has(level);\n }\n\n return {\n name: 'localStorage',\n\n write(entry: LogEntry): void {\n // Check level filter\n if (!isLevelAllowed(entry.level)) {\n return;\n }\n\n // Load, add, save\n const logs = loadLogs();\n logs.push(entry);\n saveLogs(logs);\n },\n\n flush(): void {\n // Nothing to flush - writes are immediate\n },\n\n close(): void {\n // Nothing to close\n },\n\n supports(env: 'node' | 'browser'): boolean {\n return env === 'browser';\n },\n };\n}\n\n/**\n * Read logs from localStorage.\n *\n * @example\n * ```typescript\n * const logs = readLogs('app-logs');\n * ```\n */\nexport function readLogs(key: string): LogEntry[] {\n if (!isBrowser()) return [];\n\n try {\n const data = window.localStorage.getItem(key);\n if (!data) return [];\n return JSON.parse(data) as LogEntry[];\n } catch {\n return [];\n }\n}\n\n/**\n * Clear logs from localStorage.\n *\n * @example\n * ```typescript\n * clearLogs('app-logs');\n * ```\n */\nexport function clearLogs(key: string): void {\n if (!isBrowser()) return;\n window.localStorage.removeItem(key);\n}\n\n/**\n * Get storage usage for logs.\n *\n * @example\n * ```typescript\n * const bytes = getStorageUsage('app-logs');\n * ```\n */\nexport function getStorageUsage(key: string): number {\n if (!isBrowser()) return 0;\n\n const data = window.localStorage.getItem(key);\n if (!data) return 0;\n return data.length * 2; // UTF-16 encoding\n}\n\nexport default localStorageTransport;\n","/**\n * @oxog/log - Redaction Utilities\n *\n * Mask sensitive data in log entries.\n *\n * @packageDocumentation\n */\n\nimport { REDACTED_VALUE } from '../constants.js';\n\n/**\n * Redact sensitive fields from an object.\n *\n * @example\n * ```typescript\n * const data = { user: 'john', password: 'secret' };\n * const redacted = redactFields(data, ['password']);\n * // { user: 'john', password: '[REDACTED]' }\n * ```\n */\nexport function redactFields<T extends Record<string, unknown>>(\n obj: T,\n paths: string[],\n placeholder = REDACTED_VALUE\n): T {\n if (!obj || typeof obj !== 'object' || paths.length === 0) {\n return obj;\n }\n\n // Create a deep clone to avoid mutating the original\n const result = deepClone(obj);\n\n for (const path of paths) {\n redactPath(result, path.split('.'), placeholder);\n }\n\n return result;\n}\n\n/**\n * Deep clone an object.\n */\nfunction deepClone<T>(obj: T): T {\n if (obj === null || typeof obj !== 'object') {\n return obj;\n }\n\n if (Array.isArray(obj)) {\n return obj.map((item) => deepClone(item)) as unknown as T;\n }\n\n if (obj instanceof Date) {\n return new Date(obj.getTime()) as unknown as T;\n }\n\n if (obj instanceof RegExp) {\n return new RegExp(obj.source, obj.flags) as unknown as T;\n }\n\n if (obj instanceof Map) {\n const result = new Map();\n for (const [key, value] of obj) {\n result.set(key, deepClone(value));\n }\n return result as unknown as T;\n }\n\n if (obj instanceof Set) {\n const result = new Set();\n for (const value of obj) {\n result.add(deepClone(value));\n }\n return result as unknown as T;\n }\n\n const result: Record<string, unknown> = {};\n for (const key of Object.keys(obj)) {\n result[key] = deepClone((obj as Record<string, unknown>)[key]);\n }\n return result as T;\n}\n\n/**\n * Redact a value at a specific path in an object.\n */\nfunction redactPath(\n obj: Record<string, unknown>,\n pathParts: string[],\n placeholder: string\n): void {\n if (pathParts.length === 0 || !obj || typeof obj !== 'object') {\n return;\n }\n\n const [current, ...rest] = pathParts;\n if (!current) return;\n\n // Handle wildcard matching\n if (current === '*') {\n for (const key of Object.keys(obj)) {\n if (rest.length === 0) {\n obj[key] = placeholder;\n } else {\n const value = obj[key];\n if (value && typeof value === 'object') {\n redactPath(value as Record<string, unknown>, rest, placeholder);\n }\n }\n }\n return;\n }\n\n // Handle array index notation [*]\n if (current === '[*]' && Array.isArray(obj)) {\n for (let i = 0; i < obj.length; i++) {\n if (rest.length === 0) {\n obj[i] = placeholder;\n } else {\n const value = obj[i];\n if (value && typeof value === 'object') {\n redactPath(value as Record<string, unknown>, rest, placeholder);\n }\n }\n }\n return;\n }\n\n if (!(current in obj)) {\n return;\n }\n\n if (rest.length === 0) {\n // Final path segment - redact the value\n obj[current] = placeholder;\n } else {\n // Continue traversing\n const value = obj[current];\n if (value && typeof value === 'object') {\n redactPath(value as Record<string, unknown>, rest, placeholder);\n }\n }\n}\n\n/**\n * Check if a field name matches any of the sensitive patterns.\n *\n * @example\n * ```typescript\n * isSensitive('password', ['password', 'token']); // true\n * isSensitive('username', ['password', 'token']); // false\n * ```\n */\nexport function isSensitive(fieldName: string, sensitivePatterns: string[]): boolean {\n const lowerField = fieldName.toLowerCase();\n\n return sensitivePatterns.some((pattern) => {\n const lowerPattern = pattern.toLowerCase();\n\n // Exact match\n if (lowerField === lowerPattern) return true;\n\n // Contains match\n if (lowerField.includes(lowerPattern)) return true;\n\n // Regex pattern (if pattern looks like a regex)\n if (pattern.startsWith('/') && pattern.endsWith('/')) {\n try {\n const regex = new RegExp(pattern.slice(1, -1), 'i');\n return regex.test(fieldName);\n } catch {\n return false;\n }\n }\n\n return false;\n });\n}\n\n/**\n * Create a redaction function with predefined paths.\n *\n * @example\n * ```typescript\n * const redact = createRedactor(['password', 'token']);\n * const safe = redact({ password: 'secret' });\n * ```\n */\nexport function createRedactor(\n paths: string[],\n placeholder = REDACTED_VALUE\n): <T extends Record<string, unknown>>(obj: T) => T {\n return (obj) => redactFields(obj, paths, placeholder);\n}\n\n/**\n * Auto-redact common sensitive field names.\n *\n * @example\n * ```typescript\n * const safe = autoRedact({ password: 'secret', username: 'john' });\n * // { password: '[REDACTED]', username: 'john' }\n * ```\n */\nexport function autoRedact<T extends Record<string, unknown>>(\n obj: T,\n additionalPatterns: string[] = [],\n placeholder = REDACTED_VALUE\n): T {\n if (!obj || typeof obj !== 'object') {\n return obj;\n }\n\n const defaultPatterns = [\n 'password',\n 'passwd',\n 'pwd',\n 'secret',\n 'token',\n 'apikey',\n 'api_key',\n 'apiKey',\n 'auth',\n 'authorization',\n 'credential',\n 'credentials',\n 'private',\n 'privateKey',\n 'private_key',\n ];\n\n const patterns = [...defaultPatterns, ...additionalPatterns];\n const result = deepClone(obj);\n\n autoRedactRecursive(result, patterns, placeholder);\n\n return result;\n}\n\n/**\n * Recursively auto-redact sensitive fields.\n */\nfunction autoRedactRecursive(\n obj: Record<string, unknown>,\n patterns: string[],\n placeholder: string\n): void {\n for (const key of Object.keys(obj)) {\n const value = obj[key];\n\n if (isSensitive(key, patterns)) {\n obj[key] = placeholder;\n } else if (value && typeof value === 'object' && !Array.isArray(value)) {\n autoRedactRecursive(value as Record<string, unknown>, patterns, placeholder);\n } else if (Array.isArray(value)) {\n for (const item of value) {\n if (item && typeof item === 'object') {\n autoRedactRecursive(item as Record<string, unknown>, patterns, placeholder);\n }\n }\n }\n }\n}\n","/**\n * @oxog/log - Redact Plugin\n *\n * Masks sensitive data in log entries.\n *\n * @packageDocumentation\n */\n\nimport type { Plugin } from '@oxog/types';\nimport type { LogContext, LogEntry } from '../../types.js';\nimport { redactFields } from '../../utils/redact.js';\nimport { REDACTED_VALUE } from '../../constants.js';\n\n/**\n * Redact plugin configuration options.\n */\nexport interface RedactPluginOptions {\n /** Field paths to redact */\n paths?: string[];\n\n /** Placeholder text for redacted values */\n placeholder?: string;\n}\n\n/**\n * Redact plugin for masking sensitive data.\n *\n * This plugin:\n * - Masks specified fields with placeholder\n * - Supports dot notation for nested paths\n * - Supports wildcards for arrays\n *\n * @example\n * ```typescript\n * import { redactPlugin } from '@oxog/log/plugins';\n *\n * logger.use(redactPlugin({\n * paths: ['password', 'user.token', 'headers.authorization']\n * }));\n * ```\n */\nexport function redactPlugin(options: RedactPluginOptions = {}): Plugin<LogContext> {\n return {\n name: 'redact',\n version: '1.0.0',\n\n install(kernel) {\n const ctx = kernel.getContext();\n const paths = options.paths || ctx.redactPaths || [];\n const placeholder = options.placeholder || REDACTED_VALUE;\n\n // Store configuration in context\n ctx.redactPaths = paths;\n\n // Expose redaction function\n (kernel as unknown as { redact: (entry: LogEntry) => LogEntry }).redact = (entry) => {\n return redactEntry(entry, paths, placeholder);\n };\n },\n };\n}\n\n/**\n * Redact sensitive fields from a log entry.\n */\nexport function redactEntry(\n entry: LogEntry,\n paths: string[],\n placeholder = REDACTED_VALUE\n): LogEntry {\n if (paths.length === 0) {\n return entry;\n }\n\n return redactFields(entry, paths, placeholder);\n}\n\nexport default redactPlugin;\n","/**\n * @oxog/log - Source Location Utilities\n *\n * Capture file and line number from stack traces.\n *\n * @packageDocumentation\n */\n\n/**\n * Source location information.\n */\nexport interface SourceLocation {\n /** Source file name (without path) */\n file: string;\n\n /** Full file path */\n path?: string;\n\n /** Line number */\n line: number;\n\n /** Column number */\n column?: number;\n\n /** Function name */\n fn?: string;\n}\n\n/**\n * Get the source location of the caller.\n *\n * @param depth - How many stack frames to skip (default: 0)\n *\n * @example\n * ```typescript\n * function myLogger() {\n * const loc = getSourceLocation(1); // Skip myLogger frame\n * console.log(`${loc.file}:${loc.line}`);\n * }\n * ```\n */\nexport function getSourceLocation(depth = 0): SourceLocation | undefined {\n // Create an Error to capture stack trace\n const err = new Error();\n const stack = err.stack;\n\n if (!stack) {\n return undefined;\n }\n\n // Parse the stack trace\n const frames = parseStack(stack);\n\n // Skip internal frames + depth\n // Typical stack: Error, getSourceLocation, caller1, caller2...\n const targetIndex = 2 + depth;\n\n if (targetIndex >= frames.length) {\n return undefined;\n }\n\n return frames[targetIndex];\n}\n\n/**\n * Parse a V8-style stack trace.\n *\n * V8 format:\n * ```\n * Error: message\n * at functionName (file:line:column)\n * at file:line:column\n * at Object.<anonymous> (file:line:column)\n * ```\n */\nfunction parseStack(stack: string): SourceLocation[] {\n const lines = stack.split('\\n');\n const frames: SourceLocation[] = [];\n\n for (const line of lines) {\n const trimmed = line.trim();\n\n // Skip \"Error:\" line\n if (!trimmed.startsWith('at ')) {\n continue;\n }\n\n const frame = parseV8Frame(trimmed);\n if (frame) {\n frames.push(frame);\n }\n }\n\n return frames;\n}\n\n/**\n * Parse a single V8 stack frame.\n *\n * Formats:\n * - \"at functionName (file:line:column)\"\n * - \"at file:line:column\"\n * - \"at Object.<anonymous> (file:line:column)\"\n * - \"at async functionName (file:line:column)\"\n */\nfunction parseV8Frame(line: string): SourceLocation | undefined {\n // Remove \"at \" prefix\n let content = line.slice(3);\n\n // Handle \"async \" prefix\n if (content.startsWith('async ')) {\n content = content.slice(6);\n }\n\n // Pattern 1: \"functionName (path:line:column)\"\n const parenMatch = content.match(/^(.+?)\\s+\\((.+):(\\d+):(\\d+)\\)$/);\n if (parenMatch) {\n const [, fn, path, lineStr, colStr] = parenMatch;\n return {\n fn: fn?.trim() || undefined,\n path: path,\n file: extractFileName(path || ''),\n line: parseInt(lineStr || '0', 10),\n column: parseInt(colStr || '0', 10),\n };\n }\n\n // Pattern 2: \"path:line:column\" (no function name)\n const simpleMatch = content.match(/^(.+):(\\d+):(\\d+)$/);\n if (simpleMatch) {\n const [, path, lineStr, colStr] = simpleMatch;\n return {\n path: path,\n file: extractFileName(path || ''),\n line: parseInt(lineStr || '0', 10),\n column: parseInt(colStr || '0', 10),\n };\n }\n\n // Pattern 3: \"path:line\" (no column)\n const noColMatch = content.match(/^(.+):(\\d+)$/);\n if (noColMatch) {\n const [, path, lineStr] = noColMatch;\n return {\n path: path,\n file: extractFileName(path || ''),\n line: parseInt(lineStr || '0', 10),\n };\n }\n\n return undefined;\n}\n\n/**\n * Extract the file name from a full path.\n *\n * @example\n * ```typescript\n * extractFileName('/path/to/file.ts'); // 'file.ts'\n * extractFileName('C:\\\\path\\\\to\\\\file.ts'); // 'file.ts'\n * extractFileName('file:///path/to/file.ts'); // 'file.ts'\n * ```\n */\nexport function extractFileName(path: string): string {\n // Remove file:// protocol\n let cleanPath = path.replace(/^file:\\/\\//, '');\n\n // Handle Windows paths\n cleanPath = cleanPath.replace(/\\\\/g, '/');\n\n // Remove query string and hash\n cleanPath = cleanPath.split('?')[0]?.split('#')[0] || cleanPath;\n\n // Get the file name\n const parts = cleanPath.split('/');\n return parts[parts.length - 1] || cleanPath;\n}\n\n/**\n * Check if a stack frame should be filtered out.\n * Used to skip internal frames from the logging library.\n *\n * @param location - Source location to check\n * @param internalPatterns - Patterns to filter (file names or paths)\n */\nexport function isInternalFrame(\n location: SourceLocation,\n internalPatterns: string[] = []\n): boolean {\n const defaultPatterns = [\n '@oxog/log',\n 'node_modules',\n 'internal/',\n '<anonymous>',\n ];\n\n const patterns = [...defaultPatterns, ...internalPatterns];\n const pathToCheck = location.path || location.file;\n\n return patterns.some((pattern) => {\n if (pattern.includes('/') || pattern.includes('\\\\')) {\n // Path pattern\n return pathToCheck.includes(pattern);\n }\n // File name pattern\n return location.file === pattern || location.file.includes(pattern);\n });\n}\n\n/**\n * Get the first non-internal source location.\n *\n * @param depth - Additional frames to skip\n * @param internalPatterns - Additional patterns to filter\n */\nexport function getCallerLocation(\n depth = 0,\n internalPatterns: string[] = []\n): SourceLocation | undefined {\n const err = new Error();\n const stack = err.stack;\n\n if (!stack) {\n return undefined;\n }\n\n const frames = parseStack(stack);\n\n // Skip: Error, getCallerLocation, getSourceLocation (if called), and depth\n let skipped = 0;\n for (const frame of frames) {\n if (skipped < 2 + depth) {\n skipped++;\n continue;\n }\n\n if (!isInternalFrame(frame, internalPatterns)) {\n return frame;\n }\n }\n\n return undefined;\n}\n\n/**\n * Format a source location as a string.\n *\n * @example\n * ```typescript\n * formatLocation({ file: 'app.ts', line: 42 }); // 'app.ts:42'\n * formatLocation({ file: 'app.ts', line: 42, column: 10 }); // 'app.ts:42:10'\n * ```\n */\nexport function formatLocation(location: SourceLocation): string {\n let result = location.file;\n\n if (location.line) {\n result += `:${location.line}`;\n }\n\n if (location.column) {\n result += `:${location.column}`;\n }\n\n return result;\n}\n","/**\n * @oxog/log - Source Plugin\n *\n * Captures source file and line number for log entries.\n *\n * @packageDocumentation\n */\n\nimport type { Plugin } from '@oxog/types';\nimport type { LogContext, LogEntry } from '../../types.js';\nimport { getSourceLocation, type SourceLocation } from '../../utils/source.js';\n\n/**\n * Source plugin configuration options.\n */\nexport interface SourcePluginOptions {\n /** Stack frame depth to skip */\n depth?: number;\n\n /** Include column number */\n includeColumn?: boolean;\n\n /** Include full file path */\n includeFullPath?: boolean;\n}\n\n/**\n * Source plugin for capturing file and line number.\n *\n * This plugin:\n * - Captures source file name\n * - Captures line number\n * - Optionally captures column number\n *\n * @example\n * ```typescript\n * import { sourcePlugin } from '@oxog/log/plugins';\n *\n * logger.use(sourcePlugin());\n *\n * log.info('Hello'); // Output includes file:line\n * ```\n */\nexport function sourcePlugin(options: SourcePluginOptions = {}): Plugin<LogContext> {\n return {\n name: 'source',\n version: '1.0.0',\n\n install(kernel) {\n const ctx = kernel.getContext();\n\n // Enable source tracking in context\n ctx.source = true;\n\n // Expose source location function with configured depth\n const depth = options.depth ?? 4; // Skip internal frames\n\n (kernel as unknown as { getSource: () => SourceLocation | undefined }).getSource = () => {\n return getSourceLocation(depth);\n };\n },\n };\n}\n\n/**\n * Add source location to a log entry.\n */\nexport function addSourceLocation(\n entry: LogEntry,\n depth = 4,\n options: SourcePluginOptions = {}\n): LogEntry {\n const location = getSourceLocation(depth);\n\n if (location) {\n entry.file = options.includeFullPath ? location.path : location.file;\n entry.line = location.line;\n\n if (options.includeColumn && location.column) {\n entry.column = location.column;\n }\n }\n\n return entry;\n}\n\nexport default sourcePlugin;\n","/**\n * @oxog/log - Timing Plugin\n *\n * Provides performance timing utilities for log entries.\n *\n * @packageDocumentation\n */\n\nimport type { Plugin } from '@oxog/types';\nimport type { LogContext } from '../../types.js';\n\n/**\n * Timing plugin for performance measurement.\n *\n * This plugin:\n * - Provides time/timeEnd methods\n * - Tracks named timers\n * - Logs duration in milliseconds\n *\n * @example\n * ```typescript\n * import { timingPlugin } from '@oxog/log/plugins';\n *\n * logger.use(timingPlugin());\n *\n * log.time('db-query');\n * await query();\n * log.timeEnd('db-query'); // logs duration\n * ```\n */\nexport function timingPlugin(): Plugin<LogContext> {\n return {\n name: 'timing',\n version: '1.0.0',\n\n install(kernel) {\n const ctx = kernel.getContext();\n\n // Initialize timers map\n if (!ctx.timers) {\n ctx.timers = new Map<string, number>();\n }\n },\n\n onDestroy() {\n // Clean up is handled by logger\n },\n };\n}\n\n/**\n * Start a timer with the given label.\n */\nexport function startTimer(ctx: LogContext, label: string): void {\n ctx.timers.set(label, performance.now());\n}\n\n/**\n * End a timer and return the duration.\n */\nexport function endTimer(ctx: LogContext, label: string): number | undefined {\n const start = ctx.timers.get(label);\n if (start === undefined) {\n return undefined;\n }\n\n const duration = performance.now() - start;\n ctx.timers.delete(label);\n return Math.round(duration * 100) / 100; // Round to 2 decimal places\n}\n\n/**\n * Check if a timer exists.\n */\nexport function hasTimer(ctx: LogContext, label: string): boolean {\n return ctx.timers.has(label);\n}\n\n/**\n * Get all active timer labels.\n */\nexport function getActiveTimers(ctx: LogContext): string[] {\n return Array.from(ctx.timers.keys());\n}\n\n/**\n * Clear all timers.\n */\nexport function clearTimers(ctx: LogContext): void {\n ctx.timers.clear();\n}\n\n/**\n * Create a one-shot timer function.\n */\nexport function createTimer(ctx: LogContext, label: string): () => number | undefined {\n startTimer(ctx, label);\n return () => endTimer(ctx, label);\n}\n\nexport default timingPlugin;\n","/**\n * @oxog/log - Correlation Plugin\n *\n * Provides correlation ID tracking for request tracing.\n *\n * @packageDocumentation\n */\n\nimport type { Plugin } from '@oxog/types';\nimport type { LogContext, LogEntry } from '../../types.js';\n\n/**\n * Correlation plugin configuration options.\n */\nexport interface CorrelationPluginOptions {\n /** Prefix for auto-generated correlation IDs */\n prefix?: string;\n\n /** Custom ID generator function */\n generator?: () => string;\n}\n\n// Store options at module level for ID generation\nlet correlationOptions: CorrelationPluginOptions = {};\n\n/**\n * Correlation plugin for request tracing.\n *\n * This plugin:\n * - Adds correlation ID to all log entries\n * - Supports auto-generation of IDs\n * - Inherits correlation ID in child loggers\n *\n * @example\n * ```typescript\n * import { correlationPlugin } from '@oxog/log/plugins';\n *\n * logger.use(correlationPlugin());\n *\n * const reqLog = log.withCorrelation('req-123');\n * reqLog.info('Processing'); // includes correlationId\n * ```\n */\nexport function correlationPlugin(options: CorrelationPluginOptions = {}): Plugin<LogContext> {\n return {\n name: 'correlation',\n version: '1.0.0',\n\n install(_kernel) {\n // Store options for ID generation\n correlationOptions = options;\n },\n };\n}\n\n/**\n * Generate a correlation ID.\n */\nexport function generateCorrelationId(): string {\n if (correlationOptions.generator) {\n return correlationOptions.generator();\n }\n\n const prefix = correlationOptions.prefix ?? 'cid';\n const random = Math.random().toString(36).substring(2, 10);\n const timestamp = Date.now().toString(36);\n return `${prefix}_${timestamp}${random}`;\n}\n\n/**\n * Add correlation ID to a log entry.\n */\nexport function addCorrelationId(entry: LogEntry, correlationId: string): LogEntry {\n entry.correlationId = correlationId;\n return entry;\n}\n\n/**\n * Get correlation ID from context.\n */\nexport function getCorrelationId(ctx: LogContext): string | undefined {\n return ctx.correlationId;\n}\n\n/**\n * Set correlation ID on context.\n */\nexport function setCorrelationId(ctx: LogContext, correlationId: string): void {\n ctx.correlationId = correlationId;\n}\n\n/**\n * Create or get a correlation ID.\n */\nexport function ensureCorrelationId(ctx: LogContext): string {\n if (!ctx.correlationId) {\n ctx.correlationId = generateCorrelationId();\n }\n return ctx.correlationId;\n}\n\nexport default correlationPlugin;\n","/**\n * @oxog/log - Buffer Plugin\n *\n * Provides async buffering for log entries.\n *\n * @packageDocumentation\n */\n\nimport type { Plugin } from '@oxog/types';\nimport type { LogContext, LogEntry, BufferOptions } from '../../types.js';\nimport { DEFAULT_BUFFER_OPTIONS } from '../../constants.js';\n\n/**\n * Buffer plugin for async log buffering.\n *\n * This plugin:\n * - Buffers log entries for batch processing\n * - Flushes based on size or interval\n * - Respects sync levels (fatal/error bypass buffer)\n *\n * @example\n * ```typescript\n * import { bufferPlugin } from '@oxog/log/plugins';\n *\n * logger.use(bufferPlugin({\n * size: 100,\n * flushInterval: 1000\n * }));\n * ```\n */\nexport function bufferPlugin(options: BufferOptions = {}): Plugin<LogContext> {\n return {\n name: 'buffer',\n version: '1.0.0',\n\n install(kernel) {\n const ctx = kernel.getContext();\n\n // Initialize buffer\n ctx.buffer = [];\n ctx.bufferOptions = {\n size: options.size ?? DEFAULT_BUFFER_OPTIONS.size,\n flushInterval: options.flushInterval ?? DEFAULT_BUFFER_OPTIONS.flushInterval,\n };\n\n // Start flush interval\n const flushInterval = ctx.bufferOptions.flushInterval ?? DEFAULT_BUFFER_OPTIONS.flushInterval;\n if (flushInterval > 0) {\n ctx.flushTimerId = setInterval(() => {\n flushBuffer(ctx).catch(() => {\n // Silently ignore flush errors in interval\n });\n }, flushInterval);\n }\n },\n\n async onDestroy() {\n // Flush is handled by logger.close()\n },\n };\n}\n\n/**\n * Add an entry to the buffer.\n * Returns true if buffer was flushed.\n */\nexport function bufferEntry(ctx: LogContext, entry: LogEntry): boolean {\n ctx.buffer.push(entry);\n\n // Check if buffer is full\n if (ctx.buffer.length >= (ctx.bufferOptions.size ?? DEFAULT_BUFFER_OPTIONS.size)) {\n // Flush synchronously to avoid overflow\n flushBufferSync(ctx);\n return true;\n }\n\n return false;\n}\n\n/**\n * Flush the buffer asynchronously.\n */\nexport async function flushBuffer(ctx: LogContext): Promise<LogEntry[]> {\n if (ctx.buffer.length === 0) {\n return [];\n }\n\n // Swap buffer\n const entries = ctx.buffer;\n ctx.buffer = [];\n\n // Write all entries to transports\n await Promise.all(\n entries.flatMap((entry) =>\n ctx.transports.map((transport) =>\n Promise.resolve(transport.write(entry)).catch(() => {\n // Silently ignore individual transport errors\n })\n )\n )\n );\n\n // Emit flush event\n ctx.emitter.emit('flush', undefined as never);\n\n return entries;\n}\n\n/**\n * Flush the buffer synchronously.\n */\nexport function flushBufferSync(ctx: LogContext): LogEntry[] {\n if (ctx.buffer.length === 0) {\n return [];\n }\n\n // Swap buffer\n const entries = ctx.buffer;\n ctx.buffer = [];\n\n // Write all entries to transports (ignore promises)\n for (const entry of entries) {\n for (const transport of ctx.transports) {\n try {\n transport.write(entry);\n } catch {\n // Silently ignore errors\n }\n }\n }\n\n return entries;\n}\n\n/**\n * Get the current buffer size.\n */\nexport function getBufferSize(ctx: LogContext): number {\n return ctx.buffer.length;\n}\n\n/**\n * Clear the buffer without flushing.\n */\nexport function clearBuffer(ctx: LogContext): LogEntry[] {\n const entries = ctx.buffer;\n ctx.buffer = [];\n return entries;\n}\n\n/**\n * Stop the flush interval timer.\n */\nexport function stopFlushInterval(ctx: LogContext): void {\n if (ctx.flushTimerId) {\n clearInterval(ctx.flushTimerId);\n ctx.flushTimerId = undefined;\n }\n}\n\nexport default bufferPlugin;\n","/**\n * @oxog/log - Browser Plugin\n *\n * Provides native browser DevTools integration.\n *\n * @packageDocumentation\n */\n\nimport type { Plugin } from '@oxog/types';\nimport type { LogContext, LogEntry, LogLevelName } from '../../types.js';\nimport { isBrowser } from '../../utils/env.js';\n\n/**\n * Browser plugin configuration options.\n */\nexport interface BrowserPluginOptions {\n /** Enable console grouping for child loggers */\n grouping?: boolean;\n\n /** Enable styled output */\n styled?: boolean;\n\n /** Custom styles per level */\n styles?: Partial<Record<LogLevelName, string>>;\n}\n\n// Store options at module level\nlet browserOptions: BrowserPluginOptions = {};\n\n/**\n * Browser plugin for DevTools integration.\n *\n * This plugin:\n * - Maps log levels to console methods\n * - Provides styled console output\n * - Uses console.group for child loggers\n *\n * @example\n * ```typescript\n * import { browserPlugin } from '@oxog/log/plugins';\n *\n * logger.use(browserPlugin({ styled: true }));\n *\n * log.info('Hello'); // Uses console.log with styling\n * log.error('Oops'); // Uses console.error with styling\n * ```\n */\nexport function browserPlugin(options: BrowserPluginOptions = {}): Plugin<LogContext> {\n return {\n name: 'browser',\n version: '1.0.0',\n\n install(_kernel) {\n // Store options for browser output\n browserOptions = options;\n },\n };\n}\n\n/**\n * Get the console method for a log level.\n */\nexport function getConsoleMethod(levelName: LogLevelName): 'log' | 'debug' | 'info' | 'warn' | 'error' {\n switch (levelName) {\n case 'trace':\n case 'debug':\n return 'debug';\n case 'info':\n return 'info';\n case 'warn':\n return 'warn';\n case 'error':\n case 'fatal':\n return 'error';\n default:\n return 'log';\n }\n}\n\n/**\n * Get CSS styles for a log level.\n */\nexport function getLevelStyles(levelName: LogLevelName): string {\n if (browserOptions.styles?.[levelName]) {\n return browserOptions.styles[levelName]!;\n }\n\n const colors: Record<LogLevelName, string> = {\n trace: '#888888',\n debug: '#00bcd4',\n info: '#2196f3',\n warn: '#ff9800',\n error: '#f44336',\n fatal: '#9c27b0',\n };\n\n return `color: ${colors[levelName] ?? '#000000'}; font-weight: bold;`;\n}\n\n/**\n * Write a log entry to the browser console.\n */\nexport function writeToBrowserConsole(entry: LogEntry, styled = true): void {\n if (!isBrowser()) return;\n\n const method = getConsoleMethod(entry.levelName);\n const consoleObj = console as unknown as Record<string, (...args: unknown[]) => void>;\n\n if (styled) {\n const styles = getLevelStyles(entry.levelName);\n const label = `%c[${entry.levelName.toUpperCase()}]`;\n\n // Extract extra data (excluding standard fields)\n const {\n level: _level,\n levelName: _levelName,\n time: _time,\n msg,\n file: _file,\n line: _line,\n column: _column,\n correlationId: _correlationId,\n ...extra\n } = entry;\n\n if (Object.keys(extra).length > 0) {\n consoleObj[method](label, styles, msg, extra);\n } else {\n consoleObj[method](label, styles, msg);\n }\n } else {\n consoleObj[method](`[${entry.levelName.toUpperCase()}]`, entry.msg, entry);\n }\n}\n\n/**\n * Start a console group.\n */\nexport function startGroup(label: string, collapsed = false): void {\n if (!isBrowser()) return;\n\n if (collapsed) {\n console.groupCollapsed(label);\n } else {\n console.group(label);\n }\n}\n\n/**\n * End a console group.\n */\nexport function endGroup(): void {\n if (!isBrowser()) return;\n console.groupEnd();\n}\n\n/**\n * Check if grouping is enabled.\n */\nexport function isGroupingEnabled(): boolean {\n return browserOptions.grouping ?? true;\n}\n\nexport default browserPlugin;\n"],"mappings":"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","names":["LogLevel","indent","pigment","pigment","formatTime","getExtraFields","flushBuffer","result"]}
1
+ {"version":3,"sources":["../src/logger.ts","../src/types.ts","../src/constants.ts","../src/utils/env.ts","../src/utils/format.ts","../src/transports/console.ts","../src/plugins/core/level.ts","../src/plugins/core/format.ts","../src/plugins/core/timestamp.ts","../src/errors.ts","../src/transports/file.ts","../src/transports/stream.ts","../src/transports/http.ts","../src/transports/localStorage.ts","../src/utils/redact.ts","../src/plugins/optional/redact.ts","../src/utils/source.ts","../src/plugins/optional/source.ts","../src/plugins/optional/timing.ts","../src/plugins/optional/correlation.ts","../src/plugins/optional/buffer.ts","../src/plugins/optional/browser.ts"],"sourcesContent":["/**\n * @oxog/log - Logger Factory\n *\n * Creates logger instances with plugin-based architecture.\n *\n * @packageDocumentation\n */\n\nimport { createKernel } from '@oxog/plugin';\nimport { createEmitter } from '@oxog/emitter';\nimport { pigment } from '@oxog/pigment';\nimport type { Plugin } from '@oxog/types';\nimport type {\n Logger,\n LoggerOptions,\n LogEntry,\n LogContext,\n LogEvents,\n LogLevelName,\n LogLevel,\n Transport,\n Format,\n Unsubscribe,\n} from './types.js';\nimport { LOG_LEVELS, LEVEL_NAMES, DEFAULT_NAME, DEFAULT_LEVEL, DEFAULT_FORMAT } from './constants.js';\nimport { getEnvironment, isNode } from './utils/env.js';\nimport { consoleTransport } from './transports/console.js';\nimport { levelPlugin } from './plugins/core/level.js';\nimport { formatPlugin } from './plugins/core/format.js';\nimport { timestampPlugin } from './plugins/core/timestamp.js';\nimport { ConfigError } from './errors.js';\n\n/**\n * Create a logger instance.\n *\n * @example\n * ```typescript\n * import { createLogger } from '@oxog/log';\n *\n * const logger = createLogger({\n * name: 'my-app',\n * level: 'debug',\n * transports: [consoleTransport()],\n * });\n *\n * logger.info('Hello, world!');\n * ```\n */\nexport function createLogger(options: LoggerOptions = {}): Logger {\n const {\n name = DEFAULT_NAME,\n level = DEFAULT_LEVEL,\n format = DEFAULT_FORMAT,\n colors = true,\n transports = [],\n redact = [],\n source = false,\n timestamp = true,\n sync = { fatal: true, error: true },\n buffer,\n context: initialContext = {},\n plugins = [],\n } = options;\n\n // Validate level\n if (!(level in LOG_LEVELS)) {\n throw new ConfigError(`Invalid log level: ${level}`, 'level');\n }\n\n // Create event emitter\n const emitter = createEmitter<LogEvents>();\n\n // Setup transports\n const activeTransports: Transport[] = [];\n const env = getEnvironment();\n\n // Add default console transport if none specified\n if (transports.length === 0) {\n activeTransports.push(consoleTransport({ colors }));\n } else {\n for (const transport of transports) {\n if (!transport.supports || transport.supports(env as 'node' | 'browser')) {\n activeTransports.push(transport);\n }\n }\n }\n\n // Create kernel context\n const kernelContext: LogContext = {\n name,\n level: LOG_LEVELS[level] as unknown as LogLevel,\n format: resolveFormat(format),\n colors,\n timestamp,\n source,\n transports: activeTransports,\n redactPaths: redact,\n bindings: { ...initialContext },\n correlationId: undefined,\n pigment,\n emitter,\n syncLevels: {\n trace: sync.trace ?? false,\n debug: sync.debug ?? false,\n info: sync.info ?? false,\n warn: sync.warn ?? false,\n error: sync.error ?? true,\n fatal: sync.fatal ?? true,\n },\n bufferOptions: buffer ?? {},\n timers: new Map(),\n buffer: [],\n flushTimerId: undefined,\n };\n\n // Create kernel with plugins\n const kernel = createKernel<LogContext>({ context: kernelContext });\n\n // Install core plugins\n kernel.use(levelPlugin());\n kernel.use(formatPlugin());\n kernel.use(timestampPlugin());\n\n // Install user plugins\n for (const plugin of plugins) {\n kernel.use(plugin);\n }\n\n // Track if logger is closed\n let closed = false;\n\n // Emit transport error\n function emitTransportError(transportName: string, error: unknown, entry?: LogEntry): void {\n const err = error instanceof Error ? error : new Error(String(error));\n emitter.emit('error', { transport: transportName, error: err, entry });\n\n // Fallback to stderr for critical visibility\n if (isNode()) {\n process.stderr.write(`[LOG TRANSPORT ERROR] ${transportName}: ${err.message}\\n`);\n }\n }\n\n // Write to transports synchronously (blocking)\n function writeToTransportsSync(entry: LogEntry): void {\n if (closed) return;\n\n for (const transport of activeTransports) {\n try {\n if (transport.writeSync) {\n transport.writeSync(entry);\n } else {\n // Fallback to async write but don't await (best effort)\n const result = transport.write(entry);\n if (result instanceof Promise) {\n result.catch((err) => emitTransportError(transport.name, err, entry));\n }\n }\n } catch (err) {\n emitTransportError(transport.name, err, entry);\n }\n }\n }\n\n // Write to transports asynchronously\n async function writeToTransports(entry: LogEntry): Promise<void> {\n if (closed) return;\n\n const promises: Promise<void>[] = [];\n\n for (const transport of activeTransports) {\n try {\n const result = transport.write(entry);\n if (result instanceof Promise) {\n promises.push(\n result.catch((err) => {\n emitTransportError(transport.name, err, entry);\n })\n );\n }\n } catch (err) {\n emitTransportError(transport.name, err, entry);\n }\n }\n\n if (promises.length > 0) {\n await Promise.all(promises);\n }\n }\n\n // Create log entry\n function createEntry(\n levelNum: LogLevel,\n levelName: LogLevelName,\n msg: string,\n data?: Record<string, unknown>,\n error?: Error\n ): LogEntry {\n const ctx = kernel.getContext();\n\n const entry: LogEntry = {\n level: levelNum,\n levelName,\n time: Date.now(),\n msg,\n ...ctx.bindings,\n ...data,\n };\n\n // Add error if present\n if (error) {\n entry.err = {\n name: error.name,\n message: error.message,\n stack: error.stack,\n };\n }\n\n // Add correlation ID if set\n if (ctx.correlationId) {\n entry.correlationId = ctx.correlationId;\n }\n\n return entry;\n }\n\n // Check if level is enabled\n function isEnabled(levelNum: LogLevel): boolean {\n const ctx = kernel.getContext();\n return levelNum >= ctx.level;\n }\n\n // Should write sync\n function shouldSync(levelName: LogLevelName): boolean {\n const ctx = kernel.getContext();\n return ctx.syncLevels[levelName] ?? false;\n }\n\n // Generic log method\n function log(\n levelNum: LogLevel,\n levelName: LogLevelName,\n msgOrObj: string | object,\n msgOrUndefined?: string\n ): void {\n if (!isEnabled(levelNum)) return;\n\n let msg: string;\n let data: Record<string, unknown> | undefined;\n let error: Error | undefined;\n\n if (typeof msgOrObj === 'string') {\n msg = msgOrObj;\n } else if (msgOrObj instanceof Error) {\n msg = msgOrUndefined ?? msgOrObj.message;\n error = msgOrObj;\n } else {\n msg = msgOrUndefined ?? '';\n data = msgOrObj as Record<string, unknown>;\n }\n\n const entry = createEntry(levelNum, levelName, msg, data, error);\n\n // Emit events\n emitter.emit('log', entry);\n emitter.emit(`log:${levelName}` as keyof LogEvents, entry);\n\n if (shouldSync(levelName)) {\n // Sync write - truly blocking for critical logs\n writeToTransportsSync(entry);\n } else {\n // Async write\n writeToTransports(entry).catch((err) => {\n emitTransportError('logger', err, entry);\n });\n }\n }\n\n // Create the logger object\n const logger: Logger = {\n // Log methods with overloads\n trace(msgOrObj: string | object, msg?: string): void {\n log(LOG_LEVELS.trace as unknown as LogLevel, 'trace', msgOrObj, msg);\n },\n\n debug(msgOrObj: string | object, msg?: string): void {\n log(LOG_LEVELS.debug as unknown as LogLevel, 'debug', msgOrObj, msg);\n },\n\n info(msgOrObj: string | object, msg?: string): void {\n log(LOG_LEVELS.info as unknown as LogLevel, 'info', msgOrObj, msg);\n },\n\n warn(msgOrObj: string | object, msg?: string): void {\n log(LOG_LEVELS.warn as unknown as LogLevel, 'warn', msgOrObj, msg);\n },\n\n error(msgOrObj: string | object | Error, msg?: string): void {\n log(LOG_LEVELS.error as unknown as LogLevel, 'error', msgOrObj, msg);\n },\n\n fatal(msgOrObj: string | object | Error, msg?: string): void {\n log(LOG_LEVELS.fatal as unknown as LogLevel, 'fatal', msgOrObj, msg);\n },\n\n // Level management\n getLevel(): LogLevelName {\n const ctx = kernel.getContext();\n return LEVEL_NAMES[ctx.level] ?? 'info';\n },\n\n setLevel(newLevel: LogLevelName): void {\n if (!(newLevel in LOG_LEVELS)) {\n throw new ConfigError(`Invalid log level: ${newLevel}`, 'level');\n }\n const ctx = kernel.getContext();\n ctx.level = LOG_LEVELS[newLevel] as unknown as LogLevel;\n },\n\n isLevelEnabled(levelName: LogLevelName): boolean {\n return isEnabled(LOG_LEVELS[levelName] as unknown as LogLevel);\n },\n\n // Child logger\n child(bindings: Record<string, unknown>): Logger {\n const ctx = kernel.getContext();\n return createLogger({\n ...options,\n context: { ...ctx.bindings, ...bindings },\n transports: activeTransports,\n });\n },\n\n // Correlation\n withCorrelation(id?: string): Logger {\n const ctx = kernel.getContext();\n const correlationId = id ?? generateCorrelationId();\n const childLogger = createLogger({\n ...options,\n context: { ...ctx.bindings },\n transports: activeTransports,\n });\n // Set correlation ID on child's context\n const childCtx = (childLogger as unknown as { _getContext: () => LogContext })._getContext?.();\n if (childCtx) {\n childCtx.correlationId = correlationId;\n }\n return childLogger;\n },\n\n // Timing\n time(label: string): void {\n const ctx = kernel.getContext();\n ctx.timers.set(label, performance.now());\n },\n\n timeEnd(label: string): void {\n const ctx = kernel.getContext();\n const start = ctx.timers.get(label);\n if (start === undefined) {\n logger.warn(`Timer '${label}' does not exist`);\n return;\n }\n\n const duration = performance.now() - start;\n ctx.timers.delete(label);\n\n logger.debug({ label, duration }, `${label}: ${duration.toFixed(2)}ms`);\n },\n\n async timeAsync<T>(label: string, fn: () => Promise<T>): Promise<T> {\n const start = performance.now();\n try {\n return await fn();\n } finally {\n const duration = performance.now() - start;\n logger.debug({ label, duration }, `${label}: ${duration.toFixed(2)}ms`);\n }\n },\n\n startTimer(label: string): () => void {\n const start = performance.now();\n return () => {\n const duration = performance.now() - start;\n logger.debug({ label, duration }, `${label}: ${duration.toFixed(2)}ms`);\n };\n },\n\n // Plugin management\n use(plugin: Plugin<LogContext>): Logger {\n kernel.use(plugin);\n return logger;\n },\n\n unregister(pluginName: string): boolean {\n return kernel.unregister(pluginName);\n },\n\n hasPlugin(pluginName: string): boolean {\n return kernel.has(pluginName);\n },\n\n listPlugins(): Plugin<LogContext>[] {\n return kernel.list();\n },\n\n // Event handling\n on<K extends keyof LogEvents>(event: K, handler: (payload: LogEvents[K]) => void): Unsubscribe {\n return emitter.on(event, handler as (payload: LogEvents[K]) => void);\n },\n\n // Lifecycle\n async flush(): Promise<void> {\n const promises: Promise<void>[] = [];\n\n for (const transport of activeTransports) {\n if (transport.flush) {\n try {\n const result = transport.flush();\n if (result instanceof Promise) {\n promises.push(result.catch((err) => emitTransportError(transport.name, err)));\n }\n } catch (err) {\n emitTransportError(transport.name, err);\n }\n }\n }\n\n await Promise.all(promises);\n emitter.emit('flush', undefined as never);\n },\n\n async close(): Promise<void> {\n if (closed) return;\n closed = true;\n\n // Stop flush interval timer if running\n const ctx = kernel.getContext();\n if (ctx.flushTimerId) {\n clearInterval(ctx.flushTimerId);\n ctx.flushTimerId = undefined;\n }\n\n // Flush internal buffer if any entries are pending\n if (ctx.buffer && ctx.buffer.length > 0) {\n const bufferedEntries = ctx.buffer;\n ctx.buffer = [];\n\n // Write buffered entries synchronously to ensure they're not lost\n for (const entry of bufferedEntries) {\n for (const transport of activeTransports) {\n try {\n if (transport.writeSync) {\n transport.writeSync(entry);\n } else {\n const result = transport.write(entry);\n if (result instanceof Promise) {\n await result.catch((err) => emitTransportError(transport.name, err, entry));\n }\n }\n } catch (err) {\n emitTransportError(transport.name, err, entry);\n }\n }\n }\n }\n\n // Flush transport buffers\n await logger.flush();\n\n // Close transports\n const promises: Promise<void>[] = [];\n\n for (const transport of activeTransports) {\n if (transport.close) {\n try {\n const result = transport.close();\n if (result instanceof Promise) {\n promises.push(result.catch((err) => emitTransportError(transport.name, err)));\n }\n } catch (err) {\n emitTransportError(transport.name, err);\n }\n }\n }\n\n await Promise.all(promises);\n\n // Destroy kernel\n kernel.destroy();\n\n emitter.emit('close', undefined as never);\n },\n\n async destroy(): Promise<void> {\n return logger.close();\n },\n\n // Internal method for getting context\n _getContext(): LogContext {\n return kernel.getContext();\n },\n } as Logger & { _getContext(): LogContext };\n\n return logger;\n}\n\n/**\n * Resolve format option to concrete format.\n */\nfunction resolveFormat(format: Format): Format {\n if (format !== 'auto') {\n return format;\n }\n\n // Auto-detect based on environment\n if (isNode()) {\n // Use pretty for TTY, JSON otherwise\n return process.stdout?.isTTY ? 'pretty' : 'json';\n }\n\n // Browser - always pretty\n return 'pretty';\n}\n\n/**\n * Generate a unique correlation ID.\n */\nfunction generateCorrelationId(): string {\n // Simple UUID v4-like generation\n return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {\n const r = (Math.random() * 16) | 0;\n const v = c === 'x' ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n}\n\nexport default createLogger;\n","/**\n * @oxog/log - Type Definitions\n *\n * Core type definitions for the logging library.\n * Uses @oxog/types for Plugin and Kernel interfaces.\n *\n * @packageDocumentation\n */\n\nimport type { Plugin, MaybePromise } from '@oxog/types';\nimport type { Emitter } from '@oxog/emitter';\nimport type { Pigment } from '@oxog/pigment';\n\n// ============================================================================\n// Log Levels\n// ============================================================================\n\n/**\n * Log level numeric values for filtering.\n *\n * @example\n * ```typescript\n * import { LogLevel } from '@oxog/log';\n *\n * if (entry.level >= LogLevel.Error) {\n * alertTeam(entry);\n * }\n * ```\n */\nexport enum LogLevel {\n Trace = 10,\n Debug = 20,\n Info = 30,\n Warn = 40,\n Error = 50,\n Fatal = 60,\n}\n\n/**\n * Log level names as string literals.\n *\n * @example\n * ```typescript\n * const level: LogLevelName = 'info';\n * ```\n */\nexport type LogLevelName = 'trace' | 'debug' | 'info' | 'warn' | 'error' | 'fatal';\n\n/**\n * Output format options.\n *\n * - `'json'` - Structured JSON output (production)\n * - `'pretty'` - Human-readable colored output (development)\n * - `'auto'` - Auto-detect based on NODE_ENV and TTY\n *\n * @example\n * ```typescript\n * const log = createLogger({ format: 'pretty' });\n * ```\n */\nexport type Format = 'json' | 'pretty' | 'auto';\n\n// ============================================================================\n// Log Entry\n// ============================================================================\n\n/**\n * Structure of a log entry.\n *\n * @example\n * ```typescript\n * const entry: LogEntry = {\n * level: LogLevel.Info,\n * levelName: 'info',\n * time: Date.now(),\n * msg: 'User logged in',\n * userId: 123,\n * };\n * ```\n */\nexport interface LogEntry {\n /** Numeric log level value */\n level: LogLevel;\n\n /** Log level name */\n levelName: LogLevelName;\n\n /** Unix timestamp in milliseconds */\n time: number;\n\n /** Log message */\n msg: string;\n\n /** Additional data fields */\n [key: string]: unknown;\n\n // Optional standard fields\n /** Source file name (when source tracking enabled) */\n file?: string;\n\n /** Source line number (when source tracking enabled) */\n line?: number;\n\n /** Source column number (when source tracking enabled) */\n column?: number;\n\n /** Correlation ID for request tracing */\n correlationId?: string;\n\n /** Duration in milliseconds (for timing) */\n duration?: number;\n\n /** Error information */\n err?: {\n message: string;\n stack?: string;\n name: string;\n code?: string;\n };\n}\n\n// ============================================================================\n// Transport\n// ============================================================================\n\n/**\n * Transport interface for log output destinations.\n * Transports receive formatted log entries and write them to destinations.\n *\n * @example\n * ```typescript\n * const myTransport: Transport = {\n * name: 'my-transport',\n * write(entry) {\n * console.log(JSON.stringify(entry));\n * },\n * writeSync(entry) {\n * // Blocking write for critical logs\n * fs.writeFileSync('/var/log/app.log', JSON.stringify(entry) + '\\n', { flag: 'a' });\n * },\n * };\n * ```\n */\nexport interface Transport {\n /** Unique transport identifier */\n name: string;\n\n /**\n * Write a log entry to the destination.\n * Can be sync or async.\n */\n write(entry: LogEntry): MaybePromise<void>;\n\n /**\n * Write a log entry synchronously (blocking).\n * Used for fatal/error logs to ensure they are written before process exit.\n * Falls back to write() if not implemented.\n */\n writeSync?(entry: LogEntry): void;\n\n /**\n * Flush any buffered entries.\n * Called before shutdown or on manual flush.\n */\n flush?(): MaybePromise<void>;\n\n /**\n * Close the transport and cleanup resources.\n */\n close?(): MaybePromise<void>;\n\n /**\n * Check if transport supports the current environment.\n */\n supports?(env: 'node' | 'browser'): boolean;\n}\n\n// ============================================================================\n// Logger Options\n// ============================================================================\n\n/**\n * Buffer configuration for async logging.\n *\n * @example\n * ```typescript\n * const log = createLogger({\n * buffer: { size: 100, flushInterval: 1000 }\n * });\n * ```\n */\nexport interface BufferOptions {\n /** Maximum number of entries to buffer before flush */\n size?: number;\n\n /** Flush interval in milliseconds */\n flushInterval?: number;\n}\n\n/**\n * Logger configuration options.\n *\n * @example\n * ```typescript\n * const log = createLogger({\n * level: 'debug',\n * format: 'pretty',\n * colors: true,\n * timestamp: true,\n * redact: ['password', 'token'],\n * });\n * ```\n */\nexport interface LoggerOptions {\n /**\n * Logger name, included in all entries.\n * @default 'app'\n */\n name?: string;\n\n /**\n * Minimum log level to output.\n * @default 'info'\n */\n level?: LogLevelName;\n\n /**\n * Output format.\n * @default 'auto'\n */\n format?: Format;\n\n /**\n * Enable colored output (uses @oxog/pigment).\n * @default true\n */\n colors?: boolean;\n\n /**\n * Include ISO 8601 timestamp in entries.\n * @default true\n */\n timestamp?: boolean;\n\n /**\n * Include source file and line number.\n * @default false\n */\n source?: boolean;\n\n /**\n * Fields to redact from output.\n * Supports dot notation for nested paths.\n * @example ['password', 'user.token', 'headers.authorization']\n */\n redact?: string[];\n\n /**\n * Output transports.\n * @default [consoleTransport()]\n */\n transports?: Transport[];\n\n /**\n * Additional plugins to load.\n */\n plugins?: Plugin<LogContext>[];\n\n /**\n * Sync/async mode per level.\n * Sync mode ensures log is written before continuing.\n * @default { fatal: true, error: true }\n */\n sync?: Partial<Record<LogLevelName, boolean>>;\n\n /**\n * Buffer configuration for async logging.\n */\n buffer?: BufferOptions;\n\n /**\n * Static context added to all entries.\n */\n context?: Record<string, unknown>;\n}\n\n// ============================================================================\n// Log Context\n// ============================================================================\n\n/**\n * Log context shared between plugins.\n * This is the kernel context type for @oxog/plugin.\n */\nexport interface LogContext {\n /** Logger name */\n name: string;\n\n /** Current minimum log level */\n level: LogLevel;\n\n /** Output format */\n format: Format;\n\n /** Colors enabled */\n colors: boolean;\n\n /** Timestamp enabled */\n timestamp: boolean;\n\n /** Source tracking enabled */\n source: boolean;\n\n /** Registered transports */\n transports: Transport[];\n\n /** Fields to redact */\n redactPaths: string[];\n\n /** Bound context (from child loggers) */\n bindings: Record<string, unknown>;\n\n /** Correlation ID (if set) */\n correlationId?: string;\n\n /** Pigment instance for colors */\n pigment: Pigment;\n\n /** Event emitter for log events */\n emitter: Emitter<LogEvents>;\n\n /** Sync settings per level */\n syncLevels: Record<LogLevelName, boolean>;\n\n /** Buffer settings */\n bufferOptions: BufferOptions;\n\n /** Active timers for timing plugin */\n timers: Map<string, number>;\n\n /** Buffered entries for async logging */\n buffer: LogEntry[];\n\n /** Flush interval timer ID */\n flushTimerId?: ReturnType<typeof setInterval>;\n}\n\n// ============================================================================\n// Log Events\n// ============================================================================\n\n/**\n * Transport error payload for error events.\n */\nexport interface TransportErrorPayload {\n /** Transport name that failed */\n transport: string;\n /** The error that occurred */\n error: Error;\n /** The log entry that failed to write (if available) */\n entry?: LogEntry;\n}\n\n/**\n * Log events for subscription via @oxog/emitter.\n *\n * @example\n * ```typescript\n * log.on('log:error', (entry) => {\n * alertTeam(entry);\n * });\n *\n * // Listen for transport errors\n * log.on('error', ({ transport, error }) => {\n * console.error(`Transport ${transport} failed:`, error);\n * });\n * ```\n */\nexport interface LogEvents {\n /** Index signature for EventMap compatibility */\n [key: string]: unknown;\n\n /** Emitted for every log entry */\n log: LogEntry;\n\n /** Emitted for trace level logs */\n 'log:trace': LogEntry;\n\n /** Emitted for debug level logs */\n 'log:debug': LogEntry;\n\n /** Emitted for info level logs */\n 'log:info': LogEntry;\n\n /** Emitted for warn level logs */\n 'log:warn': LogEntry;\n\n /** Emitted for error level logs */\n 'log:error': LogEntry;\n\n /** Emitted for fatal level logs */\n 'log:fatal': LogEntry;\n\n /** Emitted when buffer is flushed */\n flush: void;\n\n /** Emitted when logger is closed */\n close: void;\n\n /** Emitted when a transport fails to write */\n error: TransportErrorPayload;\n}\n\n/**\n * Unsubscribe function returned by event subscription.\n */\nexport type Unsubscribe = () => void;\n\n// ============================================================================\n// Logger Interface\n// ============================================================================\n\n/**\n * Logger instance interface.\n * Provides logging methods, child loggers, and lifecycle management.\n *\n * @example\n * ```typescript\n * const log = createLogger();\n *\n * log.info('Server started');\n * log.info({ port: 3000 }, 'Listening');\n *\n * const dbLog = log.child({ module: 'database' });\n * dbLog.debug('Connected');\n *\n * await log.flush();\n * await log.close();\n * ```\n */\nexport interface Logger {\n // ─────────────────────────────────────────────────────────────────────────\n // Logging Methods\n // ─────────────────────────────────────────────────────────────────────────\n\n /**\n * Log at TRACE level (10).\n * Most verbose, for detailed debugging.\n */\n trace(msg: string): void;\n trace(obj: object, msg?: string): void;\n\n /**\n * Log at DEBUG level (20).\n * Debug information for developers.\n */\n debug(msg: string): void;\n debug(obj: object, msg?: string): void;\n\n /**\n * Log at INFO level (30).\n * General informational messages.\n */\n info(msg: string): void;\n info(obj: object, msg?: string): void;\n\n /**\n * Log at WARN level (40).\n * Warning conditions.\n */\n warn(msg: string): void;\n warn(obj: object, msg?: string): void;\n\n /**\n * Log at ERROR level (50).\n * Error conditions.\n */\n error(msg: string): void;\n error(obj: object, msg?: string): void;\n error(err: Error, msg?: string): void;\n\n /**\n * Log at FATAL level (60).\n * System is unusable.\n */\n fatal(msg: string): void;\n fatal(obj: object, msg?: string): void;\n fatal(err: Error, msg?: string): void;\n\n // ─────────────────────────────────────────────────────────────────────────\n // Child Loggers\n // ─────────────────────────────────────────────────────────────────────────\n\n /**\n * Create a child logger with bound context.\n * Child context is merged with parent context.\n *\n * @example\n * ```typescript\n * const dbLog = log.child({ module: 'database' });\n * dbLog.info('Connected'); // includes { module: 'database' }\n * ```\n */\n child(bindings: Record<string, unknown>): Logger;\n\n /**\n * Create a child logger with correlation ID.\n * Useful for request tracing.\n *\n * @example\n * ```typescript\n * const reqLog = log.withCorrelation('req-123');\n * reqLog.info('Request received');\n * ```\n */\n withCorrelation(id?: string): Logger;\n\n // ─────────────────────────────────────────────────────────────────────────\n // Timing\n // ─────────────────────────────────────────────────────────────────────────\n\n /**\n * Start a timer with the given label.\n *\n * @example\n * ```typescript\n * log.time('db-query');\n * await db.query('SELECT * FROM users');\n * log.timeEnd('db-query'); // logs duration\n * ```\n */\n time(label: string): void;\n\n /**\n * End a timer and log the duration.\n */\n timeEnd(label: string): void;\n\n /**\n * Time an async operation.\n *\n * @example\n * ```typescript\n * const result = await log.timeAsync('api-call', async () => {\n * return await fetch('/api/data');\n * });\n * ```\n */\n timeAsync<T>(label: string, fn: () => Promise<T>): Promise<T>;\n\n /**\n * Start a timer and return a stop function.\n *\n * @example\n * ```typescript\n * const stop = log.startTimer('process');\n * await doWork();\n * stop(); // logs duration\n * ```\n */\n startTimer(label: string): () => void;\n\n // ─────────────────────────────────────────────────────────────────────────\n // Events\n // ─────────────────────────────────────────────────────────────────────────\n\n /**\n * Subscribe to log events.\n *\n * @example\n * ```typescript\n * const unsub = log.on('log:error', (entry) => {\n * alertTeam(entry);\n * });\n *\n * // Later: unsub();\n * ```\n */\n on<K extends keyof LogEvents>(\n event: K,\n handler: (payload: LogEvents[K]) => void\n ): Unsubscribe;\n\n // ─────────────────────────────────────────────────────────────────────────\n // Plugin Management\n // ─────────────────────────────────────────────────────────────────────────\n\n /**\n * Register a plugin.\n */\n use(plugin: Plugin<LogContext>): this;\n\n /**\n * Unregister a plugin by name.\n */\n unregister(name: string): boolean;\n\n /**\n * Check if a plugin is registered.\n */\n hasPlugin(name: string): boolean;\n\n /**\n * List all registered plugins.\n */\n listPlugins(): Plugin<LogContext>[];\n\n // ─────────────────────────────────────────────────────────────────────────\n // Level Management\n // ─────────────────────────────────────────────────────────────────────────\n\n /**\n * Set the minimum log level.\n */\n setLevel(level: LogLevelName): void;\n\n /**\n * Get the current minimum log level.\n */\n getLevel(): LogLevelName;\n\n /**\n * Check if a level is enabled.\n */\n isLevelEnabled(level: LogLevelName): boolean;\n\n // ─────────────────────────────────────────────────────────────────────────\n // Lifecycle\n // ─────────────────────────────────────────────────────────────────────────\n\n /**\n * Flush all buffered entries.\n */\n flush(): Promise<void>;\n\n /**\n * Close the logger and cleanup resources.\n */\n close(): Promise<void>;\n\n /**\n * Alias for close().\n */\n destroy(): Promise<void>;\n}\n\n// ============================================================================\n// Transport Options\n// ============================================================================\n\n/**\n * Console transport options.\n */\nexport interface ConsoleTransportOptions {\n /** Enable colors */\n colors?: boolean;\n\n /** Show timestamp */\n timestamp?: boolean;\n\n /** Custom level colors */\n levelColors?: Partial<Record<LogLevelName, string>>;\n}\n\n/**\n * File transport options.\n */\nexport interface FileTransportOptions {\n /** File path */\n path: string;\n\n /** Rotation interval ('1d', '1h', etc.) */\n rotate?: string;\n\n /** Max file size ('10MB', '1GB', etc.) */\n maxSize?: string;\n\n /** Max number of files to keep */\n maxFiles?: number;\n\n /** Compress rotated files */\n compress?: boolean;\n}\n\n/**\n * HTTP transport options.\n */\nexport interface HttpTransportOptions {\n /** Endpoint URL */\n url: string;\n\n /** HTTP method */\n method?: 'POST' | 'PUT';\n\n /** Custom headers */\n headers?: Record<string, string>;\n\n /** Batch size before sending */\n batch?: number;\n\n /** Flush interval in milliseconds */\n interval?: number;\n\n /** Retry attempts on failure */\n retry?: number;\n}\n\n/**\n * Stream transport options.\n */\nexport interface StreamTransportOptions {\n /** Node.js writable stream */\n stream: NodeJS.WritableStream;\n}\n\n/**\n * LocalStorage transport options (browser only).\n */\nexport interface LocalStorageTransportOptions {\n /** Storage key prefix */\n key: string;\n\n /** Max storage size ('1MB', etc.) */\n maxSize?: string;\n\n /** Only store these levels */\n levels?: LogLevelName[];\n}\n","/**\n * @oxog/log - Constants\n *\n * Log levels, default values, and configuration constants.\n *\n * @packageDocumentation\n */\n\nimport { LogLevel, type LogLevelName, type Format, type BufferOptions } from './types.js';\n\n// ============================================================================\n// Log Levels\n// ============================================================================\n\n/**\n * Mapping of log level names to numeric values.\n *\n * @example\n * ```typescript\n * const level = LOG_LEVELS.info; // 30\n * ```\n */\nexport const LOG_LEVELS: Record<LogLevelName, LogLevel> = {\n trace: LogLevel.Trace,\n debug: LogLevel.Debug,\n info: LogLevel.Info,\n warn: LogLevel.Warn,\n error: LogLevel.Error,\n fatal: LogLevel.Fatal,\n} as const;\n\n/**\n * Mapping of numeric values to log level names.\n *\n * @example\n * ```typescript\n * const name = LEVEL_NAMES[30]; // 'info'\n * ```\n */\nexport const LEVEL_NAMES: Record<LogLevel, LogLevelName> = {\n [LogLevel.Trace]: 'trace',\n [LogLevel.Debug]: 'debug',\n [LogLevel.Info]: 'info',\n [LogLevel.Warn]: 'warn',\n [LogLevel.Error]: 'error',\n [LogLevel.Fatal]: 'fatal',\n} as const;\n\n/**\n * Array of all log level names in order of severity.\n */\nexport const LEVEL_ORDER: LogLevelName[] = [\n 'trace',\n 'debug',\n 'info',\n 'warn',\n 'error',\n 'fatal',\n] as const;\n\n// ============================================================================\n// Default Configuration\n// ============================================================================\n\n/**\n * Default logger name.\n */\nexport const DEFAULT_NAME = 'app';\n\n/**\n * Default log level.\n */\nexport const DEFAULT_LEVEL: LogLevelName = 'info';\n\n/**\n * Default output format.\n */\nexport const DEFAULT_FORMAT: Format = 'auto';\n\n/**\n * Default colors setting.\n */\nexport const DEFAULT_COLORS = true;\n\n/**\n * Default timestamp setting.\n */\nexport const DEFAULT_TIMESTAMP = true;\n\n/**\n * Default source tracking setting.\n */\nexport const DEFAULT_SOURCE = false;\n\n/**\n * Default sync levels (fatal and error are sync by default).\n */\nexport const DEFAULT_SYNC_LEVELS: Record<LogLevelName, boolean> = {\n trace: false,\n debug: false,\n info: false,\n warn: false,\n error: true,\n fatal: true,\n} as const;\n\n/**\n * Default buffer options.\n */\nexport const DEFAULT_BUFFER_OPTIONS: Required<BufferOptions> = {\n size: 100,\n flushInterval: 1000,\n} as const;\n\n// ============================================================================\n// Level Colors\n// ============================================================================\n\n/**\n * Default colors for each log level (used with @oxog/pigment).\n */\nexport const LEVEL_COLORS: Record<LogLevelName, string> = {\n trace: 'gray',\n debug: 'cyan',\n info: 'blue',\n warn: 'yellow',\n error: 'red',\n fatal: 'magenta',\n} as const;\n\n/**\n * Level label display strings (padded for alignment).\n */\nexport const LEVEL_LABELS: Record<LogLevelName, string> = {\n trace: 'TRACE',\n debug: 'DEBUG',\n info: 'INFO ',\n warn: 'WARN ',\n error: 'ERROR',\n fatal: 'FATAL',\n} as const;\n\n// ============================================================================\n// Redaction\n// ============================================================================\n\n/**\n * Default redaction placeholder.\n */\nexport const REDACTED_VALUE = '[REDACTED]';\n\n/**\n * Common sensitive field names.\n */\nexport const COMMON_SENSITIVE_FIELDS = [\n 'password',\n 'token',\n 'secret',\n 'apiKey',\n 'api_key',\n 'apikey',\n 'authorization',\n 'auth',\n 'credential',\n 'credentials',\n 'ssn',\n 'creditCard',\n 'credit_card',\n 'creditcard',\n 'cvv',\n 'pin',\n] as const;\n\n// ============================================================================\n// Size Constants\n// ============================================================================\n\n/**\n * Parse size string to bytes.\n *\n * @example\n * ```typescript\n * parseSize('10MB'); // 10485760\n * parseSize('1GB'); // 1073741824\n * ```\n */\nexport function parseSize(size: string): number {\n const match = size.match(/^(\\d+(?:\\.\\d+)?)\\s*(B|KB|MB|GB|TB)?$/i);\n if (!match) {\n throw new Error(`Invalid size format: ${size}`);\n }\n\n const value = parseFloat(match[1]!);\n const unit = (match[2] || 'B').toUpperCase();\n\n const units: Record<string, number> = {\n B: 1,\n KB: 1024,\n MB: 1024 * 1024,\n GB: 1024 * 1024 * 1024,\n TB: 1024 * 1024 * 1024 * 1024,\n };\n\n return Math.floor(value * (units[unit] ?? 1));\n}\n\n/**\n * Parse rotation interval string to milliseconds.\n *\n * @example\n * ```typescript\n * parseRotation('1d'); // 86400000\n * parseRotation('1h'); // 3600000\n * ```\n */\nexport function parseRotation(rotation: string): number {\n const match = rotation.match(/^(\\d+)\\s*(s|m|h|d|w)?$/i);\n if (!match) {\n throw new Error(`Invalid rotation format: ${rotation}`);\n }\n\n const value = parseInt(match[1]!, 10);\n const unit = (match[2] || 's').toLowerCase();\n\n const units: Record<string, number> = {\n s: 1000,\n m: 60 * 1000,\n h: 60 * 60 * 1000,\n d: 24 * 60 * 60 * 1000,\n w: 7 * 24 * 60 * 60 * 1000,\n };\n\n return value * (units[unit] ?? 1000);\n}\n\n// ============================================================================\n// Environment\n// ============================================================================\n\n/**\n * Check if running in Node.js.\n */\nexport const IS_NODE =\n typeof process !== 'undefined' &&\n process.versions != null &&\n process.versions.node != null;\n\n/**\n * Check if running in browser.\n */\nexport const IS_BROWSER =\n typeof window !== 'undefined' && typeof window.document !== 'undefined';\n\n/**\n * Check if running in development mode.\n */\nexport const IS_DEV =\n IS_NODE && process.env['NODE_ENV'] !== 'production';\n\n/**\n * Check if stdout is a TTY (terminal).\n */\nexport const IS_TTY = IS_NODE && process.stdout?.isTTY === true;\n","/**\n * @oxog/log - Environment Detection Utilities\n *\n * Detect runtime environment and capabilities.\n *\n * @packageDocumentation\n */\n\n/**\n * Check if running in Node.js environment.\n *\n * @example\n * ```typescript\n * if (isNode()) {\n * // Use Node.js APIs\n * }\n * ```\n */\nexport function isNode(): boolean {\n return (\n typeof process !== 'undefined' &&\n process.versions != null &&\n process.versions.node != null\n );\n}\n\n/**\n * Check if running in browser environment.\n *\n * @example\n * ```typescript\n * if (isBrowser()) {\n * // Use browser APIs\n * }\n * ```\n */\nexport function isBrowser(): boolean {\n return typeof window !== 'undefined' && typeof window.document !== 'undefined';\n}\n\n/**\n * Check if running in development mode.\n * Returns true if NODE_ENV is not 'production'.\n *\n * @example\n * ```typescript\n * if (isDev()) {\n * log.setLevel('debug');\n * }\n * ```\n */\nexport function isDev(): boolean {\n if (!isNode()) return false;\n return process.env['NODE_ENV'] !== 'production';\n}\n\n/**\n * Check if stdout is a TTY (terminal).\n *\n * @example\n * ```typescript\n * if (isTTY()) {\n * // Use colors\n * }\n * ```\n */\nexport function isTTY(): boolean {\n if (!isNode()) return false;\n return process.stdout?.isTTY === true;\n}\n\n/**\n * Check if colors should be enabled by default.\n * Returns true if running in TTY or browser.\n *\n * @example\n * ```typescript\n * const colors = shouldUseColors();\n * ```\n */\nexport function shouldUseColors(): boolean {\n if (isBrowser()) return true;\n if (!isNode()) return false;\n\n // Check for NO_COLOR environment variable\n if (process.env['NO_COLOR'] !== undefined) return false;\n\n // Check for FORCE_COLOR environment variable\n if (process.env['FORCE_COLOR'] !== undefined) return true;\n\n // Check if running in CI\n if (process.env['CI'] !== undefined) return true;\n\n // Default to TTY detection\n return isTTY();\n}\n\n/**\n * Get the current environment name.\n *\n * @example\n * ```typescript\n * const env = getEnvironment(); // 'development' | 'production' | 'test'\n * ```\n */\nexport function getEnvironment(): string {\n if (!isNode()) return 'browser';\n return process.env['NODE_ENV'] || 'development';\n}\n\n/**\n * Get the current working directory.\n * Returns undefined in browser.\n *\n * @example\n * ```typescript\n * const cwd = getCwd(); // '/path/to/project'\n * ```\n */\nexport function getCwd(): string | undefined {\n if (!isNode()) return undefined;\n return process.cwd();\n}\n\n/**\n * Get a safe reference to globalThis.\n */\nexport function getGlobalThis(): typeof globalThis {\n if (typeof globalThis !== 'undefined') return globalThis;\n if (typeof window !== 'undefined') return window as unknown as typeof globalThis;\n if (typeof global !== 'undefined') return global as unknown as typeof globalThis;\n if (typeof self !== 'undefined') return self as unknown as typeof globalThis;\n return {} as typeof globalThis;\n}\n","/**\n * @oxog/log - Formatting Utilities\n *\n * JSON and pretty formatting for log entries.\n *\n * @packageDocumentation\n */\n\nimport type { LogEntry, LogLevelName } from '../types.js';\nimport { LEVEL_LABELS, LEVEL_COLORS } from '../constants.js';\nimport type { Pigment } from '@oxog/pigment';\n\n/**\n * Format a log entry as JSON string.\n * Uses safe stringify to handle circular references.\n *\n * @example\n * ```typescript\n * const json = formatJson(entry);\n * // {\"level\":30,\"time\":1234567890,\"msg\":\"Hello\"}\n * ```\n */\nexport function formatJson(entry: LogEntry): string {\n // Use safeStringify to handle circular references\n return safeStringify(entry);\n}\n\n/**\n * JSON replacer function to handle special values.\n */\nfunction jsonReplacer(_key: string, value: unknown): unknown {\n // Handle BigInt\n if (typeof value === 'bigint') {\n return value.toString();\n }\n\n // Handle Error objects\n if (value instanceof Error) {\n const errorObj = value as Error & Record<string, unknown>;\n const result: Record<string, unknown> = {\n name: value.name,\n message: value.message,\n stack: value.stack,\n };\n // Copy any additional enumerable properties\n for (const key of Object.keys(errorObj)) {\n if (!(key in result)) {\n result[key] = errorObj[key];\n }\n }\n return result;\n }\n\n // Handle circular references and special objects\n if (typeof value === 'object' && value !== null) {\n // Handle RegExp\n if (value instanceof RegExp) {\n return value.toString();\n }\n\n // Handle Date (already handled by JSON.stringify, but explicit for clarity)\n if (value instanceof Date) {\n return value.toISOString();\n }\n\n // Handle Map\n if (value instanceof Map) {\n return Object.fromEntries(value);\n }\n\n // Handle Set\n if (value instanceof Set) {\n return Array.from(value);\n }\n }\n\n return value;\n}\n\n/**\n * Safe JSON stringify with circular reference handling.\n *\n * @example\n * ```typescript\n * const obj = { a: 1 };\n * obj.self = obj; // circular\n * safeStringify(obj); // {\"a\":1,\"self\":\"[Circular]\"}\n * ```\n */\nexport function safeStringify(value: unknown, indent?: number): string {\n const seen = new WeakSet<object>();\n\n return JSON.stringify(\n value,\n (_key, val) => {\n // First apply the standard replacer\n const replaced = jsonReplacer(_key, val);\n\n // Then check for circular references\n if (typeof replaced === 'object' && replaced !== null) {\n if (seen.has(replaced)) {\n return '[Circular]';\n }\n seen.add(replaced);\n }\n\n return replaced;\n },\n indent\n );\n}\n\n/**\n * Format a log entry as pretty string with colors.\n *\n * @example\n * ```typescript\n * const pretty = formatPretty(entry, pigment);\n * // [14:30:22] INFO Hello world\n * ```\n */\nexport function formatPretty(\n entry: LogEntry,\n pigment?: Pigment,\n options: { timestamp?: boolean; source?: boolean } = {}\n): string {\n const parts: string[] = [];\n const { timestamp = true, source = true } = options;\n\n // Timestamp\n if (timestamp && entry.time) {\n const time = formatTime(entry.time);\n parts.push(pigment ? pigment.gray(`[${time}]`) : `[${time}]`);\n }\n\n // Level\n const levelLabel = LEVEL_LABELS[entry.levelName] || entry.levelName.toUpperCase();\n const levelColor = LEVEL_COLORS[entry.levelName] || 'white';\n\n if (pigment) {\n const colorFn = (pigment as unknown as Record<string, (s: string) => string>)[levelColor];\n parts.push(colorFn ? colorFn(levelLabel) : levelLabel);\n } else {\n parts.push(levelLabel);\n }\n\n // Source location\n if (source && entry.file) {\n const location = entry.line ? `${entry.file}:${entry.line}` : entry.file;\n parts.push(pigment ? pigment.dim(`(${location})`) : `(${location})`);\n }\n\n // Message\n if (entry.msg) {\n parts.push(entry.msg);\n }\n\n // Extra data (excluding standard fields)\n const extra = getExtraFields(entry);\n if (Object.keys(extra).length > 0) {\n const extraStr = safeStringify(extra);\n parts.push(pigment ? pigment.dim(extraStr) : extraStr);\n }\n\n // Error stack\n if (entry.err?.stack) {\n parts.push('\\n' + (pigment ? pigment.red(entry.err.stack) : entry.err.stack));\n }\n\n return parts.join(' ');\n}\n\n/**\n * Get extra fields from entry (excluding standard fields).\n */\nfunction getExtraFields(entry: LogEntry): Record<string, unknown> {\n const standardFields = new Set([\n 'level',\n 'levelName',\n 'time',\n 'msg',\n 'file',\n 'line',\n 'column',\n 'correlationId',\n 'duration',\n 'err',\n 'name',\n ]);\n\n const extra: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(entry)) {\n if (!standardFields.has(key)) {\n extra[key] = value;\n }\n }\n return extra;\n}\n\n/**\n * Format timestamp as HH:MM:SS.\n */\nexport function formatTime(timestamp: number): string {\n const date = new Date(timestamp);\n const hours = date.getHours().toString().padStart(2, '0');\n const minutes = date.getMinutes().toString().padStart(2, '0');\n const seconds = date.getSeconds().toString().padStart(2, '0');\n return `${hours}:${minutes}:${seconds}`;\n}\n\n/**\n * Format timestamp as ISO 8601 string.\n */\nexport function formatIso(timestamp: number): string {\n return new Date(timestamp).toISOString();\n}\n\n/**\n * Format duration in human-readable format.\n *\n * @example\n * ```typescript\n * formatDuration(45); // '45ms'\n * formatDuration(1500); // '1.50s'\n * formatDuration(90000); // '1m 30s'\n * ```\n */\nexport function formatDuration(ms: number): string {\n if (ms < 1000) {\n return `${ms}ms`;\n }\n\n if (ms < 60000) {\n return `${(ms / 1000).toFixed(2)}s`;\n }\n\n const minutes = Math.floor(ms / 60000);\n const seconds = Math.round((ms % 60000) / 1000);\n return `${minutes}m ${seconds}s`;\n}\n\n/**\n * Format bytes in human-readable format.\n *\n * @example\n * ```typescript\n * formatBytes(1024); // '1 KB'\n * formatBytes(1048576); // '1 MB'\n * ```\n */\nexport function formatBytes(bytes: number): string {\n const units = ['B', 'KB', 'MB', 'GB', 'TB'];\n let unitIndex = 0;\n let value = bytes;\n\n while (value >= 1024 && unitIndex < units.length - 1) {\n value /= 1024;\n unitIndex++;\n }\n\n return `${value.toFixed(unitIndex > 0 ? 2 : 0)} ${units[unitIndex]}`;\n}\n\n/**\n * Truncate a string to a maximum length.\n *\n * @example\n * ```typescript\n * truncate('Hello world', 8); // 'Hello...'\n * ```\n */\nexport function truncate(str: string, maxLength: number, suffix = '...'): string {\n if (str.length <= maxLength) return str;\n return str.slice(0, maxLength - suffix.length) + suffix;\n}\n\n/**\n * Indent a multi-line string.\n */\nexport function indent(str: string, spaces = 2): string {\n const pad = ' '.repeat(spaces);\n return str\n .split('\\n')\n .map((line) => pad + line)\n .join('\\n');\n}\n","/**\n * @oxog/log - Console Transport\n *\n * Output logs to console with optional colors.\n *\n * @packageDocumentation\n */\n\nimport type { Transport, LogEntry, ConsoleTransportOptions, LogLevelName } from '../types.js';\nimport { formatJson, formatPretty } from '../utils/format.js';\nimport { isBrowser, isTTY, shouldUseColors } from '../utils/env.js';\nimport type { Pigment } from '@oxog/pigment';\n\n/**\n * Default level colors for console output.\n */\nconst DEFAULT_LEVEL_COLORS: Record<LogLevelName, string> = {\n trace: 'gray',\n debug: 'cyan',\n info: 'blue',\n warn: 'yellow',\n error: 'red',\n fatal: 'magenta',\n};\n\n/**\n * Create a console transport.\n *\n * @example\n * ```typescript\n * import { consoleTransport } from '@oxog/log/transports';\n *\n * const transport = consoleTransport({ colors: true });\n * ```\n */\nexport function consoleTransport(options: ConsoleTransportOptions = {}): Transport {\n const {\n colors = shouldUseColors(),\n timestamp = true,\n levelColors = {},\n } = options;\n\n // Merge level colors\n const mergedColors = { ...DEFAULT_LEVEL_COLORS, ...levelColors };\n\n // Store pigment instance (set by logger)\n let pigment: Pigment | undefined;\n\n // Format entry for Node.js output\n function formatEntry(entry: LogEntry): string {\n if (colors && pigment) {\n return formatPretty(entry, pigment, { timestamp, source: true });\n } else if (colors) {\n return formatWithAnsi(entry, mergedColors, timestamp);\n } else {\n return formatJson(entry);\n }\n }\n\n return {\n name: 'console',\n\n write(entry: LogEntry): void {\n if (isBrowser()) {\n // In browser, use console methods directly\n writeToBrowserConsole(entry, colors);\n return;\n }\n\n // In Node.js, format and write to stdout/stderr\n const output = formatEntry(entry);\n\n // Write to appropriate stream\n if (entry.level >= 50) {\n // Error and Fatal to stderr\n process.stderr.write(output + '\\n');\n } else {\n process.stdout.write(output + '\\n');\n }\n },\n\n writeSync(entry: LogEntry): void {\n if (isBrowser()) {\n // Browser console is inherently synchronous\n writeToBrowserConsole(entry, colors);\n return;\n }\n\n // In Node.js, use synchronous file descriptor writes for true blocking\n const output = formatEntry(entry) + '\\n';\n const fd = entry.level >= 50 ? 2 : 1; // 2 = stderr, 1 = stdout\n\n try {\n // Dynamic import of fs would be async, so we use process.stdout/stderr\n // which are synchronous when writing to a TTY or when piped\n if (entry.level >= 50) {\n process.stderr.write(output);\n } else {\n process.stdout.write(output);\n }\n\n // Note: process.stdout.write is actually synchronous when:\n // 1. Writing to a TTY (terminal)\n // 2. The internal buffer is not full\n // For truly blocking writes to files, use fs.writeFileSync\n } catch {\n // If write fails, there's not much we can do in sync mode\n // The error will be visible if stderr is available\n }\n },\n\n flush(): void {\n // Console doesn't need flushing\n },\n\n close(): void {\n // Console doesn't need closing\n },\n\n supports(env: 'node' | 'browser'): boolean {\n return true; // Works in both environments\n },\n };\n}\n\n/**\n * Format entry with ANSI colors (without pigment).\n */\nfunction formatWithAnsi(\n entry: LogEntry,\n levelColors: Record<LogLevelName, string>,\n showTimestamp: boolean\n): string {\n const parts: string[] = [];\n\n // Timestamp\n if (showTimestamp && entry.time) {\n const time = formatTime(entry.time);\n parts.push(`\\x1b[90m[${time}]\\x1b[0m`);\n }\n\n // Level with color\n const color = getAnsiColor(levelColors[entry.levelName] || 'white');\n const levelLabel = entry.levelName.toUpperCase().padEnd(5);\n parts.push(`${color}${levelLabel}\\x1b[0m`);\n\n // Source location\n if (entry.file) {\n const location = entry.line ? `${entry.file}:${entry.line}` : entry.file;\n parts.push(`\\x1b[90m(${location})\\x1b[0m`);\n }\n\n // Message\n if (entry.msg) {\n parts.push(entry.msg);\n }\n\n // Extra data\n const extra = getExtraFields(entry);\n if (Object.keys(extra).length > 0) {\n parts.push(`\\x1b[90m${JSON.stringify(extra)}\\x1b[0m`);\n }\n\n // Error stack\n if (entry.err?.stack) {\n parts.push('\\n\\x1b[31m' + entry.err.stack + '\\x1b[0m');\n }\n\n return parts.join(' ');\n}\n\n/**\n * Get ANSI color code for a color name.\n */\nfunction getAnsiColor(colorName: string): string {\n const colors: Record<string, string> = {\n black: '\\x1b[30m',\n red: '\\x1b[31m',\n green: '\\x1b[32m',\n yellow: '\\x1b[33m',\n blue: '\\x1b[34m',\n magenta: '\\x1b[35m',\n cyan: '\\x1b[36m',\n white: '\\x1b[37m',\n gray: '\\x1b[90m',\n grey: '\\x1b[90m',\n };\n return colors[colorName] || '\\x1b[0m';\n}\n\n/**\n * Format timestamp as HH:MM:SS.\n */\nfunction formatTime(timestamp: number): string {\n const date = new Date(timestamp);\n return date.toTimeString().slice(0, 8);\n}\n\n/**\n * Get extra fields from entry (excluding standard fields).\n */\nfunction getExtraFields(entry: LogEntry): Record<string, unknown> {\n const standardFields = new Set([\n 'level',\n 'levelName',\n 'time',\n 'msg',\n 'file',\n 'line',\n 'column',\n 'correlationId',\n 'duration',\n 'err',\n 'name',\n ]);\n\n const extra: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(entry)) {\n if (!standardFields.has(key)) {\n extra[key] = value;\n }\n }\n return extra;\n}\n\n/**\n * Write to browser console with styling.\n */\nfunction writeToBrowserConsole(entry: LogEntry, styled: boolean): void {\n const method = getConsoleMethod(entry.levelName);\n const consoleObj = console as unknown as Record<string, (...args: unknown[]) => void>;\n\n if (styled) {\n const styles = getBrowserStyles(entry.levelName);\n const label = `%c[${entry.levelName.toUpperCase()}]`;\n\n const extra = getExtraFields(entry);\n if (Object.keys(extra).length > 0) {\n consoleObj[method](label, styles, entry.msg, extra);\n } else {\n consoleObj[method](label, styles, entry.msg);\n }\n } else {\n consoleObj[method](`[${entry.levelName.toUpperCase()}]`, entry.msg, entry);\n }\n}\n\n/**\n * Get console method for level.\n */\nfunction getConsoleMethod(levelName: LogLevelName): string {\n switch (levelName) {\n case 'trace':\n case 'debug':\n return 'debug';\n case 'info':\n return 'info';\n case 'warn':\n return 'warn';\n case 'error':\n case 'fatal':\n return 'error';\n default:\n return 'log';\n }\n}\n\n/**\n * Get browser CSS styles for level.\n */\nfunction getBrowserStyles(levelName: LogLevelName): string {\n const colors: Record<LogLevelName, string> = {\n trace: '#888888',\n debug: '#00bcd4',\n info: '#2196f3',\n warn: '#ff9800',\n error: '#f44336',\n fatal: '#9c27b0',\n };\n return `color: ${colors[levelName]}; font-weight: bold;`;\n}\n\nexport default consoleTransport;\n","/**\n * @oxog/log - Level Plugin\n *\n * Manages log level filtering and configuration.\n *\n * @packageDocumentation\n */\n\nimport type { Plugin } from '@oxog/types';\nimport type { LogContext, LogLevelName } from '../../types.js';\nimport { LOG_LEVELS, LEVEL_NAMES } from '../../constants.js';\n\n/**\n * Level plugin for log level management.\n *\n * This plugin:\n * - Filters log entries by level\n * - Provides level checking utilities\n * - Allows runtime level changes\n *\n * @example\n * ```typescript\n * import { levelPlugin } from '@oxog/log/plugins';\n *\n * logger.use(levelPlugin());\n *\n * // Only logs at or above 'warn' level will be processed\n * logger.setLevel('warn');\n * ```\n */\nexport function levelPlugin(): Plugin<LogContext> {\n return {\n name: 'level',\n version: '1.0.0',\n\n install(kernel) {\n const ctx = kernel.getContext();\n\n // Ensure level is set\n if (ctx.level === undefined) {\n ctx.level = LOG_LEVELS.info;\n }\n },\n };\n}\n\n/**\n * Check if a log level is enabled.\n *\n * @example\n * ```typescript\n * if (isLevelEnabled(context, 'debug')) {\n * // Process debug log\n * }\n * ```\n */\nexport function isLevelEnabled(ctx: LogContext, levelName: LogLevelName): boolean {\n const levelValue = LOG_LEVELS[levelName];\n return levelValue >= ctx.level;\n}\n\n/**\n * Get the current level name from context.\n */\nexport function getLevelName(ctx: LogContext): LogLevelName {\n return LEVEL_NAMES[ctx.level] ?? 'info';\n}\n\n/**\n * Set the log level on context.\n */\nexport function setLevel(ctx: LogContext, levelName: LogLevelName): void {\n const levelValue = LOG_LEVELS[levelName];\n if (levelValue !== undefined) {\n ctx.level = levelValue;\n }\n}\n\n/**\n * Parse a level name or number to LogLevel.\n */\nexport function parseLevel(level: LogLevelName | number): number {\n if (typeof level === 'number') {\n return level;\n }\n return LOG_LEVELS[level] ?? LOG_LEVELS.info;\n}\n\nexport default levelPlugin;\n","/**\n * @oxog/log - Format Plugin\n *\n * Handles output format selection and formatting.\n *\n * @packageDocumentation\n */\n\nimport type { Plugin } from '@oxog/types';\nimport type { LogContext, LogEntry, Format } from '../../types.js';\nimport { formatJson, formatPretty } from '../../utils/format.js';\nimport { isDev, isTTY } from '../../utils/env.js';\n\n/**\n * Format plugin for output formatting.\n *\n * This plugin:\n * - Selects format based on configuration\n * - Provides JSON and Pretty formatters\n * - Auto-detects format based on environment\n *\n * @example\n * ```typescript\n * import { formatPlugin } from '@oxog/log/plugins';\n *\n * logger.use(formatPlugin());\n *\n * // Format is auto-detected or can be set explicitly\n * ```\n */\nexport function formatPlugin(): Plugin<LogContext> {\n return {\n name: 'format',\n version: '1.0.0',\n\n install(kernel) {\n const ctx = kernel.getContext();\n\n // Set default format if not set\n if (ctx.format === undefined) {\n ctx.format = detectFormat();\n }\n // Auto-detect format if set to 'auto'\n else if (ctx.format === 'auto') {\n ctx.format = detectFormat();\n }\n },\n };\n}\n\n/**\n * Auto-detect the best format based on environment.\n *\n * - Development + TTY = 'pretty'\n * - Production or non-TTY = 'json'\n */\nexport function detectFormat(): 'json' | 'pretty' {\n if (isDev() && isTTY()) {\n return 'pretty';\n }\n return 'json';\n}\n\n/**\n * Format a log entry based on context settings.\n */\nexport function formatEntry(ctx: LogContext, entry: LogEntry): string {\n const format = ctx.format === 'auto' ? detectFormat() : ctx.format;\n\n if (format === 'pretty') {\n return formatPretty(entry, ctx.pigment, {\n timestamp: ctx.timestamp,\n source: ctx.source,\n });\n }\n\n return formatJson(entry);\n}\n\n/**\n * Get the effective format (resolving 'auto').\n */\nexport function getEffectiveFormat(ctx: LogContext): 'json' | 'pretty' {\n if (ctx.format === 'auto') {\n return detectFormat();\n }\n return ctx.format as 'json' | 'pretty';\n}\n\nexport default formatPlugin;\n","/**\n * @oxog/log - Timestamp Plugin\n *\n * Adds timestamp to log entries.\n *\n * @packageDocumentation\n */\n\nimport type { Plugin } from '@oxog/types';\nimport type { LogContext, LogEntry } from '../../types.js';\n\n/**\n * Timestamp plugin for adding timestamps to log entries.\n *\n * This plugin:\n * - Adds Unix timestamp (ms) to entries\n * - Optionally adds ISO 8601 timestamp\n *\n * @example\n * ```typescript\n * import { timestampPlugin } from '@oxog/log/plugins';\n *\n * logger.use(timestampPlugin());\n *\n * // Entries will have: { time: 1234567890123, ... }\n * ```\n */\nexport function timestampPlugin(): Plugin<LogContext> {\n return {\n name: 'timestamp',\n version: '1.0.0',\n\n install(kernel) {\n const ctx = kernel.getContext();\n // Set default timestamp setting if not set\n if (ctx.timestamp === undefined) {\n ctx.timestamp = true;\n }\n },\n };\n}\n\n/**\n * Get current Unix timestamp in milliseconds.\n */\nexport function now(): number {\n return Date.now();\n}\n\n/**\n * Get current ISO 8601 timestamp string.\n */\nexport function nowIso(): string {\n return new Date().toISOString();\n}\n\n/**\n * Format a Unix timestamp as ISO 8601 string.\n */\nexport function toIso(timestamp: number): string {\n return new Date(timestamp).toISOString();\n}\n\n/**\n * Parse an ISO 8601 string to Unix timestamp.\n */\nexport function fromIso(isoString: string): number {\n return new Date(isoString).getTime();\n}\n\n/**\n * Add timestamp to a log entry.\n */\nexport function addTimestamp(entry: LogEntry): LogEntry {\n if (entry.time === undefined) {\n entry.time = Date.now();\n }\n return entry;\n}\n\n/**\n * Format timestamp for display.\n */\nexport function formatTimestamp(timestamp: number): string {\n return new Date(timestamp).toISOString();\n}\n\nexport default timestampPlugin;\n","/**\n * @oxog/log - Error Classes\n *\n * Custom error classes for the logging library.\n *\n * @packageDocumentation\n */\n\n/**\n * Base error class for @oxog/log.\n *\n * @example\n * ```typescript\n * try {\n * log.info({ nested: circular });\n * } catch (err) {\n * if (err instanceof LogError) {\n * console.error('Log error:', err.code);\n * }\n * }\n * ```\n */\nexport class LogError extends Error {\n /** Error code for programmatic handling */\n readonly code: string;\n\n /** Original error if wrapping another error */\n override readonly cause?: Error;\n\n constructor(message: string, code: string, cause?: Error) {\n super(message);\n this.name = 'LogError';\n this.code = code;\n this.cause = cause;\n\n // Maintain proper stack trace in V8\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, this.constructor);\n }\n }\n}\n\n/**\n * Error thrown when a plugin fails to install or operate.\n *\n * @example\n * ```typescript\n * throw new PluginError('Failed to initialize plugin', 'my-plugin');\n * ```\n */\nexport class PluginError extends LogError {\n /** Name of the plugin that caused the error */\n readonly pluginName: string;\n\n constructor(message: string, pluginName: string, cause?: Error) {\n super(`[Plugin: ${pluginName}] ${message}`, 'PLUGIN_ERROR', cause);\n this.name = 'PluginError';\n this.pluginName = pluginName;\n }\n}\n\n/**\n * Error thrown when a transport fails to write or operate.\n *\n * @example\n * ```typescript\n * throw new TransportError('Failed to write to file', 'file-transport');\n * ```\n */\nexport class TransportError extends LogError {\n /** Name of the transport that caused the error */\n readonly transportName: string;\n\n constructor(message: string, transportName: string, cause?: Error) {\n super(`[Transport: ${transportName}] ${message}`, 'TRANSPORT_ERROR', cause);\n this.name = 'TransportError';\n this.transportName = transportName;\n }\n}\n\n/**\n * Error thrown when configuration is invalid.\n *\n * @example\n * ```typescript\n * throw new ConfigError('Invalid log level: verbose');\n * ```\n */\nexport class ConfigError extends LogError {\n /** Configuration option that caused the error */\n readonly option?: string;\n\n constructor(message: string, option?: string, cause?: Error) {\n super(message, 'CONFIG_ERROR', cause);\n this.name = 'ConfigError';\n this.option = option;\n }\n}\n\n/**\n * Error thrown when serialization fails (e.g., circular references).\n *\n * @example\n * ```typescript\n * throw new SerializationError('Circular reference detected');\n * ```\n */\nexport class SerializationError extends LogError {\n constructor(message: string, cause?: Error) {\n super(message, 'SERIALIZATION_ERROR', cause);\n this.name = 'SerializationError';\n }\n}\n\n/**\n * Error thrown when a required feature is not available in the current environment.\n *\n * @example\n * ```typescript\n * throw new EnvironmentError('File transport is not available in browser');\n * ```\n */\nexport class EnvironmentError extends LogError {\n /** Required environment */\n readonly requiredEnv: 'node' | 'browser';\n\n constructor(message: string, requiredEnv: 'node' | 'browser', cause?: Error) {\n super(message, 'ENVIRONMENT_ERROR', cause);\n this.name = 'EnvironmentError';\n this.requiredEnv = requiredEnv;\n }\n}\n\n/**\n * Error thrown when buffer operations fail.\n *\n * @example\n * ```typescript\n * throw new BufferError('Buffer overflow: max size exceeded');\n * ```\n */\nexport class BufferError extends LogError {\n constructor(message: string, cause?: Error) {\n super(message, 'BUFFER_ERROR', cause);\n this.name = 'BufferError';\n }\n}\n\n/**\n * Create an error from an unknown caught value.\n * Ensures we always have a proper Error object.\n *\n * @example\n * ```typescript\n * try {\n * riskyOperation();\n * } catch (err) {\n * throw ensureError(err);\n * }\n * ```\n */\nexport function ensureError(value: unknown): Error {\n if (value instanceof Error) {\n return value;\n }\n\n if (typeof value === 'string') {\n return new Error(value);\n }\n\n if (typeof value === 'object' && value !== null) {\n const obj = value as Record<string, unknown>;\n if (typeof obj['message'] === 'string') {\n const err = new Error(obj['message']);\n if (typeof obj['name'] === 'string') {\n err.name = obj['name'];\n }\n return err;\n }\n }\n\n return new Error(String(value));\n}\n\n/**\n * Wrap an error with additional context.\n *\n * @example\n * ```typescript\n * try {\n * writeToFile(data);\n * } catch (err) {\n * throw wrapError(err, 'Failed to write log file');\n * }\n * ```\n */\nexport function wrapError(error: unknown, message: string): LogError {\n const cause = ensureError(error);\n return new LogError(`${message}: ${cause.message}`, 'WRAPPED_ERROR', cause);\n}\n","/**\n * @oxog/log - File Transport\n *\n * Output logs to files with optional rotation.\n * Node.js only.\n *\n * @packageDocumentation\n */\n\nimport type { Transport, LogEntry, FileTransportOptions } from '../types.js';\nimport { formatJson } from '../utils/format.js';\nimport { isNode } from '../utils/env.js';\nimport { parseSize, parseRotation } from '../constants.js';\nimport { TransportError, EnvironmentError } from '../errors.js';\n\n/**\n * Create a file transport.\n *\n * @example\n * ```typescript\n * import { fileTransport } from '@oxog/log/transports';\n *\n * const transport = fileTransport({\n * path: './logs/app.log',\n * rotate: '1d',\n * maxSize: '10MB',\n * maxFiles: 7,\n * });\n * ```\n */\nexport function fileTransport(options: FileTransportOptions): Transport {\n if (!isNode()) {\n throw new EnvironmentError('File transport is only available in Node.js', 'node');\n }\n\n const {\n path: filePath,\n rotate,\n maxSize,\n maxFiles = 5,\n compress = false,\n } = options;\n\n // Parse size and rotation settings\n const maxSizeBytes = maxSize ? parseSize(maxSize) : undefined;\n const rotationMs = rotate ? parseRotation(rotate) : undefined;\n\n // Track current file state\n let currentSize = 0;\n let lastRotation = Date.now();\n let writeStream: NodeJS.WritableStream | null = null;\n let fs: typeof import('fs') | null = null;\n let path: typeof import('path') | null = null;\n let zlib: typeof import('zlib') | null = null;\n\n // Lazy load Node.js modules\n async function ensureModules(): Promise<void> {\n if (!fs) {\n fs = await import('fs');\n path = await import('path');\n if (compress) {\n zlib = await import('zlib');\n }\n }\n }\n\n // Open write stream\n async function ensureStream(): Promise<NodeJS.WritableStream> {\n await ensureModules();\n\n if (!writeStream) {\n // Ensure directory exists\n const dir = path!.dirname(filePath);\n if (!fs!.existsSync(dir)) {\n fs!.mkdirSync(dir, { recursive: true });\n }\n\n // Get current file size if exists\n if (fs!.existsSync(filePath)) {\n const stats = fs!.statSync(filePath);\n currentSize = stats.size;\n }\n\n writeStream = fs!.createWriteStream(filePath, { flags: 'a' });\n }\n\n return writeStream;\n }\n\n // Check if rotation is needed\n function shouldRotate(): boolean {\n // Size-based rotation\n if (maxSizeBytes && currentSize >= maxSizeBytes) {\n return true;\n }\n\n // Time-based rotation\n if (rotationMs && Date.now() - lastRotation >= rotationMs) {\n return true;\n }\n\n return false;\n }\n\n // Perform rotation\n async function performRotation(): Promise<void> {\n await ensureModules();\n\n if (!writeStream) return;\n\n // Close current stream\n await new Promise<void>((resolve, reject) => {\n writeStream!.once('finish', resolve);\n writeStream!.once('error', reject);\n writeStream!.end();\n });\n writeStream = null;\n\n // Generate rotation timestamp\n const timestamp = new Date().toISOString().replace(/[:.]/g, '-');\n const ext = path!.extname(filePath);\n const base = filePath.slice(0, -ext.length);\n const rotatedPath = `${base}.${timestamp}${ext}`;\n\n // Rename current file\n fs!.renameSync(filePath, rotatedPath);\n\n // Compress if enabled\n if (compress && zlib) {\n const gzPath = `${rotatedPath}.gz`;\n const input = fs!.createReadStream(rotatedPath);\n const output = fs!.createWriteStream(gzPath);\n const gzip = zlib.createGzip();\n\n await new Promise<void>((resolve, reject) => {\n input.pipe(gzip).pipe(output);\n output.on('finish', () => {\n fs!.unlinkSync(rotatedPath);\n resolve();\n });\n output.on('error', reject);\n });\n }\n\n // Cleanup old files\n await cleanupOldFiles();\n\n // Reset state\n currentSize = 0;\n lastRotation = Date.now();\n }\n\n // Cleanup old rotated files\n async function cleanupOldFiles(): Promise<void> {\n await ensureModules();\n\n const dir = path!.dirname(filePath);\n const baseName = path!.basename(filePath);\n const ext = path!.extname(filePath);\n const prefix = baseName.slice(0, -ext.length);\n\n const files = fs!.readdirSync(dir)\n .filter((f) => f.startsWith(prefix) && f !== baseName)\n .map((f) => ({\n name: f,\n path: path!.join(dir, f),\n mtime: fs!.statSync(path!.join(dir, f)).mtime.getTime(),\n }))\n .sort((a, b) => b.mtime - a.mtime);\n\n // Remove excess files\n while (files.length > maxFiles) {\n const file = files.pop()!;\n fs!.unlinkSync(file.path);\n }\n }\n\n return {\n name: 'file',\n\n async write(entry: LogEntry): Promise<void> {\n // Check rotation\n if (shouldRotate()) {\n await performRotation();\n }\n\n // Get stream\n const stream = await ensureStream();\n\n // Format entry\n const line = formatJson(entry) + '\\n';\n const bytes = Buffer.byteLength(line, 'utf8');\n\n // Write\n return new Promise((resolve, reject) => {\n stream.write(line, (err) => {\n if (err) {\n reject(new TransportError(`Failed to write to file: ${err.message}`, 'file', err));\n } else {\n currentSize += bytes;\n resolve();\n }\n });\n });\n },\n\n writeSync(entry: LogEntry): void {\n // Ensure modules are loaded synchronously (they should be by now)\n // This is a synchronous fallback for critical logs\n if (!fs) {\n // Lazy load synchronously - this works because require is sync\n // In ESM, we need to handle this differently\n try {\n // For critical sync writes, we attempt direct file write\n const fsSync = require('fs') as typeof import('fs');\n const pathSync = require('path') as typeof import('path');\n\n // Ensure directory exists\n const dir = pathSync.dirname(filePath);\n if (!fsSync.existsSync(dir)) {\n fsSync.mkdirSync(dir, { recursive: true });\n }\n\n // Format and write synchronously\n const line = formatJson(entry) + '\\n';\n fsSync.appendFileSync(filePath, line, 'utf8');\n currentSize += Buffer.byteLength(line, 'utf8');\n } catch {\n // If sync write fails, fall through to stderr as last resort\n process.stderr.write(formatJson(entry) + '\\n');\n }\n return;\n }\n\n try {\n // Format entry\n const line = formatJson(entry) + '\\n';\n\n // Write synchronously using appendFileSync\n fs.appendFileSync(filePath, line, 'utf8');\n currentSize += Buffer.byteLength(line, 'utf8');\n } catch (err) {\n // If sync write fails, write to stderr as fallback\n process.stderr.write(formatJson(entry) + '\\n');\n throw new TransportError(\n `Failed to write sync to file: ${err instanceof Error ? err.message : String(err)}`,\n 'file',\n err instanceof Error ? err : undefined\n );\n }\n },\n\n async flush(): Promise<void> {\n if (writeStream && 'flush' in writeStream) {\n return new Promise<void>((resolve) => {\n (writeStream as NodeJS.WritableStream & { flush: (cb: () => void) => void }).flush(resolve);\n });\n }\n },\n\n async close(): Promise<void> {\n if (writeStream) {\n await new Promise<void>((resolve, reject) => {\n writeStream!.once('finish', resolve);\n writeStream!.once('error', reject);\n writeStream!.end();\n });\n writeStream = null;\n }\n },\n\n supports(env: 'node' | 'browser'): boolean {\n return env === 'node';\n },\n };\n}\n\nexport default fileTransport;\n","/**\n * @oxog/log - Stream Transport\n *\n * Output logs to Node.js writable streams.\n * Node.js only.\n *\n * @packageDocumentation\n */\n\nimport type { Transport, LogEntry, StreamTransportOptions } from '../types.js';\nimport { formatJson } from '../utils/format.js';\nimport { isNode } from '../utils/env.js';\nimport { TransportError, EnvironmentError } from '../errors.js';\n\n/**\n * Create a stream transport.\n *\n * @example\n * ```typescript\n * import { streamTransport } from '@oxog/log/transports';\n * import { createWriteStream } from 'fs';\n *\n * const transport = streamTransport({\n * stream: createWriteStream('./app.log'),\n * });\n * ```\n */\nexport function streamTransport(options: StreamTransportOptions): Transport {\n if (!isNode()) {\n throw new EnvironmentError('Stream transport is only available in Node.js', 'node');\n }\n\n const { stream } = options;\n\n if (!stream) {\n throw new TransportError('Stream is required', 'stream');\n }\n\n let closed = false;\n\n return {\n name: 'stream',\n\n write(entry: LogEntry): Promise<void> {\n if (closed) {\n return Promise.reject(new TransportError('Stream is closed', 'stream'));\n }\n\n const line = formatJson(entry) + '\\n';\n\n return new Promise((resolve, reject) => {\n const canWrite = stream.write(line, (err) => {\n if (err) {\n reject(new TransportError(`Failed to write to stream: ${err.message}`, 'stream', err));\n } else {\n resolve();\n }\n });\n\n // Handle backpressure\n if (!canWrite) {\n stream.once('drain', () => {\n resolve();\n });\n }\n });\n },\n\n flush(): Promise<void> {\n // Most streams don't have explicit flush\n return Promise.resolve();\n },\n\n async close(): Promise<void> {\n if (closed) return;\n closed = true;\n\n return new Promise((resolve, reject) => {\n stream.once('finish', resolve);\n stream.once('error', (err) => {\n reject(new TransportError(`Failed to close stream: ${err.message}`, 'stream', err));\n });\n stream.end();\n });\n },\n\n supports(env: 'node' | 'browser'): boolean {\n return env === 'node';\n },\n };\n}\n\nexport default streamTransport;\n","/**\n * @oxog/log - HTTP Transport\n *\n * Send logs to HTTP endpoints with batching and retry.\n *\n * @packageDocumentation\n */\n\nimport type { Transport, LogEntry, HttpTransportOptions } from '../types.js';\nimport { TransportError } from '../errors.js';\n\n/**\n * Create an HTTP transport.\n *\n * @example\n * ```typescript\n * import { httpTransport } from '@oxog/log/transports';\n *\n * const transport = httpTransport({\n * url: 'https://logs.example.com/ingest',\n * batch: 100,\n * interval: 5000,\n * headers: { 'X-API-Key': 'xxx' },\n * });\n * ```\n */\nexport function httpTransport(options: HttpTransportOptions): Transport {\n const {\n url,\n method = 'POST',\n headers = {},\n batch = 100,\n interval = 5000,\n retry = 3,\n } = options;\n\n if (!url) {\n throw new TransportError('URL is required', 'http');\n }\n\n // Buffer for batching\n let buffer: LogEntry[] = [];\n let flushTimer: ReturnType<typeof setInterval> | null = null;\n let isFlushing = false;\n let closed = false;\n\n // Start flush interval\n function startFlushInterval(): void {\n if (flushTimer) return;\n if (interval > 0) {\n flushTimer = setInterval(() => {\n flushBuffer().catch(() => {\n // Silently ignore interval flush errors\n });\n }, interval);\n }\n }\n\n // Stop flush interval\n function stopFlushInterval(): void {\n if (flushTimer) {\n clearInterval(flushTimer);\n flushTimer = null;\n }\n }\n\n // Flush the buffer\n async function flushBuffer(): Promise<void> {\n if (isFlushing || buffer.length === 0) return;\n isFlushing = true;\n\n // Take current buffer\n const entries = buffer;\n buffer = [];\n\n try {\n await sendWithRetry(entries);\n } catch (err) {\n // Put entries back in buffer if send fails\n buffer = [...entries, ...buffer].slice(0, batch * 2); // Limit buffer size\n throw err;\n } finally {\n isFlushing = false;\n }\n }\n\n // Send entries with retry\n async function sendWithRetry(entries: LogEntry[]): Promise<void> {\n let lastError: Error | null = null;\n\n for (let attempt = 0; attempt <= retry; attempt++) {\n try {\n await sendEntries(entries);\n return;\n } catch (err) {\n lastError = err instanceof Error ? err : new Error(String(err));\n\n // Exponential backoff\n if (attempt < retry) {\n const delay = Math.min(1000 * Math.pow(2, attempt), 30000);\n await sleep(delay);\n }\n }\n }\n\n throw new TransportError(\n `Failed to send logs after ${retry + 1} attempts: ${lastError?.message}`,\n 'http',\n lastError || undefined\n );\n }\n\n // Send entries to endpoint\n async function sendEntries(entries: LogEntry[]): Promise<void> {\n const body = JSON.stringify(entries);\n\n const response = await fetch(url, {\n method,\n headers: {\n 'Content-Type': 'application/json',\n ...headers,\n },\n body,\n });\n\n if (!response.ok) {\n throw new Error(`HTTP ${response.status}: ${response.statusText}`);\n }\n }\n\n // Sleep utility\n function sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n }\n\n // Start interval on first write\n let started = false;\n\n return {\n name: 'http',\n\n async write(entry: LogEntry): Promise<void> {\n if (closed) {\n throw new TransportError('Transport is closed', 'http');\n }\n\n // Start interval on first write\n if (!started) {\n started = true;\n startFlushInterval();\n }\n\n // Add to buffer\n buffer.push(entry);\n\n // Flush if buffer is full\n if (buffer.length >= batch) {\n await flushBuffer();\n }\n },\n\n async flush(): Promise<void> {\n await flushBuffer();\n },\n\n async close(): Promise<void> {\n if (closed) return;\n closed = true;\n\n stopFlushInterval();\n\n // Final flush\n if (buffer.length > 0) {\n try {\n await flushBuffer();\n } catch {\n // Ignore errors on close\n }\n }\n },\n\n supports(_env: 'node' | 'browser'): boolean {\n // Works in both environments with fetch\n return typeof fetch !== 'undefined';\n },\n };\n}\n\nexport default httpTransport;\n","/**\n * @oxog/log - LocalStorage Transport\n *\n * Persist logs to browser localStorage.\n * Browser only.\n *\n * @packageDocumentation\n */\n\nimport type { Transport, LogEntry, LocalStorageTransportOptions, LogLevelName } from '../types.js';\nimport { isBrowser } from '../utils/env.js';\nimport { parseSize } from '../constants.js';\nimport { TransportError, EnvironmentError } from '../errors.js';\nimport { LOG_LEVELS } from '../constants.js';\n\n/**\n * Create a localStorage transport.\n *\n * @example\n * ```typescript\n * import { localStorageTransport } from '@oxog/log/transports';\n *\n * const transport = localStorageTransport({\n * key: 'app-logs',\n * maxSize: '1MB',\n * levels: ['error', 'fatal'],\n * });\n * ```\n */\nexport function localStorageTransport(options: LocalStorageTransportOptions): Transport {\n if (!isBrowser()) {\n throw new EnvironmentError('LocalStorage transport is only available in browser', 'browser');\n }\n\n const {\n key,\n maxSize = '1MB',\n levels,\n } = options;\n\n if (!key) {\n throw new TransportError('Key is required', 'localStorage');\n }\n\n const maxBytes = parseSize(maxSize);\n const allowedLevels = levels\n ? new Set(levels.map((l) => LOG_LEVELS[l]))\n : null;\n\n // Get storage\n function getStorage(): Storage {\n return window.localStorage;\n }\n\n // Load existing logs\n function loadLogs(): LogEntry[] {\n try {\n const data = getStorage().getItem(key);\n if (!data) return [];\n return JSON.parse(data) as LogEntry[];\n } catch {\n return [];\n }\n }\n\n // Save logs\n function saveLogs(logs: LogEntry[]): void {\n const data = JSON.stringify(logs);\n\n // Check size\n while (data.length > maxBytes && logs.length > 0) {\n logs.shift(); // Remove oldest\n }\n\n try {\n getStorage().setItem(key, JSON.stringify(logs));\n } catch (err) {\n // Storage full - try to clear some space\n if (logs.length > 10) {\n logs.splice(0, Math.floor(logs.length / 2));\n saveLogs(logs);\n }\n }\n }\n\n // Check if level is allowed\n function isLevelAllowed(level: number): boolean {\n if (!allowedLevels) return true;\n return allowedLevels.has(level);\n }\n\n return {\n name: 'localStorage',\n\n write(entry: LogEntry): void {\n // Check level filter\n if (!isLevelAllowed(entry.level)) {\n return;\n }\n\n // Load, add, save\n const logs = loadLogs();\n logs.push(entry);\n saveLogs(logs);\n },\n\n flush(): void {\n // Nothing to flush - writes are immediate\n },\n\n close(): void {\n // Nothing to close\n },\n\n supports(env: 'node' | 'browser'): boolean {\n return env === 'browser';\n },\n };\n}\n\n/**\n * Read logs from localStorage.\n *\n * @example\n * ```typescript\n * const logs = readLogs('app-logs');\n * ```\n */\nexport function readLogs(key: string): LogEntry[] {\n if (!isBrowser()) return [];\n\n try {\n const data = window.localStorage.getItem(key);\n if (!data) return [];\n return JSON.parse(data) as LogEntry[];\n } catch {\n return [];\n }\n}\n\n/**\n * Clear logs from localStorage.\n *\n * @example\n * ```typescript\n * clearLogs('app-logs');\n * ```\n */\nexport function clearLogs(key: string): void {\n if (!isBrowser()) return;\n window.localStorage.removeItem(key);\n}\n\n/**\n * Get storage usage for logs.\n *\n * @example\n * ```typescript\n * const bytes = getStorageUsage('app-logs');\n * ```\n */\nexport function getStorageUsage(key: string): number {\n if (!isBrowser()) return 0;\n\n const data = window.localStorage.getItem(key);\n if (!data) return 0;\n return data.length * 2; // UTF-16 encoding\n}\n\nexport default localStorageTransport;\n","/**\n * @oxog/log - Redaction Utilities\n *\n * Mask sensitive data in log entries.\n *\n * @packageDocumentation\n */\n\nimport { REDACTED_VALUE } from '../constants.js';\n\n/**\n * Redact sensitive fields from an object.\n *\n * @example\n * ```typescript\n * const data = { user: 'john', password: 'secret' };\n * const redacted = redactFields(data, ['password']);\n * // { user: 'john', password: '[REDACTED]' }\n * ```\n */\nexport function redactFields<T extends Record<string, unknown>>(\n obj: T,\n paths: string[],\n placeholder = REDACTED_VALUE\n): T {\n if (!obj || typeof obj !== 'object' || paths.length === 0) {\n return obj;\n }\n\n // Create a deep clone to avoid mutating the original\n const result = deepClone(obj);\n\n for (const path of paths) {\n redactPath(result, path.split('.'), placeholder);\n }\n\n return result;\n}\n\n/**\n * Create a JSON replacer function that redacts sensitive fields during serialization.\n * This is more efficient than deep cloning as it redacts during the JSON.stringify process.\n *\n * @example\n * ```typescript\n * const replacer = createRedactingReplacer(['password', 'token']);\n * JSON.stringify(data, replacer);\n * // Redacts password and token fields without cloning the entire object\n * ```\n */\nexport function createRedactingReplacer(\n paths: string[],\n placeholder = REDACTED_VALUE\n): (key: string, value: unknown) => unknown {\n // Pre-compile paths into a Set for O(1) lookup\n const exactPaths = new Set<string>();\n const wildcardPaths: { prefix: string; suffix: string }[] = [];\n\n for (const path of paths) {\n if (path.includes('*')) {\n const parts = path.split('*');\n wildcardPaths.push({ prefix: parts[0] || '', suffix: parts[1] || '' });\n } else {\n // Add the field name itself for simple matching\n const lastDot = path.lastIndexOf('.');\n const fieldName = lastDot >= 0 ? path.slice(lastDot + 1) : path;\n exactPaths.add(fieldName);\n exactPaths.add(path);\n }\n }\n\n // Track current path during serialization\n const pathStack: string[] = [];\n\n return function replacer(key: string, value: unknown): unknown {\n // Handle the root object\n if (key === '') {\n pathStack.length = 0;\n return value;\n }\n\n // Check if this key should be redacted\n if (exactPaths.has(key)) {\n return placeholder;\n }\n\n // Build current path and check\n const currentPath = pathStack.length > 0 ? `${pathStack.join('.')}.${key}` : key;\n\n if (exactPaths.has(currentPath)) {\n return placeholder;\n }\n\n // Check wildcard paths\n for (const { prefix, suffix } of wildcardPaths) {\n if (currentPath.startsWith(prefix) && currentPath.endsWith(suffix)) {\n return placeholder;\n }\n }\n\n // If this is an object, track the path for nested keys\n if (value !== null && typeof value === 'object' && !Array.isArray(value)) {\n pathStack.push(key);\n // Note: JSON.stringify will call us again for nested properties\n // We need to pop after processing children, which happens automatically\n // because JSON.stringify processes depth-first\n }\n\n return value;\n };\n}\n\n/**\n * Stringify an object with redaction applied during serialization.\n * More efficient than redactFields + JSON.stringify for large objects.\n *\n * @example\n * ```typescript\n * const json = stringifyWithRedaction(data, ['password', 'headers.authorization']);\n * ```\n */\nexport function stringifyWithRedaction(\n obj: unknown,\n paths: string[],\n placeholder = REDACTED_VALUE,\n indent?: number\n): string {\n if (!obj || typeof obj !== 'object' || paths.length === 0) {\n return JSON.stringify(obj, null, indent);\n }\n\n // Use a WeakSet for circular reference detection\n const seen = new WeakSet<object>();\n\n // Pre-compile paths for efficient lookup\n const exactFields = new Set<string>();\n const pathPatterns: string[] = [];\n\n for (const path of paths) {\n if (path.includes('.') || path.includes('*')) {\n pathPatterns.push(path);\n } else {\n exactFields.add(path.toLowerCase());\n }\n }\n\n function replacer(this: unknown, key: string, value: unknown): unknown {\n // Root object\n if (key === '' && typeof value === 'object' && value !== null) {\n seen.add(value);\n return value;\n }\n\n // Check for simple field name match\n if (exactFields.has(key.toLowerCase())) {\n return placeholder;\n }\n\n // Handle circular references\n if (typeof value === 'object' && value !== null) {\n if (seen.has(value)) {\n return '[Circular]';\n }\n seen.add(value);\n }\n\n // Handle special types\n if (typeof value === 'bigint') {\n return value.toString();\n }\n\n if (value instanceof Error) {\n return {\n name: value.name,\n message: value.message,\n stack: value.stack,\n };\n }\n\n if (value instanceof RegExp) {\n return value.toString();\n }\n\n if (value instanceof Map) {\n return Object.fromEntries(value);\n }\n\n if (value instanceof Set) {\n return Array.from(value);\n }\n\n return value;\n }\n\n return JSON.stringify(obj, replacer, indent);\n}\n\n/**\n * Deep clone an object.\n */\nfunction deepClone<T>(obj: T): T {\n if (obj === null || typeof obj !== 'object') {\n return obj;\n }\n\n if (Array.isArray(obj)) {\n return obj.map((item) => deepClone(item)) as unknown as T;\n }\n\n if (obj instanceof Date) {\n return new Date(obj.getTime()) as unknown as T;\n }\n\n if (obj instanceof RegExp) {\n return new RegExp(obj.source, obj.flags) as unknown as T;\n }\n\n if (obj instanceof Map) {\n const result = new Map();\n for (const [key, value] of obj) {\n result.set(key, deepClone(value));\n }\n return result as unknown as T;\n }\n\n if (obj instanceof Set) {\n const result = new Set();\n for (const value of obj) {\n result.add(deepClone(value));\n }\n return result as unknown as T;\n }\n\n const result: Record<string, unknown> = {};\n for (const key of Object.keys(obj)) {\n result[key] = deepClone((obj as Record<string, unknown>)[key]);\n }\n return result as T;\n}\n\n/**\n * Redact a value at a specific path in an object.\n */\nfunction redactPath(\n obj: Record<string, unknown>,\n pathParts: string[],\n placeholder: string\n): void {\n if (pathParts.length === 0 || !obj || typeof obj !== 'object') {\n return;\n }\n\n const [current, ...rest] = pathParts;\n if (!current) return;\n\n // Handle wildcard matching\n if (current === '*') {\n for (const key of Object.keys(obj)) {\n if (rest.length === 0) {\n obj[key] = placeholder;\n } else {\n const value = obj[key];\n if (value && typeof value === 'object') {\n redactPath(value as Record<string, unknown>, rest, placeholder);\n }\n }\n }\n return;\n }\n\n // Handle array index notation [*]\n if (current === '[*]' && Array.isArray(obj)) {\n for (let i = 0; i < obj.length; i++) {\n if (rest.length === 0) {\n obj[i] = placeholder;\n } else {\n const value = obj[i];\n if (value && typeof value === 'object') {\n redactPath(value as Record<string, unknown>, rest, placeholder);\n }\n }\n }\n return;\n }\n\n if (!(current in obj)) {\n return;\n }\n\n if (rest.length === 0) {\n // Final path segment - redact the value\n obj[current] = placeholder;\n } else {\n // Continue traversing\n const value = obj[current];\n if (value && typeof value === 'object') {\n redactPath(value as Record<string, unknown>, rest, placeholder);\n }\n }\n}\n\n/**\n * Check if a field name matches any of the sensitive patterns.\n *\n * @example\n * ```typescript\n * isSensitive('password', ['password', 'token']); // true\n * isSensitive('username', ['password', 'token']); // false\n * ```\n */\nexport function isSensitive(fieldName: string, sensitivePatterns: string[]): boolean {\n const lowerField = fieldName.toLowerCase();\n\n return sensitivePatterns.some((pattern) => {\n const lowerPattern = pattern.toLowerCase();\n\n // Exact match\n if (lowerField === lowerPattern) return true;\n\n // Contains match\n if (lowerField.includes(lowerPattern)) return true;\n\n // Regex pattern (if pattern looks like a regex)\n if (pattern.startsWith('/') && pattern.endsWith('/')) {\n try {\n const regex = new RegExp(pattern.slice(1, -1), 'i');\n return regex.test(fieldName);\n } catch {\n return false;\n }\n }\n\n return false;\n });\n}\n\n/**\n * Create a redaction function with predefined paths.\n *\n * @example\n * ```typescript\n * const redact = createRedactor(['password', 'token']);\n * const safe = redact({ password: 'secret' });\n * ```\n */\nexport function createRedactor(\n paths: string[],\n placeholder = REDACTED_VALUE\n): <T extends Record<string, unknown>>(obj: T) => T {\n return (obj) => redactFields(obj, paths, placeholder);\n}\n\n/**\n * Auto-redact common sensitive field names.\n *\n * @example\n * ```typescript\n * const safe = autoRedact({ password: 'secret', username: 'john' });\n * // { password: '[REDACTED]', username: 'john' }\n * ```\n */\nexport function autoRedact<T extends Record<string, unknown>>(\n obj: T,\n additionalPatterns: string[] = [],\n placeholder = REDACTED_VALUE\n): T {\n if (!obj || typeof obj !== 'object') {\n return obj;\n }\n\n const defaultPatterns = [\n 'password',\n 'passwd',\n 'pwd',\n 'secret',\n 'token',\n 'apikey',\n 'api_key',\n 'apiKey',\n 'auth',\n 'authorization',\n 'credential',\n 'credentials',\n 'private',\n 'privateKey',\n 'private_key',\n ];\n\n const patterns = [...defaultPatterns, ...additionalPatterns];\n const result = deepClone(obj);\n\n autoRedactRecursive(result, patterns, placeholder);\n\n return result;\n}\n\n/**\n * Recursively auto-redact sensitive fields.\n */\nfunction autoRedactRecursive(\n obj: Record<string, unknown>,\n patterns: string[],\n placeholder: string\n): void {\n for (const key of Object.keys(obj)) {\n const value = obj[key];\n\n if (isSensitive(key, patterns)) {\n obj[key] = placeholder;\n } else if (value && typeof value === 'object' && !Array.isArray(value)) {\n autoRedactRecursive(value as Record<string, unknown>, patterns, placeholder);\n } else if (Array.isArray(value)) {\n for (const item of value) {\n if (item && typeof item === 'object') {\n autoRedactRecursive(item as Record<string, unknown>, patterns, placeholder);\n }\n }\n }\n }\n}\n","/**\n * @oxog/log - Redact Plugin\n *\n * Masks sensitive data in log entries.\n *\n * @packageDocumentation\n */\n\nimport type { Plugin } from '@oxog/types';\nimport type { LogContext, LogEntry } from '../../types.js';\nimport { redactFields } from '../../utils/redact.js';\nimport { REDACTED_VALUE } from '../../constants.js';\n\n/**\n * Redact plugin configuration options.\n */\nexport interface RedactPluginOptions {\n /** Field paths to redact */\n paths?: string[];\n\n /** Placeholder text for redacted values */\n placeholder?: string;\n}\n\n/**\n * Redact plugin for masking sensitive data.\n *\n * This plugin:\n * - Masks specified fields with placeholder\n * - Supports dot notation for nested paths\n * - Supports wildcards for arrays\n *\n * @example\n * ```typescript\n * import { redactPlugin } from '@oxog/log/plugins';\n *\n * logger.use(redactPlugin({\n * paths: ['password', 'user.token', 'headers.authorization']\n * }));\n * ```\n */\nexport function redactPlugin(options: RedactPluginOptions = {}): Plugin<LogContext> {\n return {\n name: 'redact',\n version: '1.0.0',\n\n install(kernel) {\n const ctx = kernel.getContext();\n const paths = options.paths || ctx.redactPaths || [];\n const placeholder = options.placeholder || REDACTED_VALUE;\n\n // Store configuration in context\n ctx.redactPaths = paths;\n\n // Expose redaction function\n (kernel as unknown as { redact: (entry: LogEntry) => LogEntry }).redact = (entry) => {\n return redactEntry(entry, paths, placeholder);\n };\n },\n };\n}\n\n/**\n * Redact sensitive fields from a log entry.\n */\nexport function redactEntry(\n entry: LogEntry,\n paths: string[],\n placeholder = REDACTED_VALUE\n): LogEntry {\n if (paths.length === 0) {\n return entry;\n }\n\n return redactFields(entry, paths, placeholder);\n}\n\nexport default redactPlugin;\n","/**\n * @oxog/log - Source Location Utilities\n *\n * Capture file and line number from stack traces.\n *\n * @packageDocumentation\n */\n\n/**\n * Source location information.\n */\nexport interface SourceLocation {\n /** Source file name (without path) */\n file: string;\n\n /** Full file path */\n path?: string;\n\n /** Line number */\n line: number;\n\n /** Column number */\n column?: number;\n\n /** Function name */\n fn?: string;\n}\n\n/**\n * Get the source location of the caller.\n *\n * @param depth - How many stack frames to skip (default: 0)\n *\n * @example\n * ```typescript\n * function myLogger() {\n * const loc = getSourceLocation(1); // Skip myLogger frame\n * console.log(`${loc.file}:${loc.line}`);\n * }\n * ```\n */\nexport function getSourceLocation(depth = 0): SourceLocation | undefined {\n // Create an Error to capture stack trace\n const err = new Error();\n const stack = err.stack;\n\n if (!stack) {\n return undefined;\n }\n\n // Parse the stack trace\n const frames = parseStack(stack);\n\n // Skip internal frames + depth\n // Typical stack: Error, getSourceLocation, caller1, caller2...\n const targetIndex = 2 + depth;\n\n if (targetIndex >= frames.length) {\n return undefined;\n }\n\n return frames[targetIndex];\n}\n\n/**\n * Parse a V8-style stack trace.\n *\n * V8 format:\n * ```\n * Error: message\n * at functionName (file:line:column)\n * at file:line:column\n * at Object.<anonymous> (file:line:column)\n * ```\n */\nfunction parseStack(stack: string): SourceLocation[] {\n const lines = stack.split('\\n');\n const frames: SourceLocation[] = [];\n\n for (const line of lines) {\n const trimmed = line.trim();\n\n // Skip \"Error:\" line\n if (!trimmed.startsWith('at ')) {\n continue;\n }\n\n const frame = parseV8Frame(trimmed);\n if (frame) {\n frames.push(frame);\n }\n }\n\n return frames;\n}\n\n/**\n * Parse a single V8 stack frame.\n *\n * Formats:\n * - \"at functionName (file:line:column)\"\n * - \"at file:line:column\"\n * - \"at Object.<anonymous> (file:line:column)\"\n * - \"at async functionName (file:line:column)\"\n */\nfunction parseV8Frame(line: string): SourceLocation | undefined {\n // Remove \"at \" prefix\n let content = line.slice(3);\n\n // Handle \"async \" prefix\n if (content.startsWith('async ')) {\n content = content.slice(6);\n }\n\n // Pattern 1: \"functionName (path:line:column)\"\n const parenMatch = content.match(/^(.+?)\\s+\\((.+):(\\d+):(\\d+)\\)$/);\n if (parenMatch) {\n const [, fn, path, lineStr, colStr] = parenMatch;\n return {\n fn: fn?.trim() || undefined,\n path: path,\n file: extractFileName(path || ''),\n line: parseInt(lineStr || '0', 10),\n column: parseInt(colStr || '0', 10),\n };\n }\n\n // Pattern 2: \"path:line:column\" (no function name)\n const simpleMatch = content.match(/^(.+):(\\d+):(\\d+)$/);\n if (simpleMatch) {\n const [, path, lineStr, colStr] = simpleMatch;\n return {\n path: path,\n file: extractFileName(path || ''),\n line: parseInt(lineStr || '0', 10),\n column: parseInt(colStr || '0', 10),\n };\n }\n\n // Pattern 3: \"path:line\" (no column)\n const noColMatch = content.match(/^(.+):(\\d+)$/);\n if (noColMatch) {\n const [, path, lineStr] = noColMatch;\n return {\n path: path,\n file: extractFileName(path || ''),\n line: parseInt(lineStr || '0', 10),\n };\n }\n\n return undefined;\n}\n\n/**\n * Extract the file name from a full path.\n *\n * @example\n * ```typescript\n * extractFileName('/path/to/file.ts'); // 'file.ts'\n * extractFileName('C:\\\\path\\\\to\\\\file.ts'); // 'file.ts'\n * extractFileName('file:///path/to/file.ts'); // 'file.ts'\n * ```\n */\nexport function extractFileName(path: string): string {\n // Remove file:// protocol\n let cleanPath = path.replace(/^file:\\/\\//, '');\n\n // Handle Windows paths\n cleanPath = cleanPath.replace(/\\\\/g, '/');\n\n // Remove query string and hash\n cleanPath = cleanPath.split('?')[0]?.split('#')[0] || cleanPath;\n\n // Get the file name\n const parts = cleanPath.split('/');\n return parts[parts.length - 1] || cleanPath;\n}\n\n/**\n * Check if a stack frame should be filtered out.\n * Used to skip internal frames from the logging library.\n *\n * @param location - Source location to check\n * @param internalPatterns - Patterns to filter (file names or paths)\n */\nexport function isInternalFrame(\n location: SourceLocation,\n internalPatterns: string[] = []\n): boolean {\n const defaultPatterns = [\n '@oxog/log',\n 'node_modules',\n 'internal/',\n '<anonymous>',\n ];\n\n const patterns = [...defaultPatterns, ...internalPatterns];\n const pathToCheck = location.path || location.file;\n\n return patterns.some((pattern) => {\n if (pattern.includes('/') || pattern.includes('\\\\')) {\n // Path pattern\n return pathToCheck.includes(pattern);\n }\n // File name pattern\n return location.file === pattern || location.file.includes(pattern);\n });\n}\n\n/**\n * Get the first non-internal source location.\n *\n * @param depth - Additional frames to skip\n * @param internalPatterns - Additional patterns to filter\n */\nexport function getCallerLocation(\n depth = 0,\n internalPatterns: string[] = []\n): SourceLocation | undefined {\n const err = new Error();\n const stack = err.stack;\n\n if (!stack) {\n return undefined;\n }\n\n const frames = parseStack(stack);\n\n // Skip: Error, getCallerLocation, getSourceLocation (if called), and depth\n let skipped = 0;\n for (const frame of frames) {\n if (skipped < 2 + depth) {\n skipped++;\n continue;\n }\n\n if (!isInternalFrame(frame, internalPatterns)) {\n return frame;\n }\n }\n\n return undefined;\n}\n\n/**\n * Format a source location as a string.\n *\n * @example\n * ```typescript\n * formatLocation({ file: 'app.ts', line: 42 }); // 'app.ts:42'\n * formatLocation({ file: 'app.ts', line: 42, column: 10 }); // 'app.ts:42:10'\n * ```\n */\nexport function formatLocation(location: SourceLocation): string {\n let result = location.file;\n\n if (location.line) {\n result += `:${location.line}`;\n }\n\n if (location.column) {\n result += `:${location.column}`;\n }\n\n return result;\n}\n","/**\n * @oxog/log - Source Plugin\n *\n * Captures source file and line number for log entries.\n *\n * @packageDocumentation\n */\n\nimport type { Plugin } from '@oxog/types';\nimport type { LogContext, LogEntry } from '../../types.js';\nimport { getSourceLocation, type SourceLocation } from '../../utils/source.js';\n\n/**\n * Source plugin configuration options.\n */\nexport interface SourcePluginOptions {\n /** Stack frame depth to skip */\n depth?: number;\n\n /** Include column number */\n includeColumn?: boolean;\n\n /** Include full file path */\n includeFullPath?: boolean;\n}\n\n/**\n * Source plugin for capturing file and line number.\n *\n * This plugin:\n * - Captures source file name\n * - Captures line number\n * - Optionally captures column number\n *\n * @example\n * ```typescript\n * import { sourcePlugin } from '@oxog/log/plugins';\n *\n * logger.use(sourcePlugin());\n *\n * log.info('Hello'); // Output includes file:line\n * ```\n */\nexport function sourcePlugin(options: SourcePluginOptions = {}): Plugin<LogContext> {\n return {\n name: 'source',\n version: '1.0.0',\n\n install(kernel) {\n const ctx = kernel.getContext();\n\n // Enable source tracking in context\n ctx.source = true;\n\n // Expose source location function with configured depth\n const depth = options.depth ?? 4; // Skip internal frames\n\n (kernel as unknown as { getSource: () => SourceLocation | undefined }).getSource = () => {\n return getSourceLocation(depth);\n };\n },\n };\n}\n\n/**\n * Add source location to a log entry.\n */\nexport function addSourceLocation(\n entry: LogEntry,\n depth = 4,\n options: SourcePluginOptions = {}\n): LogEntry {\n const location = getSourceLocation(depth);\n\n if (location) {\n entry.file = options.includeFullPath ? location.path : location.file;\n entry.line = location.line;\n\n if (options.includeColumn && location.column) {\n entry.column = location.column;\n }\n }\n\n return entry;\n}\n\nexport default sourcePlugin;\n","/**\n * @oxog/log - Timing Plugin\n *\n * Provides performance timing utilities for log entries.\n *\n * @packageDocumentation\n */\n\nimport type { Plugin } from '@oxog/types';\nimport type { LogContext } from '../../types.js';\n\n/**\n * Timing plugin for performance measurement.\n *\n * This plugin:\n * - Provides time/timeEnd methods\n * - Tracks named timers\n * - Logs duration in milliseconds\n *\n * @example\n * ```typescript\n * import { timingPlugin } from '@oxog/log/plugins';\n *\n * logger.use(timingPlugin());\n *\n * log.time('db-query');\n * await query();\n * log.timeEnd('db-query'); // logs duration\n * ```\n */\nexport function timingPlugin(): Plugin<LogContext> {\n return {\n name: 'timing',\n version: '1.0.0',\n\n install(kernel) {\n const ctx = kernel.getContext();\n\n // Initialize timers map\n if (!ctx.timers) {\n ctx.timers = new Map<string, number>();\n }\n },\n\n onDestroy() {\n // Clean up is handled by logger\n },\n };\n}\n\n/**\n * Start a timer with the given label.\n */\nexport function startTimer(ctx: LogContext, label: string): void {\n ctx.timers.set(label, performance.now());\n}\n\n/**\n * End a timer and return the duration.\n */\nexport function endTimer(ctx: LogContext, label: string): number | undefined {\n const start = ctx.timers.get(label);\n if (start === undefined) {\n return undefined;\n }\n\n const duration = performance.now() - start;\n ctx.timers.delete(label);\n return Math.round(duration * 100) / 100; // Round to 2 decimal places\n}\n\n/**\n * Check if a timer exists.\n */\nexport function hasTimer(ctx: LogContext, label: string): boolean {\n return ctx.timers.has(label);\n}\n\n/**\n * Get all active timer labels.\n */\nexport function getActiveTimers(ctx: LogContext): string[] {\n return Array.from(ctx.timers.keys());\n}\n\n/**\n * Clear all timers.\n */\nexport function clearTimers(ctx: LogContext): void {\n ctx.timers.clear();\n}\n\n/**\n * Create a one-shot timer function.\n */\nexport function createTimer(ctx: LogContext, label: string): () => number | undefined {\n startTimer(ctx, label);\n return () => endTimer(ctx, label);\n}\n\nexport default timingPlugin;\n","/**\n * @oxog/log - Correlation Plugin\n *\n * Provides correlation ID tracking for request tracing.\n *\n * @packageDocumentation\n */\n\nimport type { Plugin } from '@oxog/types';\nimport type { LogContext, LogEntry } from '../../types.js';\n\n/**\n * Correlation plugin configuration options.\n */\nexport interface CorrelationPluginOptions {\n /** Prefix for auto-generated correlation IDs */\n prefix?: string;\n\n /** Custom ID generator function */\n generator?: () => string;\n}\n\n// Store options at module level for ID generation\nlet correlationOptions: CorrelationPluginOptions = {};\n\n/**\n * Correlation plugin for request tracing.\n *\n * This plugin:\n * - Adds correlation ID to all log entries\n * - Supports auto-generation of IDs\n * - Inherits correlation ID in child loggers\n *\n * @example\n * ```typescript\n * import { correlationPlugin } from '@oxog/log/plugins';\n *\n * logger.use(correlationPlugin());\n *\n * const reqLog = log.withCorrelation('req-123');\n * reqLog.info('Processing'); // includes correlationId\n * ```\n */\nexport function correlationPlugin(options: CorrelationPluginOptions = {}): Plugin<LogContext> {\n return {\n name: 'correlation',\n version: '1.0.0',\n\n install(_kernel) {\n // Store options for ID generation\n correlationOptions = options;\n },\n };\n}\n\n/**\n * Generate a correlation ID.\n */\nexport function generateCorrelationId(): string {\n if (correlationOptions.generator) {\n return correlationOptions.generator();\n }\n\n const prefix = correlationOptions.prefix ?? 'cid';\n const random = Math.random().toString(36).substring(2, 10);\n const timestamp = Date.now().toString(36);\n return `${prefix}_${timestamp}${random}`;\n}\n\n/**\n * Add correlation ID to a log entry.\n */\nexport function addCorrelationId(entry: LogEntry, correlationId: string): LogEntry {\n entry.correlationId = correlationId;\n return entry;\n}\n\n/**\n * Get correlation ID from context.\n */\nexport function getCorrelationId(ctx: LogContext): string | undefined {\n return ctx.correlationId;\n}\n\n/**\n * Set correlation ID on context.\n */\nexport function setCorrelationId(ctx: LogContext, correlationId: string): void {\n ctx.correlationId = correlationId;\n}\n\n/**\n * Create or get a correlation ID.\n */\nexport function ensureCorrelationId(ctx: LogContext): string {\n if (!ctx.correlationId) {\n ctx.correlationId = generateCorrelationId();\n }\n return ctx.correlationId;\n}\n\nexport default correlationPlugin;\n","/**\n * @oxog/log - Buffer Plugin\n *\n * Provides async buffering for log entries.\n *\n * @packageDocumentation\n */\n\nimport type { Plugin } from '@oxog/types';\nimport type { LogContext, LogEntry, BufferOptions } from '../../types.js';\nimport { DEFAULT_BUFFER_OPTIONS } from '../../constants.js';\n\n/**\n * Buffer plugin for async log buffering.\n *\n * This plugin:\n * - Buffers log entries for batch processing\n * - Flushes based on size or interval\n * - Respects sync levels (fatal/error bypass buffer)\n *\n * @example\n * ```typescript\n * import { bufferPlugin } from '@oxog/log/plugins';\n *\n * logger.use(bufferPlugin({\n * size: 100,\n * flushInterval: 1000\n * }));\n * ```\n */\nexport function bufferPlugin(options: BufferOptions = {}): Plugin<LogContext> {\n return {\n name: 'buffer',\n version: '1.0.0',\n\n install(kernel) {\n const ctx = kernel.getContext();\n\n // Initialize buffer\n ctx.buffer = [];\n ctx.bufferOptions = {\n size: options.size ?? DEFAULT_BUFFER_OPTIONS.size,\n flushInterval: options.flushInterval ?? DEFAULT_BUFFER_OPTIONS.flushInterval,\n };\n\n // Start flush interval\n const flushInterval = ctx.bufferOptions.flushInterval ?? DEFAULT_BUFFER_OPTIONS.flushInterval;\n if (flushInterval > 0) {\n ctx.flushTimerId = setInterval(() => {\n flushBuffer(ctx).catch(() => {\n // Silently ignore flush errors in interval\n });\n }, flushInterval);\n }\n },\n\n async onDestroy() {\n // Flush is handled by logger.close()\n },\n };\n}\n\n/**\n * Add an entry to the buffer.\n * Returns true if buffer was flushed.\n */\nexport function bufferEntry(ctx: LogContext, entry: LogEntry): boolean {\n ctx.buffer.push(entry);\n\n // Check if buffer is full\n if (ctx.buffer.length >= (ctx.bufferOptions.size ?? DEFAULT_BUFFER_OPTIONS.size)) {\n // Flush synchronously to avoid overflow\n flushBufferSync(ctx);\n return true;\n }\n\n return false;\n}\n\n/**\n * Flush the buffer asynchronously.\n */\nexport async function flushBuffer(ctx: LogContext): Promise<LogEntry[]> {\n if (ctx.buffer.length === 0) {\n return [];\n }\n\n // Swap buffer\n const entries = ctx.buffer;\n ctx.buffer = [];\n\n // Write all entries to transports\n await Promise.all(\n entries.flatMap((entry) =>\n ctx.transports.map((transport) =>\n Promise.resolve(transport.write(entry)).catch((err) => {\n // Emit transport error instead of silently ignoring\n const error = err instanceof Error ? err : new Error(String(err));\n ctx.emitter.emit('error', { transport: transport.name, error, entry });\n })\n )\n )\n );\n\n // Emit flush event\n ctx.emitter.emit('flush', undefined as never);\n\n return entries;\n}\n\n/**\n * Flush the buffer synchronously.\n */\nexport function flushBufferSync(ctx: LogContext): LogEntry[] {\n if (ctx.buffer.length === 0) {\n return [];\n }\n\n // Swap buffer\n const entries = ctx.buffer;\n ctx.buffer = [];\n\n // Write all entries to transports\n for (const entry of entries) {\n for (const transport of ctx.transports) {\n try {\n // Prefer writeSync if available for truly synchronous flushing\n if (transport.writeSync) {\n transport.writeSync(entry);\n } else {\n transport.write(entry);\n }\n } catch (err) {\n // Emit transport error\n const error = err instanceof Error ? err : new Error(String(err));\n ctx.emitter.emit('error', { transport: transport.name, error, entry });\n }\n }\n }\n\n return entries;\n}\n\n/**\n * Get the current buffer size.\n */\nexport function getBufferSize(ctx: LogContext): number {\n return ctx.buffer.length;\n}\n\n/**\n * Clear the buffer without flushing.\n */\nexport function clearBuffer(ctx: LogContext): LogEntry[] {\n const entries = ctx.buffer;\n ctx.buffer = [];\n return entries;\n}\n\n/**\n * Stop the flush interval timer.\n */\nexport function stopFlushInterval(ctx: LogContext): void {\n if (ctx.flushTimerId) {\n clearInterval(ctx.flushTimerId);\n ctx.flushTimerId = undefined;\n }\n}\n\nexport default bufferPlugin;\n","/**\n * @oxog/log - Browser Plugin\n *\n * Provides native browser DevTools integration.\n *\n * @packageDocumentation\n */\n\nimport type { Plugin } from '@oxog/types';\nimport type { LogContext, LogEntry, LogLevelName } from '../../types.js';\nimport { isBrowser } from '../../utils/env.js';\n\n/**\n * Browser plugin configuration options.\n */\nexport interface BrowserPluginOptions {\n /** Enable console grouping for child loggers */\n grouping?: boolean;\n\n /** Enable styled output */\n styled?: boolean;\n\n /** Custom styles per level */\n styles?: Partial<Record<LogLevelName, string>>;\n}\n\n// Store options at module level\nlet browserOptions: BrowserPluginOptions = {};\n\n/**\n * Browser plugin for DevTools integration.\n *\n * This plugin:\n * - Maps log levels to console methods\n * - Provides styled console output\n * - Uses console.group for child loggers\n *\n * @example\n * ```typescript\n * import { browserPlugin } from '@oxog/log/plugins';\n *\n * logger.use(browserPlugin({ styled: true }));\n *\n * log.info('Hello'); // Uses console.log with styling\n * log.error('Oops'); // Uses console.error with styling\n * ```\n */\nexport function browserPlugin(options: BrowserPluginOptions = {}): Plugin<LogContext> {\n return {\n name: 'browser',\n version: '1.0.0',\n\n install(_kernel) {\n // Store options for browser output\n browserOptions = options;\n },\n };\n}\n\n/**\n * Get the console method for a log level.\n */\nexport function getConsoleMethod(levelName: LogLevelName): 'log' | 'debug' | 'info' | 'warn' | 'error' {\n switch (levelName) {\n case 'trace':\n case 'debug':\n return 'debug';\n case 'info':\n return 'info';\n case 'warn':\n return 'warn';\n case 'error':\n case 'fatal':\n return 'error';\n default:\n return 'log';\n }\n}\n\n/**\n * Get CSS styles for a log level.\n */\nexport function getLevelStyles(levelName: LogLevelName): string {\n if (browserOptions.styles?.[levelName]) {\n return browserOptions.styles[levelName]!;\n }\n\n const colors: Record<LogLevelName, string> = {\n trace: '#888888',\n debug: '#00bcd4',\n info: '#2196f3',\n warn: '#ff9800',\n error: '#f44336',\n fatal: '#9c27b0',\n };\n\n return `color: ${colors[levelName] ?? '#000000'}; font-weight: bold;`;\n}\n\n/**\n * Write a log entry to the browser console.\n */\nexport function writeToBrowserConsole(entry: LogEntry, styled = true): void {\n if (!isBrowser()) return;\n\n const method = getConsoleMethod(entry.levelName);\n const consoleObj = console as unknown as Record<string, (...args: unknown[]) => void>;\n\n if (styled) {\n const styles = getLevelStyles(entry.levelName);\n const label = `%c[${entry.levelName.toUpperCase()}]`;\n\n // Extract extra data (excluding standard fields)\n const {\n level: _level,\n levelName: _levelName,\n time: _time,\n msg,\n file: _file,\n line: _line,\n column: _column,\n correlationId: _correlationId,\n ...extra\n } = entry;\n\n if (Object.keys(extra).length > 0) {\n consoleObj[method](label, styles, msg, extra);\n } else {\n consoleObj[method](label, styles, msg);\n }\n } else {\n consoleObj[method](`[${entry.levelName.toUpperCase()}]`, entry.msg, entry);\n }\n}\n\n/**\n * Start a console group.\n */\nexport function startGroup(label: string, collapsed = false): void {\n if (!isBrowser()) return;\n\n if (collapsed) {\n console.groupCollapsed(label);\n } else {\n console.group(label);\n }\n}\n\n/**\n * End a console group.\n */\nexport function endGroup(): void {\n if (!isBrowser()) return;\n console.groupEnd();\n}\n\n/**\n * Check if grouping is enabled.\n */\nexport function isGroupingEnabled(): boolean {\n return browserOptions.grouping ?? true;\n}\n\nexport default browserPlugin;\n"],"mappings":"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","names":["LogLevel","indent","pigment","pigment","formatTime","getExtraFields","flushBuffer","result"]}