@oxog/log 1.0.0
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/LICENSE +21 -0
- package/README.md +297 -0
- package/dist/index.cjs +1893 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.js +1784 -0
- package/dist/index.js.map +1 -0
- package/dist/plugins/index.cjs +854 -0
- package/dist/plugins/index.cjs.map +1 -0
- package/dist/plugins/index.js +782 -0
- package/dist/plugins/index.js.map +1 -0
- package/dist/transports/index.cjs +853 -0
- package/dist/transports/index.cjs.map +1 -0
- package/dist/transports/index.js +809 -0
- package/dist/transports/index.js.map +1 -0
- package/package.json +96 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/plugins/index.ts","../../src/constants.ts","../../src/plugins/core/level.ts","../../src/utils/format.ts","../../src/utils/env.ts","../../src/plugins/core/format.ts","../../src/plugins/core/timestamp.ts","../../src/utils/redact.ts","../../src/plugins/optional/redact.ts","../../src/utils/source.ts","../../src/plugins/optional/source.ts","../../src/plugins/optional/correlation.ts","../../src/plugins/optional/timing.ts","../../src/plugins/optional/buffer.ts","../../src/plugins/optional/browser.ts"],"sourcesContent":["/**\n * @oxog/log - Plugins\n *\n * All plugins for the logging library.\n *\n * @packageDocumentation\n */\n\n// Core plugins (automatically loaded by createLogger)\nexport {\n levelPlugin,\n isLevelEnabled,\n getLevelName,\n setLevel,\n parseLevel,\n} from './core/level.js';\n\nexport {\n formatPlugin,\n detectFormat,\n formatEntry,\n getEffectiveFormat,\n} from './core/format.js';\n\nexport {\n timestampPlugin,\n now,\n nowIso,\n toIso,\n fromIso,\n addTimestamp,\n} from './core/timestamp.js';\n\n// Optional plugins\nexport {\n redactPlugin,\n redactEntry,\n type RedactPluginOptions,\n} from './optional/redact.js';\n\nexport {\n sourcePlugin,\n addSourceLocation,\n type SourcePluginOptions,\n} from './optional/source.js';\n\nexport {\n correlationPlugin,\n generateCorrelationId,\n addCorrelationId,\n getCorrelationId,\n setCorrelationId,\n ensureCorrelationId,\n type CorrelationPluginOptions,\n} from './optional/correlation.js';\n\nexport {\n timingPlugin,\n startTimer,\n endTimer,\n hasTimer,\n getActiveTimers,\n clearTimers,\n createTimer,\n} from './optional/timing.js';\n\nexport {\n bufferPlugin,\n bufferEntry,\n flushBuffer,\n flushBufferSync,\n getBufferSize,\n clearBuffer,\n stopFlushInterval,\n} from './optional/buffer.js';\n\nexport {\n browserPlugin,\n getConsoleMethod,\n getLevelStyles,\n writeToBrowserConsole,\n startGroup,\n endGroup,\n isGroupingEnabled,\n type BrowserPluginOptions,\n} from './optional/browser.js';\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 - 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 - 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 - 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 - 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 - 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 - 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 - 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 - 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":["result"]}
|