UNPKG

@syntrojs/logger

Version:

🔥 Fast, simple, and developer-friendly logger for Node.js and Bun (ALPHA - Proof of Concept)

1,108 lines (1,077 loc) • 35.4 kB
/** * Log levels and their weights */ declare const LOG_LEVEL_WEIGHTS: { readonly fatal: 60; readonly error: 50; readonly warn: 40; readonly info: 30; readonly debug: 20; readonly trace: 10; readonly silent: 0; }; type LogLevel = keyof typeof LOG_LEVEL_WEIGHTS; declare const logLevels: LogLevel[]; /** * Checks if a level should be logged based on the configured level */ declare function isLevelEnabled(logLevel: LogLevel, configuredLevel: LogLevel): boolean; /** * @file src/compliance/LoggingMatrix.ts * @description Controls which context fields are included in logs by level. * * This prevents logging sensitive fields like api_key, authorization headers, etc. * Only explicitly allowed fields are included, ensuring compliance and security. */ /** * @type LoggingMatrix * @description Matrix defining which context fields to include per log level. * * Example: * ```typescript * { * default: ['correlationId', 'transactionId'], * info: ['correlationId', 'transactionId', 'userId'], * error: ['*'] // Include all fields * } * ``` * * Use `['*']` to include all fields for a specific level. * If a level is not specified, `default` is used. */ type LoggingMatrix = Partial<Record<LogLevel | 'default', string[]>>; /** * @class FieldFilter * @description Filters context fields based on logging matrix configuration. */ declare class FieldFilter { private matrix; constructor(matrix?: LoggingMatrix); /** * Filters context fields based on the logging matrix for the given level. * Uses guard clauses and functional programming for better maintainability. * * @param context - The full context object * @param level - The log level * @returns Filtered context with only allowed fields (immutable) */ filterContext(context: Record<string, unknown>, level: LogLevel): Record<string, unknown>; /** * Updates the logging matrix (hot reconfiguration). * Functional approach: Merge matrices immutably. * * @param newMatrix - The new logging matrix configuration */ reconfigure(newMatrix: LoggingMatrix): void; /** * Gets the current logging matrix configuration. * @returns The current logging matrix */ getMatrix(): LoggingMatrix; } /** * FILE: src/masking/MaskingEngine.ts * DESCRIPTION: Ultra-fast data masking engine using JSON flattening strategy. * * This engine processes nested objects recursively, applying masking rules * to sensitive data fields based on pattern matching. */ /** * @enum MaskingStrategy * @description Different masking strategies for various data types. */ declare enum MaskingStrategy { CREDIT_CARD = "credit_card", SSN = "ssn", EMAIL = "email", PHONE = "phone", PASSWORD = "password", TOKEN = "token", CUSTOM = "custom" } /** * @interface MaskingRule * @description Configuration for a masking rule. */ interface MaskingRule { /** Regex pattern to match field names */ pattern: string | RegExp; /** Masking strategy to apply */ strategy: MaskingStrategy; /** Custom masking function (for CUSTOM strategy) */ customMask?: (value: string) => string; /** Whether to preserve original length */ preserveLength?: boolean; /** Character to use for masking */ maskChar?: string; /** Compiled regex pattern for performance */ _compiledPattern?: RegExp; } /** * @interface MaskingEngineOptions * @description Options for configuring the MaskingEngine. */ interface MaskingEngineOptions { /** Array of masking rules */ rules?: MaskingRule[]; /** Default mask character */ maskChar?: string; /** Whether to preserve original length by default */ preserveLength?: boolean; /** Enable default rules for common data types */ enableDefaultRules?: boolean; } /** * @class MaskingEngine * Ultra-fast data masking engine. * * Processes nested objects recursively and applies masking rules * to sensitive data fields based on pattern matching. */ declare class MaskingEngine { /** @private Array of masking rules */ private rules; /** @private Default mask character */ private readonly maskChar; /** @private Whether to preserve original length by default */ private readonly preserveLength; /** @private Whether the engine is initialized */ private initialized; /** @private Strategy map: Dictionary of masking functions (functional approach) */ private readonly strategyMap; constructor(options?: MaskingEngineOptions); /** * Adds default masking rules for common data types. * @private */ private addDefaultRules; /** * Adds a custom masking rule. * IMPORTANT: This only allows ADDING rules, not modifying existing ones for security. * @param rule - The masking rule to add */ addRule(rule: MaskingRule): void; /** * Processes a metadata object and applies the configured masking rules. * @param meta - The metadata object to process * @returns A new object with the masked data */ process(meta: Record<string, unknown>): Record<string, unknown>; /** * Applies masking rules to data recursively. * Uses functional programming and guard clauses for better maintainability. * @param data - Data to mask * @returns Masked data * @private */ private applyMaskingRules; /** * Find first matching masking rule for a key. * Single Responsibility: Only finds matching rules. * @param key - Field key to check * @returns Matching rule or undefined * @private */ private findMatchingRule; /** * Initialize strategy map with all masking functions. * Functional approach: Data dictionary instead of switch statements. * Pure functions stored in a Map for O(1) lookup. * * @returns Map of strategy enum to masking function * @private */ private initializeStrategyMap; /** * Applies specific masking strategy to a value. * Functional approach: Uses dictionary lookup instead of switch statement. * Pure function pattern: No side effects, predictable output. * Single Responsibility: Only applies masking strategies. * * @param value - Value to mask * @param rule - Masking rule to apply * @returns Masked value * @private */ private applyStrategy; /** * Masks credit card number. * Uses guard clause pattern for preserveLength option. * Single Responsibility: Only masks credit cards. * * @param value - Credit card number * @param rule - Masking rule * @returns Masked credit card * @private */ private maskCreditCard; /** * Masks SSN. * Uses guard clause pattern for preserveLength option. * Single Responsibility: Only masks SSNs. * * @param value - SSN * @param rule - Masking rule * @returns Masked SSN * @private */ private maskSSN; /** * Masks email address. * Functional approach: Pure function with guard clauses. * Single Responsibility: Only masks emails. * * @param value - Email address * @param rule - Masking rule * @returns Masked email * @private */ private maskEmail; /** * Masks phone number. * Functional approach: Pure function with guard clauses. * Single Responsibility: Only masks phone numbers. * * @param value - Phone number * @param rule - Masking rule * @returns Masked phone number * @private */ private maskPhone; /** * Masks password. * Functional approach: Pure function - simplest strategy. * Single Responsibility: Only masks passwords. * * @param value - Password * @param rule - Masking rule * @returns Masked password * @private */ private maskPassword; /** * Masks token. * Functional approach: Pure function with guard clauses. * Single Responsibility: Only masks tokens. * * @param value - Token * @param rule - Masking rule * @returns Masked token * @private */ private maskToken; /** * Default masking strategy. * Functional approach: Pure function with guard clauses. * Single Responsibility: Only provides default masking. * * @param value - Value to mask * @param rule - Masking rule * @returns Masked value * @private */ private maskDefault; /** * Gets masking engine statistics. * @returns Dictionary with masking statistics */ getStats(): Record<string, any>; /** * Checks if the masking engine is initialized. * @returns True if initialized */ isInitialized(): boolean; /** * Shutdown the masking engine. */ shutdown(): void; } /** * @file src/sanitization/SanitizationEngine.ts * @description Final security layer that sanitizes log entries before they are written by a transport. */ /** * @class SanitizationEngine * A security engine that makes log entries safe for printing by stripping * potentially malicious control characters, such as ANSI escape codes. * This prevents log injection attacks that could exploit terminal vulnerabilities. */ declare class SanitizationEngine { private readonly maskingEngine?; /** @private This regex matches ANSI escape codes used for colors, cursor movement, etc. */ private readonly ansiRegex; /** * @constructor * @param maskingEngine - Optional masking engine for data obfuscation */ constructor(maskingEngine?: MaskingEngine); /** * Processes a log metadata object, sanitizing all its string values. * @param meta - The metadata object to sanitize. * @returns A new, sanitized metadata object. */ process(meta: Record<string, unknown>): Record<string, unknown>; /** * @private * Recursively traverses an object or array to sanitize all string values. * IMPORTANT: Only processes plain objects (data.constructor === Object) to avoid * corrupting class instances, which protects logging and tracing tools. * * Uses guard clauses and functional programming for better maintainability. * @param data - The data to process. * @returns The sanitized data. */ private sanitizeRecursively; } /** * Core types for the logger */ interface LogEntry { /** * Timestamp as number (Date.now()) for consistency and performance. * Transports format this to ISO string when needed for human-readable output. * This avoids unnecessary Date object creation and string conversions in the hot path. */ timestamp: number; level: LogLevel; message: string; service?: string; [key: string]: unknown; } interface LoggerOptions { name?: string; level?: LogLevel; transport?: Transport; } type LogFormatArg = string | number | boolean | null | undefined; type LogMetadata = Record<string, unknown>; type JsonValue = LogFormatArg | LogMetadata | LogMetadata[]; /** * Type for metadata that can be attached to loggers. * * **Completely flexible:** Can be any JSON object (nested at any depth) with any keys and any JSON-compatible values. * Supports nested objects, arrays, and any combination thereof. No flattening required. * * Use this for ANY metadata your organization needs: * - Compliance rules (retention, policies, regulations) * - Business metadata (campaign info, user segments, product IDs) * - Internal process data (workflow IDs, pipeline stages, job queues) * - Audit information (who, what, when, why) * - Any other contextual information useful for log analysis * * The logger simply includes this metadata in all logs from the logger instance. * No validation, no interpretation - just passes it through as-is, preserving the full structure. * * @example * ```typescript * // Simple flat metadata * const complianceMetadata: LogRetentionRules = { * policy: 'HIPAA-compliant-7years', * retentionPeriod: '7-years', * encryption: 'AES-256' * }; * * // Nested objects (multiple levels) * const nestedMetadata: LogRetentionRules = { * compliance: { * policy: 'GDPR-COMPLIANT', * retention: { * period: '90-days', * archive: { * enabled: true, * location: 's3://archive' * } * }, * encryption: { * algorithm: 'AES-256', * keyRotation: '30-days' * } * }, * business: { * campaign: { * id: 'summer-2024', * channels: ['email', 'social'], * target: { * audience: 'millennials', * demographics: { age: [25, 40], location: 'US' } * } * } * }, * internal: { * workflow: { * id: 'wf-123', * pipeline: 'etl', * stages: { * extraction: { source: 'db', format: 'parquet' }, * transformation: { rules: ['clean', 'validate'] }, * load: { destination: 'warehouse' } * } * } * } * }; * * // Arrays of objects * const arrayMetadata: LogRetentionRules = { * policies: [ * { name: 'GDPR', version: '2024.1' }, * { name: 'CCPA', version: '2023.2' } * ], * campaigns: [ * { id: 'camp-1', active: true }, * { id: 'camp-2', active: false } * ] * }; * ``` */ type LogRetentionRules = Record<string, JsonValue>; /** * Base Transport class for extensibility * * This provides a solid foundation for custom transports including * future OpenTelemetry integration */ interface TransportOptions { level?: LogLevel; name?: string; } /** * Base Transport class * * All transports should extend this class for consistency and future features */ declare class Transport { level: LogLevel; name: string; constructor(options?: TransportOptions); /** * Check if this transport should handle a log entry */ isLevelEnabled(level: LogLevel): boolean; /** * Process and output a log entry. * Can receive either a LogEntry object or a pre-formatted JSON string. * Functional approach: Guard clause with ternary for single expression. */ log(entry: LogEntry | string): void; /** * Optional: Flush any buffered logs * Useful for async transports or file writers */ flush?(): void | Promise<void>; /** * Optional: Cleanup resources */ close?(): void | Promise<void>; } /** * Core Logger implementation * * Provides a fast, simple logging API inspired by Pino but even more lightweight */ interface LoggerBindings { [key: string]: unknown; } /** * Core Logger class */ declare class Logger { level: LogLevel; name: string; private transport; private bindings; private serviceName; private useAsyncContext; private sanitizationEngine?; private maskingEngine?; private fieldFilter?; /** * Disable async context lookup for this logger instance for max performance. * Useful for high-performance scenarios where you don't need correlation IDs. * @returns {this} The logger instance for chaining. */ withoutContext(): this; constructor(name: string, transport?: Transport, // JSON is the default - ultrafast! level?: LogLevel, bindings?: LoggerBindings, options?: { sanitizationEngine?: SanitizationEngine; maskingEngine?: MaskingEngine; useAsyncContext?: boolean; loggingMatrix?: LoggingMatrix; }); /** * Internal logging method. * Uses guard clauses and functional parsing for better maintainability. */ private log; /** * Parse log arguments following Pino-like signature. * Functional approach: returns parsed message and metadata. * Single Responsibility: Only parses arguments. * * @private */ private parseLogArguments; /** * Format message with optional format arguments (Single Responsibility). * Functional approach: Pure function for message formatting. * @private */ private formatMessage; /** * Get async context if enabled (Single Responsibility). * @private */ private getAsyncContext; /** * Write log entry with all processing (Single Responsibility). * Handles fast path, compliance pipeline, and JSON construction. * * @private */ private writeLogEntry; /** * Write fast path log (no context, bindings, or metadata). * Single Responsibility: Only handles minimal log entry. * * @private */ private writeFastPathLog; /** * Build base JSON string with required fields. * Single Responsibility: Only constructs base JSON. * * @private */ private buildBaseJson; /** * Check if object has any enumerable properties (performance helper). * Single Responsibility: Only checks object emptiness. * @private */ private hasNonEmptyObject; /** * Process data through compliance pipeline (filter → sanitize → mask). * Single Responsibility: Only handles compliance processing logic. * * @private */ private processCompliancePipeline; /** * Collect valid bindings (functional approach). * Optimized: Key check is redundant (Object.keys never returns empty strings). * @private */ private collectValidBindings; /** * Rebuild context map from sanitized data (functional + immutable). * @private */ private rebuildContextFromSanitized; /** * Rebuild bindings from sanitized data (functional + immutable). * @private */ private rebuildBindingsFromSanitized; /** * Append fields to JSON string (Single Responsibility). * Returns new string (immutable approach). * @private */ private appendFieldsToJson; /** * Write to transport with error handling (Single Responsibility). * @private */ private writeToTransport; fatal(...args: (LogFormatArg | LogMetadata | JsonValue)[]): void; error(...args: (LogFormatArg | LogMetadata | JsonValue)[]): void; warn(...args: (LogFormatArg | LogMetadata | JsonValue)[]): void; info(...args: (LogFormatArg | LogMetadata | JsonValue)[]): void; debug(...args: (LogFormatArg | LogMetadata | JsonValue)[]): void; trace(...args: (LogFormatArg | LogMetadata | JsonValue)[]): void; /** * Set the log level */ setLevel(level: LogLevel): void; /** * Create a child logger with additional bindings */ child(bindings: LoggerBindings): Logger; /** * Create a logger with a specific source. * Useful for identifying which module or component generated the log. * @param source - The name of the source (e.g., 'redis', 'AuthModule'). * @returns A new logger instance with the `source` binding. */ withSource(source: string): Logger; /** * Create a logger with a transaction ID bound to it. * Useful for tracking a request across multiple services in distributed systems. * @param transactionId - The unique ID of the transaction. * @returns A new logger instance with the `transactionId` binding. */ withTransactionId(transactionId: string): Logger; /** * Create a logger with metadata bound to it. * The provided metadata will be included in all logs from this logger. * * **Supports nested JSON of any depth** - objects, arrays, nested objects, etc. * * Use this for any metadata your organization needs: * - Compliance rules (retention, policies, regulations) * - Business metadata (campaign info, user segments, product IDs) * - Internal process data (workflow IDs, pipeline stages, job queues) * - Audit information or any other contextual data * * The logger simply includes this metadata as-is, preserving the full nested structure, * without validation or interpretation. * @param rules - A JSON object (can be nested at any depth) containing any metadata you need. * @returns A new logger instance with the `retention` binding (field name for backward compatibility). */ withRetention(rules: LogRetentionRules): Logger; /** * Flush buffered logs to transport. * Useful for graceful shutdown. * Uses guard clause pattern for optional method support. */ flush(): Promise<void>; /** * Close transport and cleanup resources. * Uses guard clause pattern for optional method support. */ close(): Promise<void>; /** * Reconfigure logger settings at runtime (hot reconfiguration). * * Allows changing logger settings without creating a new instance. * Security: Only allows adding masking rules, not modifying existing ones. * * @param options - Configuration options * @param options.level - Change log level dynamically * @param options.transport - Change transport dynamically * @param options.addMaskingRule - Add a new masking rule (only add, cannot modify existing) * @param options.loggingMatrix - Update logging matrix configuration * * @example * ```typescript * // Change log level at runtime * logger.reconfigure({ level: 'debug' }); * * // Switch transport * logger.reconfigure({ transport: new PrettyTransport() }); * * // Add a new masking rule * logger.reconfigure({ * addMaskingRule: { * pattern: /custom-field/i, * strategy: MaskingStrategy.CUSTOM, * customMask: (value) => '***' * } * }); * * // Update logging matrix * logger.reconfigure({ * loggingMatrix: { * default: ['correlationId'], * info: ['correlationId', 'userId'] * } * }); * ``` */ reconfigure(options: { level?: LogLevel; transport?: Transport; addMaskingRule?: MaskingRule; loggingMatrix?: LoggingMatrix; }): void; /** * Switch transport with cleanup (Single Responsibility). * Fire-and-forget cleanup pattern (non-blocking). * @private */ private switchTransport; /** * Add masking rule safely (Single Responsibility). * Security: Only allows adding rules, not modifying existing ones. * @private */ private addMaskingRuleSafely; /** * Update logging matrix (Single Responsibility). * @private */ private updateLoggingMatrix; } /** * JSON Transport - Outputs logs in structured JSON format * Perfect for production and log aggregation systems * * Optimized for raw JSON output without complex serialization overhead * * NOTE: Uses process.stdout.write() for maximum performance, which is synchronous * and avoids console.log's internal overhead. */ interface JsonTransportOptions extends TransportOptions { bufferSize?: number; } declare class JsonTransport extends Transport { private buffer; private bufferSize; constructor(options?: JsonTransportOptions); log(entry: LogEntry | string): void; flush(): void; close(): void; } /** * Pretty Transport - Human-readable colored output for development */ declare class PrettyTransport extends Transport { private readonly levelColorMap; constructor(options?: TransportOptions); log(entry: LogEntry | string): void; /** * Parse log entry from string or object (Single Responsibility). * Returns null if parsing fails. * @private */ private parseEntry; } /** * Compact Transport - Single-line logs optimized for readability */ declare class CompactTransport extends Transport { private readonly levelColorMap; constructor(options?: TransportOptions); log(entry: LogEntry | string): void; /** * Parse log entry from string or object (Single Responsibility). * Returns null if parsing fails. * @private */ private parseEntry; } /** * Classic Transport - Log4j-style single-line format * Optimized for traditional logging fans */ declare class ClassicTransport extends Transport { private readonly levelColorMap; /** Dictionary of console methods by log level (functional approach) */ private readonly consoleMethodMap; constructor(options?: TransportOptions); private formatTimestamp; log(entry: LogEntry | string): void; /** * Parse log entry from string or object (Single Responsibility). * Returns null if parsing fails. * @private */ private parseEntry; } /** * Array Transport - For testing purposes * * Writes log entries to an array instead of console/stdout. * Perfect for tests as it's fast and allows easy inspection of logs. */ declare class ArrayTransport extends Transport { /** Array to store log entries (functional: readonly from outside, mutable internally) */ readonly entries: string[]; /** * Log entry to array (Single Responsibility). * Functional approach: Single expression using ternary. */ log(entry: LogEntry | string): void; /** * Clear all entries (useful for test cleanup). * Functional approach: Mutates internal state (acceptable for test utility). */ clear(): void; /** * Get entries as parsed JSON objects (functional helper). * Guard clause: Returns empty array if no entries or parsing fails. */ getParsedEntries<T = LogEntry>(): T[]; /** * Get last entry as parsed JSON (functional helper). * Guard clause: Returns undefined if no entries or parsing fails. */ getLastEntry<T = LogEntry>(): T | undefined; } /** * Composite Transport - Send logs to multiple transports simultaneously * * Useful for logging to console AND file AND OpenTelemetry at the same time */ declare class CompositeTransport extends Transport { private transports; constructor(transports: Transport[]); log(entry: LogEntry): void; /** * Write to a single transport with error handling (Single Responsibility). * @private */ private writeToTransport; flush(): Promise<void>; close(): Promise<void>; } /** * Logger Registry * * Global registry for managing and retrieving logger instances by name * Allows accessing loggers from anywhere in your application */ interface RegistryLoggerOptions { name?: string; level?: LogLevel; transport?: Transport; } /** * Global Logger Registry * * Singleton pattern to manage logger instances across the application */ declare class LoggerRegistry { private static instance; private loggers; private constructor(); static getInstance(): LoggerRegistry; /** * Get or create a logger by name (functional approach). * * This follows the syntropyLog pattern: if the logger exists, return it; * if not, create a new one with default options and cache it automatically. */ getLogger(name: string, options?: RegistryLoggerOptions): Logger; /** * Get all registered logger names */ getLoggerNames(): string[]; /** * Check if a logger exists */ hasLogger(name: string): boolean; /** * Remove a logger from the registry */ removeLogger(name: string): boolean; /** * Clear all loggers */ clear(): void; /** * Get all loggers (for testing/debugging) * Returns an object with logger names as keys (functional approach) */ getAllLoggers(): Record<string, Logger>; } declare const loggerRegistry: LoggerRegistry; /** * Convenience functions for global access */ /** * Get a logger by name from anywhere in the app * * Automatically creates the logger if it doesn't exist. * Registration is completely internal and transparent. * * @example * ```typescript * import { getLogger } from '@syntrojs/logger/registry'; * * // First call: creates logger with default options * const dbLogger = getLogger('database'); * dbLogger.info('Query executed'); * * // Second call in different file: returns same instance * import { getLogger } from '@syntrojs/logger/registry'; * const logger = getLogger('database'); * logger.info('Another query'); // Same instance * * // With custom options (only on first call) * const apiLogger = getLogger('api', { level: 'debug', transport: 'json' }); * ``` */ declare function getLogger(name: string, options?: RegistryLoggerOptions): Logger; /** * Async Context Manager for Correlation IDs * * Uses AsyncLocalStorage to propagate correlation IDs and other context * automatically through async operations. * * Inspired by: * - Elysia's `state` for request-scoped data * - Fastify's `@fastify/request-context` for context propagation * - FastAPI's `request.state` for correlation IDs * - syntropyLog's ContextManager for enterprise features */ interface AsyncContextConfig { /** * Name of the correlation ID header * Default: 'correlationId' * Examples: 'x-correlation-id', 'x-request-id', 'trace-id' */ correlationIdKey?: string; /** * Whether to auto-generate correlation ID if not present * Default: true */ autoGenerate?: boolean; } /** * Simple context manager for correlation IDs and request-scoped data * * Similar to: * - Elysia's `state` for request-scoped data * - Fastify's `@fastify/request-context` for context propagation * - FastAPI's `request.state` for middleware data * - syntropyLog's ContextManager for correlation IDs */ declare class AsyncContext { private static storage; private static config; private static correlationIdKey; /** * Configure the context manager */ static configure(config: AsyncContextConfig): void; /** * Run a function within a context with optional initial data. * * @param fn - Function to run within the context * @param initialData - Optional initial context data (e.g., correlationId, userId, request metadata) * * @example * ```typescript * // Without initial data (auto-generates correlationId if enabled) * AsyncContext.run(() => { * const id = AsyncContext.getCorrelationId(); // UUID generated automatically * }); * * // With initial data (useful for middlewares) * AsyncContext.run(() => { * logger.info('Processing request'); * }, { correlationId: 'req-123', userId: 456, ip: '192.168.1.1' }); * ``` */ /** * Run a function within a context with optional initial data. * Functional approach: Single expression using ternary. * * @param fn - Function to run within the context * @param initialData - Optional initial context data (e.g., correlationId, userId, request metadata) * * @example * ```typescript * // Without initial data (auto-generates correlationId if enabled) * AsyncContext.run(() => { * const id = AsyncContext.getCorrelationId(); // UUID generated automatically * }); * * // With initial data (useful for middlewares) * AsyncContext.run(() => { * logger.info('Processing request'); * }, { correlationId: 'req-123', userId: 456, ip: '192.168.1.1' }); * ``` */ static run<R>(fn: () => R, initialData?: Record<string, unknown>): R; /** * Run async function within a context with optional initial data. * Functional approach: Single expression using ternary. * * @param fn - Async function to run within the context * @param initialData - Optional initial context data (e.g., correlationId, userId, request metadata) * * @example * ```typescript * // With initial data from HTTP request middleware * await AsyncContext.runAsync(async () => { * const correlationId = AsyncContext.getCorrelationId(); // from initialData or auto-generated * await processRequest(); * }, { * correlationId: req.headers['x-correlation-id'], * userId: req.user?.id, * ip: req.ip * }); * ``` */ static runAsync<R>(fn: () => Promise<R>, initialData?: Record<string, unknown>): Promise<R>; /** * Get a value from current context */ static get(key: string): unknown | undefined; /** * Get all context data */ static getAll(): Record<string, unknown>; /** * Set a value in the current context */ static set(key: string, value: unknown): void; /** * Get correlation ID from context. * Auto-generates one if not present and autoGenerate is enabled. * Uses guard clauses for better readability. */ static getCorrelationId(): string; /** * Set correlation ID in context */ static setCorrelationId(correlationId: string): void; /** * Clear all context data * Useful for cleanup or testing */ static clear(): void; /** * Check if we're currently in a context */ static isActive(): boolean; /** * Get the current context store (Map instance) * @internal Used by Logger for efficient context iteration */ static getStore(): Map<string, unknown> | undefined; } /** * Recursively validates that data is plain JSON (no functions, classes, code). * Uses guard clauses and functional programming. * * @param data - Data to validate * @param path - Current path for error messages (for debugging) * @returns true if valid, throws Error if invalid * @throws Error if data contains non-JSON values (functions, classes, etc.) */ declare function validatePlainJson(data: unknown, path?: string): void; /** * Validates and sanitizes JSON configuration. * Returns a safe copy of the data with invalid properties removed (immutable). * * @param data - Configuration data to sanitize * @returns Safe copy of the data with invalid properties removed * * @example * ```typescript * const safeConfig = validateAndSanitizeJson(externalConfig); * // SafeConfig will have all invalid properties (functions, classes) removed * ``` */ declare function validateAndSanitizeJson(data: unknown): unknown; /** * SyntroJS Logger * * A fast, simple, and developer-friendly logger for Node.js and Bun */ interface CreateLoggerOptions { name?: string; level?: LogLevel; transport?: Transport | 'pretty' | 'json' | 'compact' | 'classic'; maskingEngine?: MaskingEngine; sanitizationEngine?: SanitizationEngine; useAsyncContext?: boolean; loggingMatrix?: LoggingMatrix; } declare function createLogger(options?: CreateLoggerOptions): Logger; /** * Default logger instance */ declare const logger: Logger; export { ArrayTransport, AsyncContext, ClassicTransport, CompactTransport, CompositeTransport, type CreateLoggerOptions, FieldFilter, JsonTransport, type JsonTransportOptions, type JsonValue, LOG_LEVEL_WEIGHTS, type LogEntry, type LogFormatArg, type LogLevel, type LogMetadata, type LogRetentionRules, Logger, type LoggerOptions, type LoggingMatrix, MaskingEngine, type MaskingEngineOptions, type MaskingRule, MaskingStrategy, PrettyTransport, type RegistryLoggerOptions, SanitizationEngine, Transport, type TransportOptions, createLogger, getLogger, isLevelEnabled, logLevels, logger, loggerRegistry, validateAndSanitizeJson, validatePlainJson };