{"version":3,"file":"core.cjs","sources":["../src/core.ts"],"sourcesContent":["/**\n * @fileoverview Core Logger Module - Minimal logging without advanced features\n * @version 0.0.1\n * \n * This module provides the essential logging functionality without visual enhancements,\n * SVG support, or advanced styling. Perfect for lightweight applications or server-side usage.\n */\n\n// Core types\nimport type {\n    LogLevel,\n    Verbosity,\n    LoggerConfig,\n    ILogHandler,\n    LogMetadata,\n    TimerEntry\n} from './types/index.js';\n\n// Core utilities\nimport {\n    parseStackTrace,\n    formatTimestamp\n} from './utils/index.js';\n\n// Universal formatting and environment detection\nimport {\n    createPlainOutput,\n    createOutput,\n    getConsoleMethod,\n    createLogEntry,\n    formatTablePlain,\n    safeSerialize,\n    detectOptimalFormat,\n    type OutputFormat\n} from './utils/formatting.js';\n\nimport {\n    isBrowser,\n    isNode,\n    getRuntimeEnvironment,\n    supportsColors,\n    supportsCSSColors\n} from './utils/environment.js';\n\nimport { createStyledOutput } from './utils/output.js';\n\n// Constants\nimport { DEFAULT_CONFIG, LEVEL_STYLES } from './constants.js';\n\n/**\n * Minimal Logger class with core functionality only\n * \n * @example\n * ```typescript\n * import { CoreLogger } from '@mks2508/better-logger/core';\n * \n * const logger = new CoreLogger();\n * logger.info('Hello world');\n * logger.error('Something went wrong', error);\n * ```\n */\nexport class CoreLogger {\n    private config: LoggerConfig;\n    private scopedPrefix?: string;\n    private handlers: ILogHandler[] = [];\n    private timers: Map<string, TimerEntry> = new Map();\n    private groupDepth: number = 0;\n\n    /**\n     * Creates a new CoreLogger instance\n     * @param config - Optional configuration\n     */\n    constructor(config: Partial<LoggerConfig> = {}) {\n        this.config = {\n            ...DEFAULT_CONFIG,\n            ...config,\n            // Auto-configure based on environment\n            enableColors: config.enableColors ?? (isBrowser ? true : false),\n            enableTimestamps: config.enableTimestamps ?? true,\n            enableStackTrace: config.enableStackTrace ?? false,\n            autoDetectTheme: config.autoDetectTheme ?? true,\n            outputFormat: config.outputFormat ?? 'auto'\n        };\n    }\n\n    // ===== CONFIGURATION METHODS =====\n\n    /**\n     * Get current configuration\n     */\n    getConfig(): LoggerConfig {\n        return { ...this.config };\n    }\n\n    /**\n     * Sets the global prefix for all log messages\n     */\n    setGlobalPrefix(prefix: string): void {\n        this.config.globalPrefix = prefix;\n    }\n\n    /**\n     * Sets the verbosity level for filtering log output\n     */\n    setVerbosity(level: Verbosity): void {\n        this.config.verbosity = level;\n    }\n\n    /**\n     * Creates a scoped logger with a specific prefix\n     */\n    scope(prefix: string): CoreLogger {\n        const scopedLogger = new CoreLogger(this.config);\n        scopedLogger.scopedPrefix = prefix;\n        scopedLogger.handlers = [...this.handlers];\n        return scopedLogger;\n    }\n\n    /**\n     * Adds a custom log handler for extensibility\n     */\n    addHandler(handler: ILogHandler): void {\n        this.handlers.push(handler);\n    }\n\n    // ===== CORE LOGGING METHODS =====\n\n    /**\n     * Checks if a log level should be output based on current verbosity\n     */\n    private shouldLog(level: LogLevel): boolean {\n        if (this.config.verbosity === 'silent') return false;\n        const levels = { debug: 0, info: 1, warn: 2, error: 3, critical: 4 };\n        return levels[level] >= levels[this.config.verbosity];\n    }\n\n    /**\n     * Gets the effective prefix (global + scoped)\n     */\n    private getEffectivePrefix(): string | undefined {\n        const parts = [this.config.globalPrefix, this.scopedPrefix].filter(Boolean);\n        return parts.length > 0 ? parts.join(':') : undefined;\n    }\n\n    /**\n     * Core logging method with universal formatting\n     */\n    private log(level: LogLevel, ...args: any[]): void {\n        if (!this.shouldLog(level)) return;\n\n        const prefix = this.getEffectivePrefix();\n        const message = String(args[0] || '');\n        const stackInfo = this.config.enableStackTrace ? parseStackTrace() : null;\n        const consoleMethod = getConsoleMethod(level);\n\n        // Choose formatting based on environment and configuration\n        if (isBrowser && this.config.enableColors && supportsCSSColors()) {\n            // Browser with CSS styling\n            try {\n                const [format, ...styles] = createStyledOutput(\n                    level,\n                    LEVEL_STYLES,\n                    prefix,\n                    message,\n                    stackInfo,\n                    this.config.autoDetectTheme\n                );\n                console[consoleMethod](format, ...styles, ...args.slice(1));\n            } catch (error) {\n                // Fallback to universal formatting if CSS fails\n                const output = createOutput(level, message, prefix, stackInfo, this.config.outputFormat);\n                console[consoleMethod](output, ...args.slice(1));\n            }\n        } else {\n            // Node.js or browser without colors - use universal formatting\n            const groupIndent = '  '.repeat(this.groupDepth);\n            const output = groupIndent + createOutput(level, message, prefix, stackInfo, this.config.outputFormat);\n            console[consoleMethod](output, ...args.slice(1));\n        }\n\n        // Call custom handlers with structured metadata\n        const logEntry = createLogEntry(level, message, args, prefix, stackInfo);\n        const metadata: LogMetadata = {\n            timestamp: logEntry.timestamp,\n            level,\n            prefix,\n            stackInfo: logEntry.location,\n        };\n\n        this.handlers.forEach(handler => {\n            try {\n                handler.handle(level, message, args, metadata);\n            } catch (error) {\n                console.error('Log handler failed:', error);\n            }\n        });\n    }\n\n    /**\n     * Logs debug information (lowest priority)\n     */\n    debug(...args: any[]): void {\n        this.log('debug', ...args);\n    }\n\n    /**\n     * Logs informational messages\n     */\n    info(...args: any[]): void {\n        this.log('info', ...args);\n    }\n\n    /**\n     * Logs warning messages\n     */\n    warn(...args: any[]): void {\n        this.log('warn', ...args);\n    }\n\n    /**\n     * Logs error messages\n     */\n    error(...args: any[]): void {\n        this.log('error', ...args);\n    }\n\n    /**\n     * Logs critical errors (highest priority)\n     */\n    critical(...args: any[]): void {\n        this.log('critical', ...args);\n    }\n\n    /**\n     * Logs trace information (detailed debugging)\n     */\n    trace(...args: any[]): void {\n        this.log('debug', ...args);\n        if (this.shouldLog('debug')) {\n            console.trace(...args);\n        }\n    }\n\n    // ===== BASIC ADVANCED FEATURES =====\n\n    /**\n     * Displays data in a table format\n     */\n    table(data: any, columns?: string[]): void {\n        if (!this.shouldLog('info')) return;\n\n        const prefix = this.getEffectivePrefix();\n        const tableHeader = `[TABLE]${prefix ? ` [${prefix}]` : ''}:`;\n        \n        if (isBrowser && typeof console.table === 'function') {\n            // Browser has native table support\n            console.log(tableHeader);\n            if (columns) {\n                console.table(data, columns);\n            } else {\n                console.table(data);\n            }\n        } else {\n            // Node.js or fallback - use plain text formatting\n            console.log(tableHeader);\n            const tableText = formatTablePlain(data, columns);\n            console.log(tableText);\n        }\n    }\n\n    /**\n     * Starts a collapsible group in the console\n     */\n    group(label: string, collapsed: boolean = false): void {\n        const prefix = this.getEffectivePrefix();\n        const fullLabel = `${prefix ? `[${prefix}] ` : ''}${label}`;\n        \n        if (isBrowser && console.group && console.groupCollapsed) {\n            // Browser supports native grouping\n            if (collapsed) {\n                console.groupCollapsed(fullLabel);\n            } else {\n                console.group(fullLabel);\n            }\n        } else {\n            // Node.js fallback - just log the group label\n            const groupStart = '┌─ ' + fullLabel;\n            console.log(groupStart);\n        }\n        \n        this.groupDepth++;\n    }\n\n    /**\n     * Ends the current console group\n     */\n    groupEnd(): void {\n        if (this.groupDepth > 0) {\n            if (isBrowser && console.groupEnd) {\n                console.groupEnd();\n            } else {\n                // Node.js fallback - log group end\n                const groupEnd = '└─ (end group)';\n                console.log(groupEnd);\n            }\n            this.groupDepth--;\n        }\n    }\n\n    /**\n     * Starts a timer with the given label\n     */\n    time(label: string): void {\n        const startTime = this.getPerformanceNow();\n        const timer: TimerEntry = {\n            label,\n            startTime,\n        };\n        this.timers.set(label, timer);\n        \n        const prefix = this.getEffectivePrefix();\n        const message = `Timer started: ${label}`;\n        const output = createPlainOutput('info', message, prefix);\n        console.log(output);\n    }\n\n    /**\n     * Ends a timer and logs the elapsed time\n     */\n    timeEnd(label: string): void {\n        const timer = this.timers.get(label);\n        if (!timer) {\n            this.warn(`Timer '${label}' does not exist`);\n            return;\n        }\n\n        const elapsed = this.getPerformanceNow() - timer.startTime;\n        this.timers.delete(label);\n        \n        const prefix = this.getEffectivePrefix();\n        const message = `Timer ended: ${label} - ${elapsed.toFixed(2)}ms`;\n        const output = createPlainOutput('info', message, prefix);\n        console.log(output);\n    }\n\n    /**\n     * Gets performance.now() or fallback for older environments\n     */\n    private getPerformanceNow(): number {\n        if (typeof performance !== 'undefined' && performance.now) {\n            return performance.now();\n        }\n        \n        if (isNode && process.hrtime) {\n            // Node.js high-resolution time\n            const [seconds, nanoseconds] = process.hrtime();\n            return seconds * 1000 + nanoseconds / 1000000;\n        }\n        \n        // Fallback to Date.now()\n        return Date.now();\n    }\n}\n\n// Create and export singleton instance for convenience\nconst coreLogger = new CoreLogger();\n\n/**\n * Export individual methods for convenience (with proper binding)\n */\nexport const debug = (...args: any[]) => coreLogger.debug(...args);\nexport const info = (...args: any[]) => coreLogger.info(...args);\nexport const warn = (...args: any[]) => coreLogger.warn(...args);\nexport const error = (...args: any[]) => coreLogger.error(...args);\nexport const critical = (...args: any[]) => coreLogger.critical(...args);\nexport const trace = (...args: any[]) => coreLogger.trace(...args);\nexport const table = (data: any, columns?: string[]) => coreLogger.table(data, columns);\nexport const group = (label: string, collapsed?: boolean) => coreLogger.group(label, collapsed);\nexport const groupEnd = () => coreLogger.groupEnd();\nexport const time = (label: string) => coreLogger.time(label);\nexport const timeEnd = (label: string) => coreLogger.timeEnd(label);\nexport const setGlobalPrefix = (prefix: string) => coreLogger.setGlobalPrefix(prefix);\nexport const scope = (prefix: string) => coreLogger.scope(prefix);\nexport const setVerbosity = (level: Verbosity) => coreLogger.setVerbosity(level);\nexport const addHandler = (handler: ILogHandler) => coreLogger.addHandler(handler);\n\n// Export the singleton as default\nexport default coreLogger;\n\n// Re-export core types\nexport type {\n    LogLevel,\n    Verbosity,\n    LoggerConfig,\n    ILogHandler,\n    LogMetadata\n} from './types/index.js';"],"names":["CoreLogger","config","scopedPrefix","handlers","timers","Map","groupDepth","constructor","this","DEFAULT_CONFIG","enableColors","isBrowser","enableTimestamps","enableStackTrace","autoDetectTheme","outputFormat","getConfig","setGlobalPrefix","prefix","globalPrefix","setVerbosity","level","verbosity","scope","scopedLogger","addHandler","handler","push","shouldLog","levels","debug","info","warn","error","critical","getEffectivePrefix","parts","filter","Boolean","length","join","log","args","message","String","stackInfo","parseStackTrace","consoleMethod","getConsoleMethod","supportsCSSColors","format","styles","createStyledOutput","LEVEL_STYLES","console","slice","output","createOutput","repeat","logEntry","createLogEntry","metadata","timestamp","location","forEach","handle","trace","table","data","columns","tableHeader","tableText","formatTablePlain","group","label","collapsed","fullLabel","groupCollapsed","groupStart","groupEnd","time","timer","startTime","getPerformanceNow","set","createPlainOutput","timeEnd","get","elapsed","delete","toFixed","performance","now","isNode","process","hrtime","seconds","nanoseconds","Date","coreLogger"],"mappings":"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"}