UNPKG

lever-ui-logger

Version:

Zero-dependency logging library with optional EventBus integration. Built-in PII redaction, multiple transports, and comprehensive logging capabilities.

1,527 lines (1,509 loc) 80.6 kB
/** * Core Logger Types and Interface Definitions * * Foundational type definitions for the lever-ui-logger system, providing * comprehensive TypeScript interfaces for logger configuration, transport * systems, and event structures. Designed for seamless integration with * the EventBus architecture and maximum type safety. * * Key Types: * - Logger interface for structured logging with context and metadata * - Transport interface for pluggable log output destinations * - LoggerConfig for comprehensive logger configuration * - LogEventData for structured log event representation * - RedactionConfig for PII protection and data sanitization * - Sampling configuration for performance optimization * * @example * ```typescript * import type { Logger, LoggerConfig, Transport } from '@nuanced-labs/lever-ui-logger'; * * // Type-safe logger configuration * const config: LoggerConfig = { * level: 'info', * component: 'user-service', * defaultContext: { service: 'api', version: '1.0.0' }, * sampling: { debug: 0.1, info: 1.0 }, * redaction: { enabled: true, patterns: ['password', 'token'] }, * transports: [consoleTransport, beaconTransport] * }; * * // Custom transport implementation * const customTransport: Transport = { * name: 'custom-transport', * write: (event: LogEventData) => { * console.log(`${event.level}: ${event.message}`, event.context); * }, * flush: async () => { }, * close: async () => { } * }; * ``` */ /** * Log levels supported by the logger */ type LogLevel = 'trace' | 'debug' | 'info' | 'warn' | 'error'; /** * Logger configuration options */ interface LoggerConfig { /** Minimum log level to process */ level?: LogLevel; /** Component/module name for contextual logging */ component?: string; /** Custom context that will be added to all logs */ defaultContext?: Record<string, unknown>; /** Sampling rates per log level (0-1) */ sampling?: Partial<Record<LogLevel, number>>; /** PII redaction configuration */ redaction?: RedactionConfig; /** Transport configuration */ transports?: Transport[]; /** Enable/disable automatic error capture */ captureUnhandledErrors?: boolean; /** Enable/disable automatic unhandled rejection capture */ captureUnhandledRejections?: boolean; /** Enable/disable console.error interception */ captureConsoleErrors?: boolean; } /** * PII redaction configuration */ interface RedactionConfig { /** Enable/disable redaction */ enabled?: boolean; /** Redaction mode: strict, balanced, permissive, off */ mode?: 'strict' | 'balanced' | 'permissive' | 'off'; /** Custom redaction patterns to add */ patterns?: RedactionPattern[]; /** Specific patterns to enable (overrides defaults) */ enabledPatterns?: string[]; /** Specific patterns to disable */ disabledPatterns?: string[]; /** Custom redaction function */ customRedactor?: (input: string) => string; /** Use hash-based redaction for analytics */ hashRedaction?: boolean; /** Enable differential privacy for metrics */ differentialPrivacy?: boolean; /** Performance warning threshold in ms */ performanceThreshold?: number; } /** * Redaction pattern definition */ interface RedactionPattern { /** Pattern name for debugging and configuration */ name?: string; /** Regular expression pattern to match */ pattern: RegExp; /** Replacement string */ replacement: string; /** Description of what this pattern matches */ description?: string; /** Whether this pattern is enabled by default */ defaultEnabled?: boolean; /** Performance category for priority ordering */ priority?: 'high' | 'medium' | 'low'; } /** * Transport interface for log output */ interface Transport { /** Transport name for identification */ name: string; /** Write a log event to this transport */ write(event: LogEventData): Promise<void> | void; /** Flush any pending logs */ flush(): Promise<void> | void; /** Close the transport and clean up resources */ close(): Promise<void> | void; /** Transport configuration */ config?: Record<string, unknown>; } /** * Log event data structure passed to transports */ interface LogEventData { /** Log level */ level: LogLevel; /** Log message */ message: string; /** Timestamp when log was created */ timestamp: number; /** Additional context data */ context: Record<string, unknown>; /** Additional arguments passed to log call */ args: readonly unknown[]; /** Component/logger name that created this log */ component: string; /** Logger instance name */ logger: string; } /** * Metric data structure for structured metrics logging */ interface MetricData { /** Metric name */ name: string; /** Metric fields/values */ fields: Record<string, number | string | boolean>; /** Timestamp when metric was recorded */ timestamp: number; /** Additional context */ context: Record<string, unknown>; /** Component that recorded the metric */ component: string; } /** * Error data structure for error logging */ interface ErrorData { /** Error name/type */ name: string; /** Error message */ message: string; /** Stack trace if available */ stack?: string; /** Whether error was handled by application */ handled: boolean; /** Timestamp when error occurred */ timestamp: number; /** Additional context */ context: Record<string, unknown>; /** Component where error occurred */ component: string; } /** * Logger interface - main logging API */ interface Logger { /** Logger name/identifier */ readonly name: string; /** Current log level */ readonly level: LogLevel; /** Log trace message */ trace(message: string, ...args: readonly unknown[]): void; /** Log debug message */ debug(message: string, ...args: readonly unknown[]): void; /** Log info message */ info(message: string, ...args: readonly unknown[]): void; /** Log warning message */ warn(message: string, ...args: readonly unknown[]): void; /** Log error message */ error(message: string, ...args: readonly unknown[]): void; /** Record a metric */ metric(name: string, fields?: Record<string, number | string | boolean>): void; /** Create child logger with additional context */ withContext(context: Record<string, unknown>): Logger; /** Set minimum log level */ setLevel(level: LogLevel): void; /** Set component-specific log level */ setComponentLevel(component: string, level: LogLevel): void; /** Explicitly redact a value */ redact(value: unknown): string; /** Add a transport to this logger */ addTransport(transport: Transport): void; /** Remove a transport from this logger */ removeTransport(transportName: string): boolean; /** Flush all transports */ flush(): Promise<void>; /** Destroy logger and clean up resources */ destroy(): Promise<void>; } /** * Logger factory function type */ type LoggerFactory = (config?: LoggerConfig) => Logger; /** * EventBus integration event classes following lever-ui-eventbus patterns * All events follow the class-based event pattern with public readonly properties */ /** * Base class for all logging events with sync coordination metadata. * * All logger events extend this class to provide consistent timestamp and client ID * tracking for cross-library coordination and lever-ui-sync integration. * * @example * ```typescript * // Events automatically get timestamp and clientId * const event = new LogEvent('info', 'message', {}, [], 'component', 'logger'); * console.log(event.timestamp); // 1640995200000 * console.log(event.clientId); // "550e8400-e29b-41d4-a716-446655440000" or "client-abc123-def456" * ``` */ declare class LoggerBaseEvent { readonly timestamp: number; readonly clientId: string; /** * Creates a new logger base event. * * @param timestamp - Unix timestamp when event was created (defaults to Date.now()) * @param clientId - Unique client identifier for this browser session (auto-generated) */ constructor(timestamp?: number, clientId?: string); } /** * Core logging event published to EventBus for all log calls. * * This event is posted to the EventBus whenever a log method is called (trace, debug, info, warn, error). * Other systems can subscribe to these events for analytics, monitoring, error tracking, etc. * * @example * ```typescript * // Subscribe to all log events * eventBus.subscribe(LogEvent, (event) => { * console.log(`[${event.level.toUpperCase()}] ${event.message}`, event.context); * * if (event.level === 'error') { * sendToErrorTracking(event); * } * }); * * // Logger automatically posts LogEvent to EventBus * logger.info('User logged in', { userId: '123', method: 'oauth' }); * ``` */ declare class LogEvent extends LoggerBaseEvent { readonly level: LogLevel; readonly message: string; readonly context: Record<string, unknown>; readonly args: readonly unknown[]; readonly component: string; readonly logger: string; /** * Creates a new log event. * * @param level - Log level (trace, debug, info, warn, error) * @param message - Primary log message * @param context - Structured context data object * @param args - Additional arguments passed to the log call * @param component - Component or module name that generated the log * @param logger - Logger instance name * @param timestamp - Optional custom timestamp (defaults to current time) * @param clientId - Optional custom client ID (defaults to generated ID) */ constructor(level: LogLevel, message: string, context: Record<string, unknown>, args: readonly unknown[], component: string, logger: string, timestamp?: number, clientId?: string); /** * Converts this event to the LogEventData format used by transports. * * @returns LogEventData object ready for transport processing * @example * ```typescript * const event = new LogEvent('info', 'test', {}, [], 'comp', 'logger'); * const transportData = event.toLogEventData(); * consoleTransport.write(transportData); * ``` */ toLogEventData(): LogEventData; } /** * Structured metrics event for performance monitoring and analytics. * * Use this event type for recording quantitative measurements like response times, * user interactions, performance metrics, and business analytics. * * @example * ```typescript * // Subscribe to metrics for analytics * eventBus.subscribe(MetricEvent, (event) => { * analytics.track(event.name, event.fields); * }); * * // Logger posts MetricEvent to EventBus * logger.metric('api_response_time', { * duration: 234, * endpoint: '/users', * status: 200 * }); * ``` */ declare class MetricEvent extends LoggerBaseEvent { readonly name: string; readonly fields: Record<string, number | string | boolean>; readonly context: Record<string, unknown>; readonly component: string; /** * Creates a new metric event. * * @param name - Metric name (e.g., 'page_load_time', 'button_click') * @param fields - Metric data and measurements * @param context - Additional context for the metric * @param component - Component that recorded the metric * @param timestamp - Optional custom timestamp * @param clientId - Optional custom client ID */ constructor(name: string, fields: Record<string, number | string | boolean>, context: Record<string, unknown>, component: string, timestamp?: number, clientId?: string); /** * Convert to metric data format */ toMetricData(): MetricData; } /** * Error event for unhandled errors, exceptions, and error boundary catches */ declare class ErrorEvent extends LoggerBaseEvent { readonly error: Error; readonly handled: boolean; readonly context: Record<string, unknown>; readonly component: string; constructor(error: Error, handled: boolean, context: Record<string, unknown>, component: string, timestamp?: number, clientId?: string); /** * Get error name (constructor name or custom name) */ get name(): string; /** * Get error message */ get message(): string; /** * Get stack trace if available */ get stack(): string | undefined; /** * Convert to error data format */ toErrorData(): ErrorData; } /** * Logger lifecycle event - emitted when a logger is created */ declare class LoggerCreatedEvent extends LoggerBaseEvent { readonly name: string; readonly config: Record<string, unknown>; constructor(name: string, config: Record<string, unknown>, timestamp?: number, clientId?: string); } /** * Logger lifecycle event - emitted when a logger is destroyed */ declare class LoggerDestroyedEvent extends LoggerBaseEvent { readonly name: string; readonly reason?: string | undefined; constructor(name: string, reason?: string | undefined, timestamp?: number, clientId?: string); } /** * Transport event - emitted when transport operations occur */ declare class TransportEvent extends LoggerBaseEvent { readonly transportName: string; readonly operation: 'write' | 'flush' | 'close' | 'error'; readonly details: Record<string, unknown>; constructor(transportName: string, operation: 'write' | 'flush' | 'close' | 'error', details?: Record<string, unknown>, timestamp?: number, clientId?: string); } /** * Transport error event - emitted when transport operations fail */ declare class TransportErrorEvent extends LoggerBaseEvent { readonly transportName: string; readonly error: Error; readonly operation: string; readonly details: Record<string, unknown>; constructor(transportName: string, error: Error, operation: string, details?: Record<string, unknown>, timestamp?: number, clientId?: string); } /** * PII detection warning event - emitted in development when potential PII is detected */ declare class PIIWarningEvent extends LoggerBaseEvent { readonly field: string; readonly value: string; readonly pattern: string; readonly suggestion: string; readonly context: Record<string, unknown>; constructor(field: string, value: string, pattern: string, suggestion: string, context: Record<string, unknown>, timestamp?: number, clientId?: string); } /** * Logger configuration change event */ declare class LoggerConfigChangedEvent extends LoggerBaseEvent { readonly loggerName: string; readonly oldConfig: Record<string, unknown>; readonly newConfig: Record<string, unknown>; readonly changes: string[]; constructor(loggerName: string, oldConfig: Record<string, unknown>, newConfig: Record<string, unknown>, changes: string[], timestamp?: number, clientId?: string); } /** * Type guard to check if an event is a LogEvent */ declare function isLogEvent(event: unknown): event is LogEvent; /** * Type guard to check if an event is a MetricEvent */ declare function isMetricEvent(event: unknown): event is MetricEvent; /** * Type guard to check if an event is an ErrorEvent */ declare function isErrorEvent(event: unknown): event is ErrorEvent; /** * Type guard to check if an event is any logger-related event */ declare function isLoggerEvent(event: unknown): event is LoggerBaseEvent; /** * Logger configuration types and default values */ /** * Default log level for new loggers */ declare const DEFAULT_LOG_LEVEL: LogLevel; /** * Log level hierarchy for comparison * Higher numbers indicate higher priority */ declare const LOG_LEVEL_PRIORITY: Record<LogLevel, number>; /** * Default logger configuration */ declare const DEFAULT_LOGGER_CONFIG: Required<Omit<LoggerConfig, 'transports'>> & { transports: Transport[]; }; /** * Merges user configuration with defaults * * @param userConfig - User-provided configuration * @returns Complete configuration with defaults applied */ declare function mergeConfig(userConfig?: LoggerConfig): Required<LoggerConfig>; /** * Checks if a log level should be processed based on current minimum level * * @param level - Log level to check * @param minLevel - Minimum log level configured * @returns True if log should be processed */ declare function shouldLog(level: LogLevel, minLevel: LogLevel): boolean; /** * Applies sampling to determine if a log should be processed * * @param level - Log level * @param samplingRates - Sampling configuration * @returns True if log passes sampling check */ declare function passesSampling(level: LogLevel, samplingRates: Partial<Record<LogLevel, number>>): boolean; /** Core Logger Implementation - Standalone logger with transport system */ /** Core standalone logger implementation with transport system */ declare class LoggerImpl implements Logger { private readonly loggerName; private readonly transportRegistry; private readonly configuration; private readonly contextManager; private readonly redactionEngine; private destroyed; /** Creates a new logger instance */ constructor(config?: LoggerConfig, loggerName?: string); /** Logger name/identifier */ get name(): string; /** Current minimum log level */ get level(): LogLevel; /** Logs a trace-level message */ trace(message: string, ...args: readonly unknown[]): void; /** Logs a debug-level message */ debug(message: string, ...args: readonly unknown[]): void; /** Logs an info-level message */ info(message: string, ...args: readonly unknown[]): void; /** Logs a warning-level message */ warn(message: string, ...args: readonly unknown[]): void; /** Logs an error-level message */ error(message: string, ...args: readonly unknown[]): void; /** Records a structured metric */ metric(name: string, fields?: Record<string, number | string | boolean>): void; /** Creates a child logger with additional context */ withContext(additionalContext: Record<string, unknown>): Logger; /** Sets the minimum log level for this logger */ setLevel(level: LogLevel): void; /** Sets log level for a specific component */ setComponentLevel(component: string, level: LogLevel): void; /** Explicitly redacts a value using the configured redaction engine */ redact(value: unknown): string; /** Adds a transport to this logger */ addTransport(transport: Transport): void; /** Removes a transport from this logger */ removeTransport(transportName: string): boolean; /** Flushes all transports */ flush(): Promise<void>; /** Destroys the logger and cleans up resources */ destroy(): Promise<void>; /** Core logging method that handles all log levels */ private log; } /** Creates a new standalone logger instance */ declare function createLogger(config?: LoggerConfig): Logger; /** * Comprehensive PII Redaction System * * Advanced data protection system that automatically detects and redacts personally * identifiable information (PII) from log messages, structured data, and function * arguments. Uses pattern matching, field name detection, and customizable rules. * * Features: * - Built-in patterns for emails, phones, SSN, credit cards, API keys * - Field name detection (password, email, token, etc.) * - Configurable redaction modes (balanced, strict, permissive) * - Custom redaction patterns and functions * - Hash-based redaction for analytics preservation * - Performance monitoring and statistics * - Support for nested objects and arrays * * @example * ```typescript * import { RedactionEngine, redactString, redactObject } from '@nuanced-labs/lever-ui-logger'; * * // Global redaction functions * const safe = redactString('Contact user@example.com for help'); * // Result: "Contact <email> for help" * * const safeData = redactObject({ * username: 'john_doe', * password: 'secret123', * email: 'john@example.com', * age: 30 * }); * // Result: { username: '<redacted>', password: '<redacted>', email: '<redacted>', age: 30 } * * // Custom redaction engine * const engine = new RedactionEngine({ * enabled: true, * mode: 'strict', * hashRedaction: false, * customPatterns: [{ * name: 'internal-id', * pattern: /ID-\d{6}/g, * replacement: '<internal-id>', * priority: 100 * }] * }); * * const result = engine.redactString('User ID-123456 logged in'); * // Result: "User <internal-id> logged in" * ``` */ /** * Redaction modes with different levels of protection */ type RedactionMode = 'strict' | 'balanced' | 'permissive' | 'off'; /** * Performance statistics for redaction operations */ interface RedactionStats { /** Total redaction operations performed */ totalOperations: number; /** Total time spent on redaction (ms) */ totalTimeMs: number; /** Average time per operation (ms) */ averageTimeMs: number; /** Redactions performed by pattern name */ patternHits: Record<string, number>; /** Field redactions by field name */ fieldHits: Record<string, number>; } /** * Core redaction engine with pattern matching and field detection. * * Provides comprehensive PII redaction capabilities including: * - Pattern-based string redaction (emails, phones, API keys, etc.) * - Field name detection for sensitive data * - Configurable redaction modes * - Performance monitoring and statistics * - Hash-based redaction for analytics * - Differential privacy support * * @example * ```typescript * const engine = new RedactionEngine({ * mode: 'balanced', * enabled: true, * disabledPatterns: ['ipv4'] // Keep IP addresses for debugging * }); * * // Redact strings * const safe = engine.redactString('Contact user@example.com for help'); * // Result: 'Contact <email> for help' * * // Redact objects * const safeObj = engine.redactObject({ * username: 'john_doe', * password: 'secret123', * email: 'john@example.com' * }); * // Result: { username: '<redacted>', password: '<redacted>', email: '<redacted>' } * ``` */ declare class RedactionEngine { private readonly patterns; private readonly config; private readonly stats; private performanceWarningThreshold; constructor(config?: RedactionConfig); /** * Redacts PII from a string value using configured patterns and custom redactor. * * @param value - The string to redact PII from * @returns The string with PII replaced by redaction tokens * * @example * ```typescript * const engine = new RedactionEngine(); * engine.redactString('Contact user@example.com for help'); * // Returns: 'Contact <email> for help' * * engine.redactString('Call us at (555) 123-4567'); * // Returns: 'Call us at <phone>' * ``` */ redactString(value: string): string; /** * Redacts PII from an object, handling nested structures and circular references. * * @param obj - The object to redact PII from * @param visited - Internal WeakSet for tracking circular references * @returns The object with PII fields and string values redacted * * @example * ```typescript * const engine = new RedactionEngine(); * const user = { * name: 'John Doe', * email: 'john@example.com', * password: 'secret123', * profile: { * phone: '555-1234', * bio: 'Contact me at john@example.com' * } * }; * * engine.redactObject(user); * // Returns: { * // name: 'John Doe', * // email: '<redacted>', // Field name detected * // password: '<redacted>', // Field name detected * // profile: { * // phone: '<redacted>', // Field name detected * // bio: 'Contact me at <email>' // Pattern matched * // } * // } * ``` */ redactObject(obj: unknown, visited?: WeakSet<object>): unknown; /** * Redacts PII from log arguments array, processing each argument as an object. * * @param args - Array of log arguments to redact * @returns Array with PII redacted from each argument * * @example * ```typescript * const engine = new RedactionEngine(); * const logArgs = [ * 'User logged in', * { email: 'user@example.com', token: 'abc123' }, * 'Session started at user@example.com' * ]; * * engine.redactArgs(logArgs); * // Returns: [ * // 'User logged in', * // { email: '<redacted>', token: '<redacted>' }, * // 'Session started at <email>' * // ] * ``` */ redactArgs(args: readonly unknown[]): readonly unknown[]; /** * Adds Laplace noise to numeric values for differential privacy protection. * * @param value - The numeric value to add noise to * @param epsilon - Privacy budget parameter (default: 1.0, lower = more privacy) * @returns The value with differential privacy noise added * * @example * ```typescript * const engine = new RedactionEngine({ differentialPrivacy: true }); * * // Add noise with default epsilon (1.0) * const noisyValue = engine.addDifferentialPrivacyNoise(100); * // Returns: ~99.83 (varies each call) * * // More privacy (more noise) with lower epsilon * const privateValue = engine.addDifferentialPrivacyNoise(100, 0.1); * // Returns: ~107.42 (varies each call, larger deviation) * ``` */ addDifferentialPrivacyNoise(value: number, epsilon?: number): number; /** * Gets current redaction statistics including operation counts and performance metrics. * * @returns Copy of current redaction statistics * * @example * ```typescript * const engine = new RedactionEngine(); * engine.redactString('Contact user@example.com'); * engine.redactString('Call (555) 123-4567'); * * const stats = engine.getStats(); * // Returns: { * // totalOperations: 2, * // totalTimeMs: 0.43, * // averageTimeMs: 0.215, * // patternHits: { email: 1, 'phone-us': 1 }, * // fieldHits: {} * // } * ``` */ getStats(): RedactionStats; /** * Resets redaction statistics to initial values. * * @example * ```typescript * const engine = new RedactionEngine(); * engine.redactString('user@example.com'); // Creates stats * * console.log(engine.getStats().totalOperations); // 1 * engine.resetStats(); * console.log(engine.getStats().totalOperations); // 0 * ``` */ resetStats(): void; /** * Validates potential PII in development mode, checking against all patterns. * * @param value - String to validate for potential PII * @param context - Optional context description for warnings * @returns Array of warning messages for detected PII patterns * * @example * ```typescript * const engine = new RedactionEngine(); * const warnings = engine.validateForPII( * 'Contact user@example.com or call 555-1234', * 'user input' * ); * * // Returns: [ * // 'Potential Email addresses detected in user input: email', * // 'Potential US phone numbers detected in user input: phone-us' * // ] * ``` */ validateForPII(value: string, context?: string): string[]; /** * Merges user configuration with defaults */ private mergeConfig; /** * Initializes redaction patterns based on configuration */ private initializePatterns; /** * Filters patterns based on redaction mode */ private filterPatternsByMode; /** * Hash-based redaction for analytics preservation */ private hashValue; /** * Updates performance statistics */ private updateStats; /** * Initializes statistics tracking */ private initializeStats; } /** * Gets or creates the global redaction engine instance. * * @param config - Optional configuration to create new engine with * @returns Global redaction engine instance * * @example * ```typescript * // Get default engine * const engine = getRedactionEngine(); * * // Create new engine with custom config * const strictEngine = getRedactionEngine({ mode: 'strict' }); * ``` */ declare function getRedactionEngine(config?: RedactionConfig): RedactionEngine; /** * Convenience function for redacting strings using the global engine. * * @param value - String to redact PII from * @param config - Optional configuration for custom redaction behavior * @returns String with PII redacted * * @example * ```typescript * import { redactString } from '@nuanced-labs/lever-ui-logger'; * * const safe = redactString('Contact user@example.com for help'); * // Returns: 'Contact <email> for help' * * const strictSafe = redactString('Call 555-1234', { mode: 'strict' }); * // Returns: 'Call <phone>' * ``` */ declare function redactString(value: string, config?: RedactionConfig): string; /** * Convenience function for redacting objects using the global engine. * * @param obj - Object to redact PII from * @param config - Optional configuration for custom redaction behavior * @returns Object with PII redacted * * @example * ```typescript * import { redactObject } from '@nuanced-labs/lever-ui-logger'; * * const user = { email: 'user@example.com', password: 'secret' }; * const safe = redactObject(user); * // Returns: { email: '<redacted>', password: '<redacted>' } * * const hashRedacted = redactObject(user, { hashRedaction: true }); * // Returns: { email: '<hash:a1b2c3d4>', password: '<hash:e5f6g7h8>' } * ``` */ declare function redactObject(obj: unknown, config?: RedactionConfig): unknown; /** * Convenience function for redacting log arguments using the global engine. * * @param args - Array of log arguments to redact * @param config - Optional configuration for custom redaction behavior * @returns Array with PII redacted from each argument * * @example * ```typescript * import { redactArgs } from '@nuanced-labs/lever-ui-logger'; * * const logArgs = [ * 'Login attempt', * { user: 'john@example.com', ip: '192.168.1.1' }, * 'Session token: abc123xyz' * ]; * * const safe = redactArgs(logArgs); * // Returns: [ * // 'Login attempt', * // { user: '<redacted>', ip: '192.168.1.1' }, // IP not redacted in balanced mode * // 'Session token: abc123xyz' * // ] * ``` */ declare function redactArgs(args: readonly unknown[], config?: RedactionConfig): readonly unknown[]; /** * Built-in redaction patterns for common PII types */ interface BuiltInRedactionPattern { /** Pattern name for debugging and configuration */ name: string; /** Regular expression to match PII */ pattern: RegExp; /** Replacement text (can include capture groups) */ replacement: string; /** Description of what this pattern detects */ description: string; /** Whether this pattern is enabled by default */ defaultEnabled: boolean; /** Performance category for priority ordering */ priority: 'high' | 'medium' | 'low'; } /** * Built-in PII detection patterns * Ordered by detection priority (high performance patterns first) */ declare const BUILT_IN_PATTERNS: readonly BuiltInRedactionPattern[]; /** * Field names that commonly contain PII * These trigger redaction regardless of content */ declare const PII_FIELD_NAMES: readonly string[]; /** * Creates a case-insensitive field name matcher. * Uses exact matches and common patterns to avoid false positives. * * @param fieldName - The field name to check for PII indicators * @returns True if the field name indicates it may contain PII * * @example * ```typescript * isPIIFieldName('password'); // true * isPIIFieldName('userId'); // true * isPIIFieldName('userPassword'); // true (camelCase) * isPIIFieldName('user_email'); // true (underscore) * isPIIFieldName('auth-token'); // true (hyphen) * isPIIFieldName('message'); // false * isPIIFieldName('timestamp'); // false * ``` */ declare function isPIIFieldName(fieldName: string): boolean; /** * Gets enabled patterns based on configuration. * * @param enabledPatterns - Specific patterns to enable (overrides defaults) * @param disabledPatterns - Specific patterns to disable * @returns Array of enabled redaction patterns * * @example * ```typescript * // Get all default enabled patterns * const defaultPatterns = getEnabledPatterns(); * * // Only enable specific patterns * const emailOnly = getEnabledPatterns(['email']); * * // Enable defaults except IP addresses * const noIPs = getEnabledPatterns(undefined, ['ipv4', 'ipv6']); * ``` */ declare function getEnabledPatterns(enabledPatterns?: string[], disabledPatterns?: string[]): BuiltInRedactionPattern[]; /** * Sorts patterns by priority for optimal performance. * High priority patterns are processed first for better performance. * * @param patterns - Array of redaction patterns to sort * @returns Sorted array with high priority patterns first * * @example * ```typescript * const unsorted = [ * { name: 'low-pattern', priority: 'low', ... }, * { name: 'high-pattern', priority: 'high', ... }, * { name: 'medium-pattern', priority: 'medium', ... } * ]; * const sorted = sortPatternsByPriority(unsorted); * // Result: [high-pattern, medium-pattern, low-pattern] * ``` */ declare function sortPatternsByPriority(patterns: BuiltInRedactionPattern[]): BuiltInRedactionPattern[]; /** * Lever UI Logger - Standalone logging with PII redaction * * A zero-dependency logging system with optional EventBus integration * via transports. Includes built-in PII redaction capabilities. * * @example * ```typescript * import { createLogger, ConsoleTransport } from 'lever-ui-logger'; * * // Standalone logger * const logger = createLogger({ * level: 'debug', * component: 'my-service', * transports: [new ConsoleTransport()] * }); * * logger.info('User action completed', { userId: '123', action: 'login' }); * ``` */ /** Current version of the logger package */ declare const LOGGER_VERSION = "0.1.0"; /** * Transport interfaces and utilities for lever-ui-logger */ declare const Environment: { /** Check if running in browser environment */ readonly isBrowser: boolean; /** Check if running in Node.js environment */ readonly isNode: boolean; /** Check if running in production environment */ readonly isProduction: boolean; /** Check if console methods support styling */ readonly supportsConsoleStyles: boolean; }; /** * Console transport formatting modes */ type ConsoleFormatMode = 'json' | 'pretty' | 'compact'; /** * Console transport configuration */ interface ConsoleTransportConfig { /** Transport name (default: 'console') */ name?: string; /** Formatting mode for output */ format?: ConsoleFormatMode; /** Enable/disable colorized output */ colors?: boolean; /** Enable/disable timestamps */ timestamps?: boolean; /** Timestamp format string */ timestampFormat?: string; /** Enable/disable in production environments */ enableInProduction?: boolean; /** Maximum performance threshold in ms */ performanceThreshold?: number; /** Custom log level to console method mapping */ consoleMethods?: Partial<Record<LogLevel, string>>; } /** * Base transport class with common functionality */ declare abstract class BaseTransport implements Transport { readonly name: string; readonly config: Record<string, unknown>; constructor(name: string, config?: Record<string, unknown>); /** * Write a log event to this transport */ abstract write(_event: LogEventData): Promise<void> | void; /** * Flush any pending logs (default: no-op) */ flush(): Promise<void> | void; /** * Close the transport and clean up resources (default: no-op) */ close(): Promise<void> | void; /** * Check if transport should be active in current environment */ protected isEnabled(): boolean; /** * Measure performance of a function call */ protected measurePerformance<T>(fn: () => T, threshold?: number): T; } /** * Utility functions for formatting log data */ declare const Formatters: { /** * Format timestamp with configurable format */ readonly timestamp: (timestamp: number, format?: string) => string; /** * Pretty-print objects with indentation */ readonly prettyObject: (obj: unknown, indent?: number) => string; /** * Compact object representation */ readonly compactObject: (obj: unknown) => string; /** * Get log level priority for comparison */ readonly getLogLevelPriority: (level: LogLevel) => number; }; /** * ANSI color codes for terminal output */ declare const Colors: { readonly trace: "\u001B[36m"; readonly debug: "\u001B[34m"; readonly info: "\u001B[32m"; readonly warn: "\u001B[33m"; readonly error: "\u001B[31m"; readonly reset: "\u001B[0m"; readonly bold: "\u001B[1m"; readonly dim: "\u001B[2m"; readonly component: "\u001B[35m"; readonly timestamp: "\u001B[90m"; }; /** * Browser console styling */ declare const BrowserStyles: { readonly trace: "color: #00bcd4; font-weight: normal;"; readonly debug: "color: #2196f3; font-weight: normal;"; readonly info: "color: #4caf50; font-weight: normal;"; readonly warn: "color: #ff9800; font-weight: bold;"; readonly error: "color: #f44336; font-weight: bold;"; readonly component: "color: #9c27b0; font-weight: bold;"; readonly timestamp: "color: #666; font-weight: normal;"; }; /** * Console Transport with Advanced Formatting * * Cross-platform console transport that provides rich formatting, colorization, * and environment-specific optimizations. Supports both browser and Node.js * environments with appropriate styling and performance considerations. * * Features: * - Cross-platform support (browser/Node.js) * - Rich formatting with colors and styling * - Multiple format modes (pretty, compact, json) * - Performance monitoring and timing * - Level-specific console methods * - Grouping and indentation support * - Buffer management and flush control * * @example * ```typescript * import { ConsoleTransport } from '@nuanced-labs/lever-ui-logger'; * * // Basic console transport * const transport = new ConsoleTransport({ * level: 'info', * format: 'pretty', * colors: true, * timestamps: true * }); * * // Compact format for production * const compact = new ConsoleTransport({ * format: 'compact', * colors: false, * includeStack: false * }); * * // JSON format for log aggregation * const jsonTransport = new ConsoleTransport({ * format: 'json', * includeMetadata: true, * prettyPrint: false * }); * ``` */ /** * Console transport that outputs logs to the console with formatting and colors */ declare class ConsoleTransport extends BaseTransport { private readonly transportConfig; private readonly consoleMethods; constructor(config?: ConsoleTransportConfig); /** * Write a log event to the console */ write(event: LogEventData): void; /** * Check if transport should be active in current environment */ protected isEnabled(): boolean; /** * Initialize console method mapping */ private initializeConsoleMethods; /** * Format a log event according to the configured format */ private formatEvent; /** * Format data based on the configured format mode */ private formatData; /** * Write to console with browser CSS styles */ private writeWithBrowserStyles; /** * Write to console with ANSI colors */ private writeWithAnsiColors; /** * Write to console without colors */ private writeWithoutColors; } /** * Create a console transport with default configuration */ declare function createConsoleTransport(config?: ConsoleTransportConfig): ConsoleTransport; /** * Production-grade secure token handler for authentication tokens * * Provides comprehensive token security including: * - Memory protection against serialization attacks * - Token obfuscation using industry-standard techniques * - Comprehensive error message sanitization * - PII and token detection for debug outputs */ /** * Token provider function type */ type TokenProvider = () => string | Promise<string>; /** * Configuration for secure token handling */ interface SecureTokenConfig { /** Enable additional security measures (default: true) */ enableSecureMode?: boolean; /** Token expiration time in milliseconds (default: 1 hour) */ tokenTtl?: number; /** Enable token validation (default: true) */ validateToken?: boolean; /** Custom token validator function */ tokenValidator?: (_token: string) => boolean; } /** Secure token handler that prevents accidental token exposure */ declare class SecureTokenHandler { private readonly config; private readonly errorSanitizer; private tokenEntry; private tokenProvider; private disposed; private obfuscationKey; constructor(config?: SecureTokenConfig); /** * Set a static authentication token * * @param token - The authentication token to store securely * @throws Error if token is invalid or handler is disposed */ setToken(token: string | null): void; /** * Set a token provider function for dynamic token retrieval * * @param provider - Function that returns an authentication token * @throws Error if provider is invalid or handler is disposed */ setTokenProvider(provider: TokenProvider | null): void; /** * Retrieve the current authentication token * * @returns The current token or null if none available * @throws Error if token retrieval fails or handler is disposed */ getToken(): Promise<string | null>; /** * Check if a token is currently available and valid */ hasToken(): boolean; /** * Clear all token data and dispose resources * * This method should be called when the handler is no longer needed * to ensure tokens are properly cleared from memory. */ dispose(): void; /** * Create a secure JSON replacer function that sanitizes sensitive data */ createSecureReplacer(): (_key: string, _value: unknown) => unknown; /** * Sanitize HTTP headers to remove or mask authentication tokens * * @param headers - Headers object to sanitize * @returns New headers object with sensitive values masked */ sanitizeHeaders(headers: Record<string, string>): Record<string, string>; /** * Mask a token showing first and last few characters * * @param token - Token to mask * @returns Masked token */ maskToken(token: string): string; /** * Force sanitization of a value using masking strategy */ private forceSanitizeValue; /** * Default token validator */ private defaultTokenValidator; /** * Check if handler is disposed */ private checkDisposed; /** * Check if a token entry is valid and not expired */ private isTokenValid; /** * Multi-round obfuscation to protect tokens in memory using session key. * Uses a combination of XOR, character substitution, and encoding rounds * of transformation to protect tokens in memory against casual inspection * and memory dumps. Not meant for cryptographic security but provides * defense-in-depth against token extraction. */ private obfuscateToken; /** * Reverse the multi-round obfuscation process */ private deobfuscateToken; /** * XOR cipher implementation */ private xorCipher; /** * Character substitution using a custom mapping */ private substituteChars; /** * Reverse character substitution */ private reverseSubstituteChars; /** * Encode the obfuscated string using base64 or similar */ private encodeObfuscated; /** * Decode the obfuscated string */ private decodeObfuscated; /** * Sanitize error messages to prevent token leakage */ sanitizeErrorMessage(errorMessage: string): string; /** * Create character substitution map */ private createSubstitutionMap; /** * Create reverse substitution map */ private createReverseSubstitutionMap; /** * Simple encoding fallback for environments without btoa */ private simpleEncode; /** * Simple decoding fallback for environments without atob */ private simpleDecode; /** * Generate a random string for token clearing */ private generateRandomString; /** * Get or generate the session-specific obfuscation key */ private getObfuscationKey; /** * Make object non-serializable to prevent token leakage */ private makeNonSerializable; /** * Remove non-serializable protection (for disposal) */ private removeNonSerializable; } /** * Default secure token handler instance for immediate use */ declare const defaultSecureTokenHandler: SecureTokenHandler; /** * SendBeacon transport for efficient telemetry data transmission * * Provides efficient batching, offline support, and automatic retry capabilities * for sending telemetry data to remote endpoints using the sendBeacon API with * fetch fallback for maximum compatibility. * * @example * ```typescript * import { SendBeaconTransport } from '@nuanced-labs/lever-ui-logger'; * * const transport = new SendBeaconTransport({ * endpoint: 'https://api.example.com/telemetry', * batchSize: 100, * flushInterval: 10000, * authToken: 'your-api-token', * enableOfflineStorage: true * }); * * // Use with logger * const logger = createLogger(eventBus, { * transports: [transport] * }); * ``` */ /** * Telemetry envelope metadata structure for wrapping log events * * Contains session and user context along with the batch of log events * being transmitted to the telemetry endpoint. */ interface TelemetryEnvelope { /** Unique session identifier */ sessionId: string; /** Optional user identifier */ userId?: string; /** User agent string */ userAgent: string; /** Browser/client timezone */ timezone: string; /** Timestamp of the envelope creation */ timestamp: number; /** Array of log events */ events: LogEventData[]; /** Number of events in this batch */ eventCount: number; /** Total size in bytes (estimated) */ sizeBytes: number; } /** * Configuration options for SendBeacon transport * * @example * ```typescript * const config: SendBeaconTransportConfig = { * endpoint: 'https://api.example.com/logs', * batchSize: 50, * flushInterval: 5000, * maxPayloadSize: 64 * 1024, * authToken: () => getAuthToken(), * enableOfflineStorage: true, * rateLimitPerMinute: 1000 * }; * ``` */ interface SendBeaconTransportConfig { /** Transport name */ name?: string; /** Endpoint URL for sending telemetry */ endpoint: string; /** Maximum batch size (number of events) */ batchSize?: number; /** Flush interval in milliseconds */ flushInterval?: number; /** Maximum payload size in bytes (default ~64KB for sendBeacon) */ maxPayloadSize?: number; /** Enable offline storage */ enableOfflineStorage?: boolean; /** Storage key prefix for offline logs */ storageKeyPrefix?: string; /** Maximum retry attempts */ maxRetries?: number; /** Initial retry delay in milliseconds */ retryDelay?: number; /** Authentication token or function to get token */ authToken?: string | TokenProvider; /** Enable secure token handling (default: true) */ enableSecureTokenHandling?: boolean; /** Custom headers for requests */ headers?: Record<string, string>; /** Enable compression if available */ enableCompression?: boolean; /** Session ID generator function */ sessionIdGenerator?: () => string; /** User ID provider function */ userIdProvider?: () => string | undefined; /** Rate limit: max events per minute */ rateLimitPerMinute?: number; /** Enable automatic page lifecycle handling */ enableLifecycleHandling?: boolean; } /** * SendBeacon transport for efficient telemetry transmission * * High-performance transport that uses the sendBeacon API when available, * falling back to fetch with keepalive. Provides intelligent batching, * offline storage, retry logic, and lifecycle management. * * Features: * - Automatic batching with size and time-based flushing * - sendBeacon API with fetch fallback * - Offline storage with localStorage * - Exponential backoff retry logic * - Rate limiting and abuse prevention * - Page lifecycle event handling * - Bearer token authentication * - Circular reference protection * * @example * ```typescript * const transport = new SendBeaconTransport({ * endpoint: 'https://telemetry.example.com/logs', * batchSize: 100, * flushInterval: 10000, * authToken: 'bearer-token', * enableOfflineStorage: true, * userIdProvider: () => getCurrentUserId() * }); * ``` */ declare class SendBeaconTransport extends BaseTransport { private readonly transportConfig; private rea