logixia 1.2.1 → 1.3.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.
Files changed (59) hide show
  1. package/dist/{index-BDRSTjUt.d.ts → index-CHIsdA9n.d.ts} +53 -2
  2. package/dist/index-CHIsdA9n.d.ts.map +1 -0
  3. package/dist/{index-Drrzn-Yg.d.mts → index-iDTW2-eY.d.mts} +53 -2
  4. package/dist/index-iDTW2-eY.d.mts.map +1 -0
  5. package/dist/index.d.mts +89 -3
  6. package/dist/index.d.mts.map +1 -1
  7. package/dist/index.d.ts +89 -3
  8. package/dist/index.d.ts.map +1 -1
  9. package/dist/index.js +5 -2
  10. package/dist/index.js.map +1 -1
  11. package/dist/index.mjs +3 -3
  12. package/dist/index.mjs.map +1 -1
  13. package/dist/{logitron-logger.module-iO8DPE7_.mjs → logitron-logger.module-2AzkadqZ.mjs} +226 -8
  14. package/dist/logitron-logger.module-2AzkadqZ.mjs.map +1 -0
  15. package/dist/{logitron-logger.module-X6nGDVGC.js → logitron-logger.module-BqNKp0Fs.js} +240 -4
  16. package/dist/logitron-logger.module-BqNKp0Fs.js.map +1 -0
  17. package/dist/{logitron-logger.module-CY3t8yK6.d.mts → logitron-logger.module-C0G8JGVf.d.ts} +6 -4
  18. package/dist/logitron-logger.module-C0G8JGVf.d.ts.map +1 -0
  19. package/dist/{logitron-logger.module-DgEldK9V.d.ts → logitron-logger.module-DQKaZTJL.d.mts} +6 -4
  20. package/dist/logitron-logger.module-DQKaZTJL.d.mts.map +1 -0
  21. package/dist/middleware.d.mts +83 -0
  22. package/dist/middleware.d.mts.map +1 -0
  23. package/dist/middleware.d.ts +83 -0
  24. package/dist/middleware.d.ts.map +1 -0
  25. package/dist/middleware.js +132 -0
  26. package/dist/middleware.js.map +1 -0
  27. package/dist/middleware.mjs +130 -0
  28. package/dist/middleware.mjs.map +1 -0
  29. package/dist/nest.d.mts +2 -2
  30. package/dist/nest.d.ts +2 -2
  31. package/dist/nest.js +2 -2
  32. package/dist/nest.mjs +2 -2
  33. package/dist/testing.d.mts +67 -0
  34. package/dist/testing.d.mts.map +1 -0
  35. package/dist/testing.d.ts +67 -0
  36. package/dist/testing.d.ts.map +1 -0
  37. package/dist/testing.js +164 -0
  38. package/dist/testing.js.map +1 -0
  39. package/dist/testing.mjs +163 -0
  40. package/dist/testing.mjs.map +1 -0
  41. package/dist/{transport.manager-Vi__pagn.mjs → transport.manager-5VVdqS3o.mjs} +51 -2
  42. package/dist/transport.manager-5VVdqS3o.mjs.map +1 -0
  43. package/dist/{transport.manager-C3Xr7Tvi.js → transport.manager-DCOm4uIQ.js} +51 -2
  44. package/dist/transport.manager-DCOm4uIQ.js.map +1 -0
  45. package/dist/transports.d.mts +38 -1
  46. package/dist/transports.d.mts.map +1 -1
  47. package/dist/transports.d.ts +38 -1
  48. package/dist/transports.d.ts.map +1 -1
  49. package/dist/transports.js +1 -1
  50. package/dist/transports.mjs +1 -1
  51. package/package.json +21 -1
  52. package/dist/index-BDRSTjUt.d.ts.map +0 -1
  53. package/dist/index-Drrzn-Yg.d.mts.map +0 -1
  54. package/dist/logitron-logger.module-CY3t8yK6.d.mts.map +0 -1
  55. package/dist/logitron-logger.module-DgEldK9V.d.ts.map +0 -1
  56. package/dist/logitron-logger.module-X6nGDVGC.js.map +0 -1
  57. package/dist/logitron-logger.module-iO8DPE7_.mjs.map +0 -1
  58. package/dist/transport.manager-C3Xr7Tvi.js.map +0 -1
  59. package/dist/transport.manager-Vi__pagn.mjs.map +0 -1
@@ -1 +0,0 @@
1
- {"version":3,"file":"transport.manager-C3Xr7Tvi.js","names":["config: ConsoleTransportConfig","parts: string[]","config: DatabaseTransportConfig","config: any","transformed: Record<string, unknown>","promises: Promise<void>[]","fs","path","flattened: Record<string, unknown>","chunks: T[][]","chunks: T[][]","EventEmitter","transportEntry: TransportLogEntry","writePromises: Promise<void>[]","readyPromises: Promise<boolean>[]","flushPromises: Promise<void>[]","closePromises: Promise<void>[]","details: Record<string, unknown>","readline"],"sources":["../src/utils/internal-log.ts","../src/transports/console.transport.ts","../src/transports/database.transport.ts","../src/transports/analytics.transport.ts","../src/transports/datadog.transport.ts","../src/transports/file.transport.ts","../src/transports/google-analytics.transport.ts","../src/transports/mixpanel.transport.ts","../src/transports/segment.transport.ts","../src/transports/transport.manager.ts"],"sourcesContent":["/**\n * Internal logging helpers for use within the logixia library itself.\n *\n * These functions write directly to stderr/stdout without going through\n * LogixiaLogger — this avoids circular dependencies and ensures internal\n * diagnostics still surface even when the logger is misconfigured.\n *\n * Library code must NEVER call console.log/warn/error directly. Use these\n * helpers instead so that internal output can be silenced in tests by setting\n * the LOGIXIA_SILENT_INTERNAL=1 environment variable.\n */\n\nconst silent = process.env.LOGIXIA_SILENT_INTERNAL === '1';\n\n/**\n * Emit an internal debug/info message to stderr.\n * Use for field-enable/disable notifications that a developer might want to see\n * during development but should not appear in production log streams.\n */\nexport function internalLog(message: string): void {\n if (!silent) {\n process.stderr.write(`[logixia] ${message}\\n`);\n }\n}\n\n/**\n * Emit an internal warning to stderr.\n * Use when something is misconfigured but logixia can continue operating.\n */\nexport function internalWarn(message: string): void {\n if (!silent) {\n process.stderr.write(`[logixia:warn] ${message}\\n`);\n }\n}\n\n/**\n * Emit an internal error to stderr.\n * Use when a transport write fails or a serious internal error occurs.\n */\nexport function internalError(message: string, error?: unknown): void {\n if (!silent) {\n let errStr = '';\n if (error instanceof Error) {\n errStr = ` — ${error.message}`;\n } else if (error != null) {\n errStr = ` — ${String(error)}`;\n }\n process.stderr.write(`[logixia:error] ${message}${errStr}\\n`);\n }\n}\n","import type {\n ConsoleTransportConfig,\n ITransport,\n TransportLogEntry,\n} from '../types/transport.types';\n\nexport class ConsoleTransport implements ITransport {\n public readonly name = 'console';\n\n // Pre-built ANSI color map — avoids object recreation inside formatEntry()\n private static readonly COLORS: ReadonlyMap<string, string> = new Map([\n ['red', '\\x1b[31m'],\n ['green', '\\x1b[32m'],\n ['yellow', '\\x1b[33m'],\n ['blue', '\\x1b[34m'],\n ['magenta', '\\x1b[35m'],\n ['cyan', '\\x1b[36m'],\n ['white', '\\x1b[37m'],\n ['gray', '\\x1b[90m'],\n ['reset', '\\x1b[0m'],\n ]);\n\n constructor(private config: ConsoleTransportConfig = {}) {}\n\n write(entry: TransportLogEntry): Promise<void> {\n const formatted = this.formatEntry(entry) + '\\n';\n // Use process.stderr for errors, stdout for everything else —\n // avoids the extra indirection that console.log/error add.\n const out = entry.level.toLowerCase() === 'error' ? process.stderr : process.stdout;\n out.write(formatted);\n return Promise.resolve();\n }\n\n private formatEntry(entry: TransportLogEntry): string {\n if (this.config.format === 'json') {\n return JSON.stringify(\n {\n timestamp: this.config.timestamp !== false ? entry.timestamp.toISOString() : undefined,\n level: entry.level,\n message: entry.message,\n ...(entry.data || {}),\n context: entry.context,\n traceId: entry.traceId,\n appName: entry.appName,\n environment: entry.environment,\n },\n null,\n 2\n );\n }\n\n // Text format\n const parts: string[] = [];\n\n // Timestamp\n if (this.config.timestamp !== false) {\n const timestamp = entry.timestamp.toISOString();\n parts.push(this.colorize(timestamp, 'gray'));\n }\n\n // Level\n const level = entry.level.toUpperCase().padEnd(5);\n const coloredLevel = this.colorize(level, this.getLevelColor(entry.level));\n parts.push(coloredLevel);\n\n // Context\n if (entry.context) {\n const context = `[${entry.context}]`;\n parts.push(this.colorize(context, 'cyan'));\n }\n\n // Trace ID\n if (entry.traceId) {\n const traceId = `(${entry.traceId})`;\n parts.push(this.colorize(traceId, 'magenta'));\n }\n\n // Message\n parts.push(entry.message);\n\n // Data\n if (entry.data && Object.keys(entry.data).length > 0) {\n const data = JSON.stringify(entry.data);\n parts.push(this.colorize(data, 'blue'));\n }\n\n return parts.join(' ');\n }\n\n private getLevelColor(level: string): string {\n const colors: Record<string, string> = {\n error: 'red',\n warn: 'yellow',\n warning: 'yellow',\n info: 'green',\n debug: 'blue',\n trace: 'magenta',\n verbose: 'cyan',\n };\n\n return colors[level.toLowerCase()] || 'white';\n }\n\n private colorize(text: string, color: string): string {\n if (this.config.colorize === false) return text;\n // Use the static pre-built map — no per-call object allocation\n const reset = ConsoleTransport.COLORS.get('reset')!;\n const code = ConsoleTransport.COLORS.get(color) ?? ConsoleTransport.COLORS.get('white')!;\n return `${code}${text}${reset}`;\n }\n\n close(): Promise<void> {\n return Promise.resolve();\n }\n}\n","import type {\n DatabaseTransportConfig,\n IAsyncTransport,\n IBatchTransport,\n TransportLogEntry,\n} from '../types/transport.types';\nimport { internalError } from '../utils/internal-log';\n\nexport class DatabaseTransport implements IAsyncTransport, IBatchTransport {\n public readonly name = 'database';\n public readonly batchSize: number;\n public readonly flushInterval: number;\n\n private batch: TransportLogEntry[] = [];\n private flushTimer?: NodeJS.Timeout;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any -- dynamic database driver connection object\n private connection: any;\n private isConnected = false;\n private connectionPromise?: Promise<void>;\n\n constructor(private config: DatabaseTransportConfig) {\n this.batchSize = config.batchSize || 100;\n this.flushInterval = config.flushInterval || 5000; // 5 seconds\n this.setupFlushTimer();\n }\n\n async write(entry: TransportLogEntry): Promise<void> {\n if (!this.isConnected) {\n await this.connect();\n }\n\n this.addToBatch(entry);\n\n if (this.batch.length >= this.batchSize) {\n await this.flush();\n }\n }\n\n addToBatch(entry: TransportLogEntry): void {\n this.batch.push(entry);\n }\n\n async flush(): Promise<void> {\n if (this.batch.length === 0) return;\n\n const entriesToFlush = [...this.batch];\n this.batch = [];\n\n try {\n switch (this.config.type) {\n case 'mongodb':\n await this.flushToMongoDB(entriesToFlush);\n break;\n case 'postgresql':\n await this.flushToPostgreSQL(entriesToFlush);\n break;\n case 'mysql':\n await this.flushToMySQL(entriesToFlush);\n break;\n case 'sqlite':\n await this.flushToSQLite(entriesToFlush);\n break;\n default:\n throw new Error(`Unsupported database type: ${this.config.type}`);\n }\n } catch (error) {\n internalError('Database flush error', error);\n // Re-add failed entries to batch for retry\n this.batch.unshift(...entriesToFlush);\n throw error;\n }\n }\n\n async isReady(): Promise<boolean> {\n try {\n if (!this.isConnected) {\n await this.connect();\n }\n return this.isConnected;\n } catch {\n return false;\n }\n }\n\n private async connect(): Promise<void> {\n if (this.connectionPromise) {\n return this.connectionPromise;\n }\n\n this.connectionPromise = this.establishConnection();\n return this.connectionPromise;\n }\n\n private async establishConnection(): Promise<void> {\n try {\n switch (this.config.type) {\n case 'mongodb':\n await this.connectMongoDB();\n break;\n case 'postgresql':\n await this.connectPostgreSQL();\n break;\n case 'mysql':\n await this.connectMySQL();\n break;\n case 'sqlite':\n await this.connectSQLite();\n break;\n }\n this.isConnected = true;\n } catch (error) {\n this.isConnected = false;\n throw new Error(`Database connection failed: ${error}`, { cause: error });\n }\n }\n\n private async connectMongoDB(): Promise<void> {\n try {\n const { MongoClient } = await import('mongodb').catch(() => {\n throw new Error('MongoDB driver not installed. Run: npm install mongodb');\n });\n const connectionString =\n this.config.connectionString ||\n `mongodb://${this.config.host}:${this.config.port}/${this.config.database}`;\n\n this.connection = new MongoClient(connectionString);\n await this.connection.connect();\n\n // Test connection\n await this.connection.db(this.config.database).admin().ping();\n } catch (error) {\n throw new Error(`MongoDB connection failed: ${error}`, { cause: error });\n }\n }\n\n private async connectPostgreSQL(): Promise<void> {\n try {\n const { Client } = await import('pg').catch(() => {\n throw new Error('PostgreSQL driver not installed. Run: npm install pg @types/pg');\n });\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any -- pg.Client accepts any config shape\n const config: any = {\n connectionString: this.config.connectionString,\n host: this.config.host,\n port: this.config.port,\n database: this.config.database,\n };\n\n if (this.config.username) config.user = this.config.username;\n if (this.config.password) config.password = this.config.password;\n if (this.config.ssl) config.ssl = typeof this.config.ssl === 'boolean' ? {} : this.config.ssl;\n\n this.connection = new Client(config);\n\n await this.connection.connect();\n await this.createPostgreSQLTable();\n } catch (error) {\n throw new Error(`PostgreSQL connection failed: ${error}`, { cause: error });\n }\n }\n\n private async connectMySQL(): Promise<void> {\n try {\n const mysql = await import('mysql2/promise').catch(() => {\n throw new Error('MySQL driver not installed. Run: npm install mysql2');\n });\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any -- mysql2 accepts any config shape\n const config: any = {\n host: this.config.host,\n port: this.config.port,\n database: this.config.database,\n };\n\n if (this.config.username) config.user = this.config.username;\n if (this.config.password) config.password = this.config.password;\n if (this.config.ssl) config.ssl = typeof this.config.ssl === 'boolean' ? {} : this.config.ssl;\n\n this.connection = await mysql.createConnection(config);\n\n await this.createMySQLTable();\n } catch (error) {\n throw new Error(`MySQL connection failed: ${error}`, { cause: error });\n }\n }\n\n private async connectSQLite(): Promise<void> {\n try {\n const sqlite3 = await import('sqlite3').catch(() => {\n throw new Error('SQLite driver not installed. Run: npm install sqlite3 sqlite');\n });\n const { open } = await import('sqlite').catch(() => {\n throw new Error('SQLite driver not installed. Run: npm install sqlite3 sqlite');\n });\n\n this.connection = await open({\n filename: this.config.database,\n driver: sqlite3.Database,\n });\n\n await this.createSQLiteTable();\n } catch (error) {\n throw new Error(`SQLite connection failed: ${error}`, { cause: error });\n }\n }\n\n private async flushToMongoDB(entries: TransportLogEntry[]): Promise<void> {\n const db = this.connection.db(this.config.database);\n const collection = db.collection(this.config.collection || 'logs');\n\n const documents = entries.map((entry) => ({\n timestamp: entry.timestamp,\n level: entry.level,\n message: entry.message,\n payload: entry.data,\n context: entry.context,\n traceId: entry.traceId,\n appName: entry.appName,\n environment: entry.environment,\n }));\n\n await collection.insertMany(documents);\n }\n\n private async flushToPostgreSQL(entries: TransportLogEntry[]): Promise<void> {\n const tableName = this.config.table || 'logs';\n const values = entries.map((entry) => [\n entry.timestamp,\n entry.level,\n entry.message,\n JSON.stringify(entry.data || {}),\n entry.context,\n entry.traceId,\n entry.appName,\n entry.environment,\n ]);\n\n const placeholders = values\n .map(\n (_, i) =>\n `($${i * 9 + 1}, $${i * 9 + 2}, $${i * 9 + 3}, $${i * 9 + 4}, $${i * 9 + 5}, $${i * 9 + 6}, $${i * 9 + 7}, $${i * 9 + 8}, $${i * 9 + 9})`\n )\n .join(', ');\n\n const query = `\n INSERT INTO ${tableName} \n (timestamp, level, message, payload, context, trace_id, app_name, environment)\n VALUES ${placeholders}\n `;\n\n await this.connection.query(query, values.flat());\n }\n\n private async flushToMySQL(entries: TransportLogEntry[]): Promise<void> {\n const tableName = this.config.table || 'logs';\n const values = entries.map((entry) => [\n entry.timestamp,\n entry.level,\n entry.message,\n JSON.stringify(entry.data || {}),\n entry.context,\n entry.traceId,\n entry.appName,\n entry.environment,\n ]);\n\n const query = `\n INSERT INTO ${tableName} \n (timestamp, level, message, payload, context, trace_id, app_name, environment)\n VALUES ?\n `;\n\n await this.connection.query(query, [values]);\n }\n\n private async flushToSQLite(entries: TransportLogEntry[]): Promise<void> {\n const tableName = this.config.table || 'logs';\n\n const stmt = await this.connection.prepare(`\n INSERT INTO ${tableName} \n (timestamp, level, message, payload, context, trace_id, app_name, environment)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?)\n `);\n\n for (const entry of entries) {\n await stmt.run(\n entry.timestamp instanceof Date ? entry.timestamp.toISOString() : entry.timestamp,\n entry.level,\n entry.message,\n JSON.stringify(entry.data || {}),\n entry.context,\n entry.traceId,\n entry.appName,\n entry.environment\n );\n }\n\n await stmt.finalize();\n }\n\n private async createPostgreSQLTable(): Promise<void> {\n const tableName = this.config.table || 'logs';\n const query = `\n CREATE TABLE IF NOT EXISTS ${tableName} (\n id SERIAL PRIMARY KEY,\n timestamp TIMESTAMP WITH TIME ZONE NOT NULL,\n level VARCHAR(20) NOT NULL,\n message TEXT NOT NULL,\n payload JSONB,\n context VARCHAR(255),\n trace_id VARCHAR(255),\n app_name VARCHAR(255),\n environment VARCHAR(50),\n time_taken INTEGER,\n created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP\n )\n `;\n\n await this.connection.query(query);\n\n // Create indexes for better performance\n await this.connection.query(\n `CREATE INDEX IF NOT EXISTS idx_${tableName}_timestamp ON ${tableName} (timestamp)`\n );\n await this.connection.query(\n `CREATE INDEX IF NOT EXISTS idx_${tableName}_level ON ${tableName} (level)`\n );\n await this.connection.query(\n `CREATE INDEX IF NOT EXISTS idx_${tableName}_trace_id ON ${tableName} (trace_id)`\n );\n }\n\n private async createMySQLTable(): Promise<void> {\n const tableName = this.config.table || 'logs';\n const query = `\n CREATE TABLE IF NOT EXISTS ${tableName} (\n id INT AUTO_INCREMENT PRIMARY KEY,\n timestamp DATETIME NOT NULL,\n level VARCHAR(20) NOT NULL,\n message TEXT NOT NULL,\n payload JSON,\n context VARCHAR(255),\n trace_id VARCHAR(255),\n app_name VARCHAR(255),\n environment VARCHAR(50),\n time_taken INT,\n created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,\n INDEX idx_timestamp (timestamp),\n INDEX idx_level (level),\n INDEX idx_trace_id (trace_id)\n )\n `;\n\n await this.connection.execute(query);\n }\n\n private async createSQLiteTable(): Promise<void> {\n const tableName = this.config.table || 'logs';\n const query = `\n CREATE TABLE IF NOT EXISTS ${tableName} (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n timestamp TEXT NOT NULL,\n level TEXT NOT NULL,\n message TEXT NOT NULL,\n payload TEXT,\n context TEXT,\n trace_id TEXT,\n app_name TEXT,\n environment TEXT,\n time_taken INTEGER,\n created_at DATETIME DEFAULT CURRENT_TIMESTAMP\n )\n `;\n\n await this.connection.exec(query);\n\n // Create indexes\n await this.connection.exec(\n `CREATE INDEX IF NOT EXISTS idx_${tableName}_timestamp ON ${tableName} (timestamp)`\n );\n await this.connection.exec(\n `CREATE INDEX IF NOT EXISTS idx_${tableName}_level ON ${tableName} (level)`\n );\n await this.connection.exec(\n `CREATE INDEX IF NOT EXISTS idx_${tableName}_trace_id ON ${tableName} (trace_id)`\n );\n }\n\n private setupFlushTimer(): void {\n this.flushTimer = setInterval(() => {\n this.flush().catch((error: unknown) => {\n internalError('Scheduled database flush error', error);\n });\n }, this.flushInterval);\n }\n\n async close(): Promise<void> {\n if (this.flushTimer) {\n clearInterval(this.flushTimer);\n }\n\n // Flush remaining entries\n await this.flush();\n\n // Close connection\n if (this.connection) {\n switch (this.config.type) {\n case 'mongodb':\n await this.connection.close();\n break;\n case 'postgresql':\n await this.connection.end();\n break;\n case 'mysql':\n await this.connection.end();\n break;\n case 'sqlite':\n await this.connection.close();\n break;\n }\n }\n\n this.isConnected = false;\n }\n\n // Utility methods\n getBatchInfo() {\n return {\n batchSize: this.batchSize,\n currentBatchLength: this.batch.length,\n flushInterval: this.flushInterval,\n isConnected: this.isConnected,\n };\n }\n\n async getLogCount(): Promise<number> {\n if (!this.isConnected) return 0;\n\n try {\n switch (this.config.type) {\n case 'mongodb': {\n const collection = this.connection\n .db(this.config.database)\n .collection(this.config.collection || 'logs');\n return await collection.countDocuments();\n }\n\n case 'postgresql':\n case 'mysql':\n case 'sqlite': {\n const tableName = this.config.table || 'logs';\n const result = await this.connection.query(`SELECT COUNT(*) as count FROM ${tableName}`);\n return result.rows?.[0]?.count || result[0]?.count || 0;\n }\n\n default:\n return 0;\n }\n } catch {\n return 0;\n }\n }\n}\n","import type {\n AnalyticsTransportConfig,\n IBatchTransport,\n ITransport,\n TransportLogEntry,\n} from '../types/transport.types';\nimport { internalError } from '../utils/internal-log';\n\nexport abstract class AnalyticsTransport implements ITransport, IBatchTransport {\n public readonly name: string;\n public readonly level?: string | undefined;\n public readonly batchSize?: number;\n public readonly flushInterval?: number;\n\n protected config: AnalyticsTransportConfig;\n protected batch: TransportLogEntry[] = [];\n protected batchTimer?: NodeJS.Timeout;\n protected isReady: boolean = false;\n\n constructor(name: string, config: AnalyticsTransportConfig) {\n this.name = name;\n this.config = {\n batchSize: 50,\n flushInterval: 10000, // 10 seconds\n enableUserTracking: true,\n enableEventTracking: true,\n ...config,\n };\n this.level = config.level;\n this.batchSize = this.config.batchSize || 50;\n this.flushInterval = this.config.flushInterval || 10000;\n\n this.initialize();\n }\n\n async write(entry: TransportLogEntry): Promise<void> {\n if (!this.isReady) {\n await this.waitForReady();\n }\n\n if (this.shouldSkipEntry(entry)) {\n return;\n }\n\n if (this.config.batchSize && this.config.batchSize > 1) {\n this.addToBatch(entry);\n } else {\n await this.sendEntry(entry);\n }\n }\n\n addToBatch(entry: TransportLogEntry): void {\n this.batch.push(entry);\n\n if (this.batch.length >= (this.config.batchSize || 50)) {\n this.flush().catch((err: unknown) => internalError(`${this.name} batch flush failed`, err));\n } else if (!this.batchTimer && this.config.flushInterval) {\n this.batchTimer = setTimeout(() => {\n this.flush().catch((err: unknown) =>\n internalError(`${this.name} interval flush failed`, err)\n );\n }, this.config.flushInterval);\n }\n }\n\n async flush(): Promise<void> {\n if (this.batch.length === 0) return;\n\n const entriesToSend = [...this.batch];\n this.batch = [];\n\n if (this.batchTimer) {\n clearTimeout(this.batchTimer);\n delete this.batchTimer;\n }\n\n try {\n await this.sendBatch(entriesToSend);\n } catch (error) {\n internalError(`Analytics transport ${this.name} flush failed`, error);\n // Re-add failed entries to batch for retry\n this.batch.unshift(...entriesToSend);\n }\n }\n\n async close(): Promise<void> {\n await this.flush();\n if (this.batchTimer) {\n clearTimeout(this.batchTimer);\n }\n await this.cleanup();\n }\n\n protected shouldSkipEntry(entry: TransportLogEntry): boolean {\n // Skip debug/trace logs for analytics by default\n const skipLevels = ['debug', 'trace'];\n return skipLevels.includes(entry.level.toLowerCase());\n }\n\n protected transformEntry(entry: TransportLogEntry): Record<string, unknown> {\n const transformed: Record<string, unknown> = {\n timestamp: entry.timestamp.toISOString(),\n level: entry.level,\n message: entry.message,\n ...entry.data,\n };\n\n if (entry.context) {\n transformed.context = entry.context;\n }\n\n if (entry.traceId) {\n transformed.traceId = entry.traceId;\n }\n\n if (entry.appName) {\n transformed.appName = entry.appName;\n }\n\n if (entry.environment) {\n transformed.environment = entry.environment;\n }\n\n // Add custom properties\n if (this.config.customProperties) {\n Object.assign(transformed, this.config.customProperties);\n }\n\n return transformed;\n }\n\n protected async waitForReady(timeout: number = 5000): Promise<void> {\n const startTime = Date.now();\n while (!this.isReady && Date.now() - startTime < timeout) {\n await new Promise((resolve) => setTimeout(resolve, 100));\n }\n if (!this.isReady) {\n throw new Error(`Analytics transport ${this.name} failed to initialize within ${timeout}ms`);\n }\n }\n\n // Abstract methods to be implemented by specific analytics providers\n protected abstract initialize(): Promise<void> | void;\n protected abstract sendEntry(entry: TransportLogEntry): Promise<void>;\n protected abstract sendBatch(entries: TransportLogEntry[]): Promise<void>;\n protected abstract cleanup(): Promise<void> | void;\n}\n\n// Analytics Event Types\nexport interface AnalyticsEvent {\n name: string;\n properties?: Record<string, unknown>;\n userId?: string;\n sessionId?: string;\n timestamp?: Date;\n}\n\nexport interface AnalyticsUser {\n id: string;\n properties?: Record<string, unknown>;\n traits?: Record<string, unknown>;\n}\n\nexport interface AnalyticsMetric {\n name: string;\n value: number;\n unit?: string;\n tags?: Record<string, string>;\n timestamp?: Date;\n}\n","import type { DataDogTransportConfig, TransportLogEntry } from '../types/transport.types';\nimport { internalError } from '../utils/internal-log';\nimport type { AnalyticsMetric } from './analytics.transport';\nimport { AnalyticsTransport } from './analytics.transport';\n\nexport class DataDogTransport extends AnalyticsTransport {\n private datadogConfig: DataDogTransportConfig;\n private baseUrl: string;\n private logsUrl: string;\n private metricsUrl: string;\n\n constructor(config: DataDogTransportConfig) {\n super('datadog', config);\n this.datadogConfig = config;\n\n // Set URLs based on site configuration\n const site = config.site || 'datadoghq.com';\n this.baseUrl = `https://api.${site}`;\n this.logsUrl = `https://http-intake.logs.${site}`;\n this.metricsUrl = `https://api.${site}`;\n }\n\n protected async initialize(): Promise<void> {\n try {\n // Validate required configuration\n if (!this.datadogConfig.apiKey) {\n throw new Error('DataDog API key is required');\n }\n\n // Test connection\n await this.testConnection();\n this.isReady = true;\n } catch (error) {\n internalError('DataDog transport initialization failed', error);\n throw error;\n }\n }\n\n protected async sendEntry(entry: TransportLogEntry): Promise<void> {\n const promises: Promise<void>[] = [];\n\n // Send log if enabled\n if (this.datadogConfig.enableLogs !== false) {\n promises.push(this.sendLog(entry));\n }\n\n // Send metric if enabled\n if (this.datadogConfig.enableMetrics) {\n promises.push(this.sendMetric(entry));\n }\n\n // Send trace if enabled and trace ID exists\n if (this.datadogConfig.enableTraces && entry.traceId) {\n promises.push(this.sendTrace(entry));\n }\n\n await Promise.all(promises);\n }\n\n protected async sendBatch(entries: TransportLogEntry[]): Promise<void> {\n const promises: Promise<void>[] = [];\n\n // Batch logs\n if (this.datadogConfig.enableLogs !== false) {\n promises.push(this.sendLogBatch(entries));\n }\n\n // Batch metrics\n if (this.datadogConfig.enableMetrics) {\n promises.push(this.sendMetricBatch(entries));\n }\n\n // Batch traces\n if (this.datadogConfig.enableTraces) {\n const entriesWithTraces = entries.filter((e) => e.traceId);\n if (entriesWithTraces.length > 0) {\n promises.push(this.sendTraceBatch(entriesWithTraces));\n }\n }\n\n await Promise.all(promises);\n }\n\n protected async cleanup(): Promise<void> {\n // DataDog doesn't require explicit cleanup\n }\n\n private async sendLog(entry: TransportLogEntry): Promise<void> {\n await this.sendLogBatch([entry]);\n }\n\n private async sendLogBatch(entries: TransportLogEntry[]): Promise<void> {\n const logs = entries.map((entry) => this.transformToDataDogLog(entry));\n\n const payload = {\n logs: logs,\n };\n\n await this.makeLogsRequest('/v1/input/' + this.datadogConfig.apiKey, payload);\n }\n\n private async sendMetric(entry: TransportLogEntry): Promise<void> {\n await this.sendMetricBatch([entry]);\n }\n\n private async sendMetricBatch(entries: TransportLogEntry[]): Promise<void> {\n const metrics = entries.map((entry) => this.transformToDataDogMetric(entry));\n\n const payload = {\n series: metrics,\n };\n\n await this.makeMetricsRequest('/api/v1/series', payload);\n }\n\n private async sendTrace(entry: TransportLogEntry): Promise<void> {\n // DataDog traces are typically sent via the trace agent\n // For simplicity, we'll log this as a structured log with trace information\n await this.sendLog(entry);\n }\n\n private async sendTraceBatch(entries: TransportLogEntry[]): Promise<void> {\n // For batch traces, send as structured logs with trace information\n await this.sendLogBatch(entries);\n }\n\n private transformToDataDogLog(entry: TransportLogEntry): Record<string, unknown> {\n const transformed = this.transformEntry(entry);\n\n return {\n timestamp: entry.timestamp.toISOString(),\n level: this.mapLogLevel(entry.level),\n message: entry.message,\n service: this.datadogConfig.service || 'logitron',\n version: this.datadogConfig.version,\n env: this.datadogConfig.env || 'production',\n logger: {\n name: 'logitron',\n thread_name: 'main',\n },\n ...transformed,\n // Add DataDog specific fields\n 'dd.trace_id': entry.traceId,\n 'dd.span_id': this.generateSpanId(),\n host: this.getHostname(),\n source: 'nodejs',\n };\n }\n\n private transformToDataDogMetric(entry: TransportLogEntry): Record<string, unknown> {\n return {\n metric: `logitron.logs.${entry.level}`,\n points: [[Math.floor(entry.timestamp.getTime() / 1000), 1]],\n type: 'count',\n host: this.getHostname(),\n tags: [\n `level:${entry.level}`,\n `service:${this.datadogConfig.service || 'logitron'}`,\n `env:${this.datadogConfig.env || 'production'}`,\n ...(entry.context ? [`context:${entry.context}`] : []),\n ...(entry.appName ? [`app:${entry.appName}`] : []),\n ],\n };\n }\n\n private transformToDataDogTrace(entry: TransportLogEntry): Record<string, unknown> {\n return {\n trace_id: entry.traceId,\n span_id: this.generateSpanId(),\n parent_id: null,\n name: 'log.entry',\n service: this.datadogConfig.service || 'logitron',\n resource: entry.message,\n type: 'log',\n start: entry.timestamp.getTime() * 1000000, // nanoseconds\n duration: 1000000, // 1ms in nanoseconds\n meta: {\n 'log.level': entry.level,\n 'log.message': entry.message,\n ...(entry.context && { 'log.context': entry.context }),\n ...(entry.data &&\n Object.keys(entry.data).reduce(\n (acc, key) => {\n acc[`log.${key}`] = String(entry.data![key]);\n return acc;\n },\n {} as Record<string, string>\n )),\n },\n metrics: {\n _sampling_priority_v1: 1,\n },\n };\n }\n\n private mapLogLevel(level: string): string {\n const levelMap: Record<string, string> = {\n error: 'error',\n warn: 'warn',\n warning: 'warn',\n info: 'info',\n debug: 'debug',\n trace: 'trace',\n verbose: 'debug',\n };\n\n return levelMap[level.toLowerCase()] || 'info';\n }\n\n private async makeLogsRequest(endpoint: string, data: unknown): Promise<void> {\n const url = `${this.logsUrl}${endpoint}`;\n\n try {\n const response = await fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'DD-API-KEY': this.datadogConfig.apiKey,\n },\n body: JSON.stringify(data),\n });\n\n if (!response.ok) {\n throw new Error(`DataDog Logs API error: ${response.status} ${response.statusText}`);\n }\n } catch (error) {\n throw new Error(`Failed to send logs to DataDog: ${(error as Error).message}`, {\n cause: error,\n });\n }\n }\n\n private async makeMetricsRequest(endpoint: string, data: unknown): Promise<void> {\n const url = `${this.metricsUrl}${endpoint}`;\n\n try {\n const response = await fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'DD-API-KEY': this.datadogConfig.apiKey,\n },\n body: JSON.stringify(data),\n });\n\n if (!response.ok) {\n throw new Error(`DataDog Metrics API error: ${response.status} ${response.statusText}`);\n }\n } catch (error) {\n throw new Error(`Failed to send metrics to DataDog: ${(error as Error).message}`, {\n cause: error,\n });\n }\n }\n\n private async testConnection(): Promise<void> {\n // Test with a simple metric\n const testMetric = {\n series: [\n {\n metric: 'logitron.test',\n points: [[Math.floor(Date.now() / 1000), 1]],\n type: 'count',\n host: this.getHostname(),\n tags: ['test:true'],\n },\n ],\n };\n\n await this.makeMetricsRequest('/api/v1/series', testMetric);\n }\n\n private generateSpanId(): string {\n // eslint-disable-next-line sonarjs/pseudo-random -- non-security span ID generation\n return Math.floor(Math.random() * 0xffffffffffff).toString(16);\n }\n\n private getHostname(): string {\n try {\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n return require('node:os').hostname() as string;\n } catch {\n return 'unknown';\n }\n }\n\n // Public methods for additional DataDog functionality\n public async sendCustomMetric(metric: AnalyticsMetric): Promise<void> {\n const payload = {\n series: [\n {\n metric: metric.name,\n points: [[Math.floor((metric.timestamp || new Date()).getTime() / 1000), metric.value]],\n type: 'gauge',\n host: this.getHostname(),\n tags: Object.entries(metric.tags || {}).map(([key, value]) => `${key}:${value}`),\n },\n ],\n };\n\n await this.makeMetricsRequest('/api/v1/series', payload);\n }\n\n public async sendEvent(title: string, text: string, tags: string[] = []): Promise<void> {\n const payload = {\n title,\n text,\n date_happened: Math.floor(Date.now() / 1000),\n priority: 'normal',\n tags: [\n `service:${this.datadogConfig.service || 'logitron'}`,\n `env:${this.datadogConfig.env || 'production'}`,\n ...tags,\n ],\n source_type_name: 'logitron',\n };\n\n const url = `${this.baseUrl}/api/v1/events`;\n\n try {\n const response = await fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'DD-API-KEY': this.datadogConfig.apiKey,\n },\n body: JSON.stringify(payload),\n });\n\n if (!response.ok) {\n throw new Error(`DataDog Events API error: ${response.status} ${response.statusText}`);\n }\n } catch (error) {\n throw new Error(`Failed to send event to DataDog: ${(error as Error).message}`, {\n cause: error,\n });\n }\n }\n}\n","import type { WriteStream } from 'node:fs';\nimport * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport { promisify } from 'node:util';\n\nimport type {\n FileTransportConfig,\n IBatchTransport,\n ITransport,\n TransportLogEntry,\n} from '../types/transport.types';\nimport { internalError } from '../utils/internal-log';\n\nconst writeFile = promisify(fs.writeFile);\nconst mkdir = promisify(fs.mkdir);\nconst unlink = promisify(fs.unlink);\nconst readdir = promisify(fs.readdir);\nconst stat = promisify(fs.stat);\n\nexport class FileTransport implements ITransport, IBatchTransport {\n public readonly name = 'file';\n public readonly level?: string | undefined;\n public readonly batchSize?: number;\n public readonly flushInterval?: number;\n\n private config: FileTransportConfig;\n private writeStream: WriteStream | undefined;\n private batch: TransportLogEntry[] = [];\n private batchTimer?: NodeJS.Timeout | undefined;\n private lastRotation: Date = new Date();\n private currentFilePath: string;\n\n constructor(config: FileTransportConfig) {\n this.config = {\n format: 'json',\n batchSize: 100,\n flushInterval: 5000,\n ...config,\n };\n this.level = config.level;\n this.batchSize = this.config.batchSize || 100;\n this.flushInterval = this.config.flushInterval || 5000;\n this.currentFilePath = this.generateFilePath();\n this.ensureDirectoryExists();\n }\n\n async write(entry: TransportLogEntry): Promise<void> {\n try {\n if (this.shouldRotateNow()) {\n await this.rotate();\n }\n\n if (this.config.batchSize && this.config.batchSize > 1) {\n this.addToBatch(entry);\n } else {\n await this.writeBatch([entry]);\n }\n } catch (error) {\n throw new Error(`File transport write failed: ${(error as Error).message}`, { cause: error });\n }\n }\n\n async flush(): Promise<void> {\n if (this.batch.length > 0) {\n await this.writeBatch([...this.batch]);\n this.batch = [];\n }\n\n if (this.batchTimer) {\n clearTimeout(this.batchTimer);\n this.batchTimer = undefined;\n }\n }\n\n private formatEntry(entry: TransportLogEntry): string {\n switch (this.config.format) {\n case 'json':\n return JSON.stringify({\n timestamp: entry.timestamp.toISOString(),\n level: entry.level,\n message: entry.message,\n ...(entry.data || {}),\n });\n\n case 'csv': {\n const fields = [\n entry.timestamp.toISOString(),\n entry.level,\n `\"${entry.message.replace(/\"/g, '\"\"')}\"`,\n entry.context || '',\n entry.traceId || '',\n JSON.stringify(entry.data || {}),\n ];\n return fields.join(',');\n }\n\n case 'text':\n default:\n return `${entry.timestamp.toISOString()} [${entry.level.toUpperCase()}] ${entry.message}${entry.data ? ' ' + JSON.stringify(entry.data) : ''}`;\n }\n }\n\n addToBatch(entry: TransportLogEntry): void {\n this.batch.push(entry);\n\n if (this.batch.length >= (this.config.batchSize || 100)) {\n this.flush().catch((err: unknown) => internalError('FileTransport batch flush failed', err));\n } else if (!this.batchTimer && this.config.flushInterval) {\n this.batchTimer = setTimeout(() => {\n this.flush().catch((err: unknown) =>\n internalError('FileTransport interval flush failed', err)\n );\n }, this.config.flushInterval);\n }\n }\n\n private async writeBatch(entries: TransportLogEntry[]): Promise<void> {\n if (entries.length === 0) return;\n\n const content = entries.map((entry) => this.formatEntry(entry)).join('\\n') + '\\n';\n\n if (this.writeStream) {\n return new Promise((resolve, reject) => {\n this.writeStream!.write(content, (error) => {\n if (error) reject(error);\n else resolve();\n });\n });\n } else {\n await writeFile(this.currentFilePath, content, { flag: 'a' });\n }\n }\n\n private shouldRotateNow(): boolean {\n if (!this.config.rotation) return false;\n\n const now = new Date();\n const timeDiff = now.getTime() - this.lastRotation.getTime();\n const rotationInterval = this.parseInterval(this.config.rotation.interval!);\n\n return timeDiff >= rotationInterval;\n }\n\n private parseInterval(interval: string): number {\n // eslint-disable-next-line sonarjs/slow-regex -- simple bounded pattern for interval parsing\n const match = interval.match(/(\\d+)([hdwmy])/i);\n if (!match) return 24 * 60 * 60 * 1000; // Default 1 day\n\n const value = Number.parseInt(match[1] || '1', 10);\n const unit = (match[2] || 'h').toLowerCase();\n\n switch (unit) {\n case 'h':\n return value * 60 * 60 * 1000;\n case 'd':\n return value * 24 * 60 * 60 * 1000;\n case 'w':\n return value * 7 * 24 * 60 * 60 * 1000;\n case 'm':\n return value * 30 * 24 * 60 * 60 * 1000;\n case 'y':\n return value * 365 * 24 * 60 * 60 * 1000;\n default:\n return value * 60 * 60 * 1000;\n }\n }\n\n private async rotate(): Promise<void> {\n await this.flush();\n\n if (this.writeStream) {\n await new Promise<void>((resolve) => {\n this.writeStream!.end(() => resolve());\n });\n this.writeStream = undefined;\n }\n\n const oldPath = this.currentFilePath;\n this.currentFilePath = this.generateFilePath();\n this.lastRotation = new Date();\n\n // Compress old file if configured\n if (this.config.rotation?.compress) {\n await this.compressFile(oldPath);\n }\n\n // Clean up old files\n if (this.config.rotation?.maxFiles) {\n await this.cleanupOldFiles();\n }\n }\n\n private generateFilePath(): string {\n const now = new Date();\n const timestamp = now.toISOString().replace(/[:.]/g, '-').slice(0, 19);\n const dir = path.dirname(this.config.filename);\n const ext = path.extname(this.config.filename);\n const base = path.basename(this.config.filename, ext);\n\n if (this.config.rotation) {\n return path.join(dir, `${base}-${timestamp}${ext}`);\n }\n\n return this.config.filename;\n }\n\n private async ensureDirectoryExists(): Promise<void> {\n const dir = path.dirname(this.currentFilePath);\n try {\n await mkdir(dir, { recursive: true });\n } catch {\n // Directory might already exist\n }\n }\n\n private async compressFile(_filePath: string): Promise<void> {\n // Simple gzip compression implementation would go here\n // For now, just rename with .gz extension\n // In a real implementation, you'd use zlib\n }\n\n private async cleanupOldFiles(): Promise<void> {\n if (!this.config.rotation?.maxFiles) return;\n\n try {\n const dir = path.dirname(this.config.filename);\n const files = await readdir(dir);\n const base = path.basename(this.config.filename, path.extname(this.config.filename));\n\n const logFiles = files\n .filter((file) => file.startsWith(base))\n .map(async (file) => {\n const filePath = path.join(dir, file);\n const stats = await stat(filePath);\n return { path: filePath, mtime: stats.mtime };\n });\n\n const fileStats = await Promise.all(logFiles);\n const sortedFiles = fileStats.sort((a, b) => b.mtime.getTime() - a.mtime.getTime());\n\n const filesToDelete = sortedFiles.slice(this.config.rotation!.maxFiles!);\n\n for (const file of filesToDelete) {\n await unlink(file.path);\n }\n } catch (error) {\n internalError('Failed to cleanup old log files', error);\n }\n }\n\n async close(): Promise<void> {\n await this.flush();\n\n if (this.writeStream) {\n return new Promise((resolve) => {\n this.writeStream!.end(() => resolve());\n });\n }\n }\n}\n","import type { GoogleAnalyticsTransportConfig, TransportLogEntry } from '../types/transport.types';\nimport { internalError, internalLog } from '../utils/internal-log';\nimport { AnalyticsTransport } from './analytics.transport';\n\nexport class GoogleAnalyticsTransport extends AnalyticsTransport {\n private gaConfig: GoogleAnalyticsTransportConfig;\n private baseUrl: string = 'https://www.google-analytics.com/mp/collect';\n private debugUrl: string = 'https://www.google-analytics.com/debug/mp/collect';\n\n constructor(config: GoogleAnalyticsTransportConfig) {\n super('google-analytics', config);\n this.gaConfig = config;\n }\n\n protected async initialize(): Promise<void> {\n try {\n // Validate required configuration\n if (!this.gaConfig.measurementId) {\n throw new Error('Google Analytics Measurement ID is required');\n }\n if (!this.gaConfig.apiSecret) {\n throw new Error('Google Analytics API Secret is required');\n }\n\n // Test connection\n await this.testConnection();\n this.isReady = true;\n } catch (error) {\n internalError('Google Analytics transport initialization failed', error);\n throw error;\n }\n }\n\n protected async sendEntry(entry: TransportLogEntry): Promise<void> {\n const event = this.transformToGAEvent(entry);\n await this.sendEvent(event);\n }\n\n protected async sendBatch(entries: TransportLogEntry[]): Promise<void> {\n const events = entries.map((entry) => this.transformToGAEvent(entry));\n await this.sendEvents(events);\n }\n\n protected async cleanup(): Promise<void> {\n // Google Analytics doesn't require explicit cleanup\n }\n\n private transformToGAEvent(entry: TransportLogEntry): Record<string, unknown> {\n const transformed = this.transformEntry(entry);\n\n // Map log levels to GA event categories\n const eventCategory = this.mapLogLevelToCategory(entry.level);\n\n return {\n name: 'log_event',\n params: {\n event_category: eventCategory,\n event_label: entry.message,\n log_level: entry.level,\n log_message: entry.message,\n timestamp: entry.timestamp.toISOString(),\n ...(entry.context && { context: entry.context }),\n ...(entry.traceId && { trace_id: entry.traceId }),\n ...(entry.appName && { app_name: entry.appName }),\n ...(entry.environment && { environment: entry.environment }),\n ...this.flattenData(transformed),\n // Add custom dimensions\n custom_dimension_1: entry.level,\n custom_dimension_2: entry.context || 'default',\n custom_dimension_3: entry.environment || 'production',\n },\n };\n }\n\n private mapLogLevelToCategory(level: string): string {\n const categoryMap: Record<string, string> = {\n error: 'Error',\n warn: 'Warning',\n warning: 'Warning',\n info: 'Information',\n debug: 'Debug',\n trace: 'Trace',\n verbose: 'Verbose',\n };\n\n return categoryMap[level.toLowerCase()] || 'Information';\n }\n\n private flattenData(data: Record<string, unknown>, prefix: string = ''): Record<string, unknown> {\n const flattened: Record<string, unknown> = {};\n\n for (const [key, value] of Object.entries(data)) {\n const newKey = prefix ? `${prefix}_${key}` : key;\n\n if (value && typeof value === 'object' && !Array.isArray(value) && !(value instanceof Date)) {\n Object.assign(flattened, this.flattenData(value as Record<string, unknown>, newKey));\n } else {\n // GA4 has parameter value limits\n const stringValue = String(value);\n flattened[newKey] = stringValue.length > 100 ? stringValue.slice(0, 100) : stringValue;\n }\n }\n\n return flattened;\n }\n\n private async sendEvent(event: unknown): Promise<void> {\n const payload = {\n client_id: this.gaConfig.clientId || this.generateClientId(),\n events: [event],\n };\n\n await this.makeRequest(payload);\n }\n\n private async sendEvents(events: unknown[]): Promise<void> {\n // GA4 allows up to 25 events per request\n const chunks = this.chunkArray(events, 25);\n\n for (const chunk of chunks) {\n const payload = {\n client_id: this.gaConfig.clientId || this.generateClientId(),\n events: chunk,\n };\n\n await this.makeRequest(payload);\n }\n }\n\n private async makeRequest(payload: unknown, debug: boolean = false): Promise<void> {\n const url = debug ? this.debugUrl : this.baseUrl;\n const params = new URLSearchParams({\n measurement_id: this.gaConfig.measurementId,\n api_secret: this.gaConfig.apiSecret,\n });\n\n try {\n const response = await fetch(`${url}?${params}`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(payload),\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(\n `Google Analytics API error: ${response.status} ${response.statusText} - ${errorText}`\n );\n }\n\n if (debug) {\n const result = await response.json();\n internalLog(`GA4 Debug Response: ${JSON.stringify(result)}`);\n }\n } catch (error) {\n throw new Error(`Failed to send data to Google Analytics: ${(error as Error).message}`, {\n cause: error,\n });\n }\n }\n\n private async testConnection(): Promise<void> {\n // Send a test event to validate the connection\n const testEvent = {\n name: 'logitron_test',\n params: {\n event_category: 'Test',\n event_label: 'Connection Test',\n test: true,\n timestamp: new Date().toISOString(),\n },\n };\n\n const payload = {\n client_id: this.gaConfig.clientId || this.generateClientId(),\n events: [testEvent],\n };\n\n // Use debug endpoint for testing\n await this.makeRequest(payload, true);\n }\n\n private generateClientId(): string {\n // Generate a UUID-like client ID (non-security use)\n return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {\n // eslint-disable-next-line sonarjs/pseudo-random -- non-security UUID generation\n const r = (Math.random() * 16) | 0;\n const v = c === 'x' ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n }\n\n private chunkArray<T>(array: T[], size: number): T[][] {\n const chunks: T[][] = [];\n for (let i = 0; i < array.length; i += size) {\n chunks.push(array.slice(i, i + size));\n }\n return chunks;\n }\n\n // Public methods for additional GA4 functionality\n public async trackPageView(pagePath: string, pageTitle?: string): Promise<void> {\n const event = {\n name: 'page_view',\n params: {\n page_location: pagePath,\n page_title: pageTitle || pagePath,\n engagement_time_msec: 1,\n },\n };\n\n await this.sendEvent(event);\n }\n\n public async trackCustomEvent(\n eventName: string,\n parameters: Record<string, unknown> = {}\n ): Promise<void> {\n // Ensure event name follows GA4 conventions\n const sanitizedEventName = eventName.toLowerCase().replace(/[^a-z0-9_]/g, '_');\n\n const event = {\n name: sanitizedEventName,\n params: {\n ...this.flattenData(parameters),\n timestamp: new Date().toISOString(),\n },\n };\n\n await this.sendEvent(event);\n }\n\n public async trackConversion(\n conversionName: string,\n value?: number,\n currency?: string\n ): Promise<void> {\n const event = {\n name: conversionName,\n params: {\n ...(value !== undefined && { value }),\n ...(currency && { currency }),\n timestamp: new Date().toISOString(),\n },\n };\n\n await this.sendEvent(event);\n }\n\n public async trackError(\n errorMessage: string,\n errorCode?: string,\n fatal: boolean = false\n ): Promise<void> {\n const event = {\n name: 'exception',\n params: {\n description: errorMessage,\n fatal,\n ...(errorCode && { error_code: errorCode }),\n timestamp: new Date().toISOString(),\n },\n };\n\n await this.sendEvent(event);\n }\n\n public async setUserProperties(properties: Record<string, unknown>): Promise<void> {\n // GA4 user properties are set with events\n const event = {\n name: 'user_properties_update',\n params: {\n ...this.flattenData(properties),\n timestamp: new Date().toISOString(),\n },\n };\n\n await this.sendEvent(event);\n }\n\n // Enhanced measurement events\n public async trackFileDownload(fileName: string, fileExtension: string): Promise<void> {\n if (!this.gaConfig.enableEnhancedMeasurement) {\n return;\n }\n\n const event = {\n name: 'file_download',\n params: {\n file_name: fileName,\n file_extension: fileExtension,\n link_url: fileName,\n timestamp: new Date().toISOString(),\n },\n };\n\n await this.sendEvent(event);\n }\n\n public async trackVideoEngagement(\n videoTitle: string,\n videoUrl: string,\n progress: number\n ): Promise<void> {\n if (!this.gaConfig.enableEnhancedMeasurement) {\n return;\n }\n\n const event = {\n name: 'video_progress',\n params: {\n video_title: videoTitle,\n video_url: videoUrl,\n video_progress: progress,\n timestamp: new Date().toISOString(),\n },\n };\n\n await this.sendEvent(event);\n }\n}\n","import type { MixpanelTransportConfig, TransportLogEntry } from '../types/transport.types';\nimport { internalError } from '../utils/internal-log';\nimport type { AnalyticsEvent, AnalyticsUser } from './analytics.transport';\nimport { AnalyticsTransport } from './analytics.transport';\n\nexport class MixpanelTransport extends AnalyticsTransport {\n private mixpanelConfig: MixpanelTransportConfig;\n private baseUrl: string = 'https://api.mixpanel.com';\n\n constructor(config: MixpanelTransportConfig) {\n super('mixpanel', config);\n this.mixpanelConfig = config;\n }\n\n protected async initialize(): Promise<void> {\n try {\n // Validate required configuration\n if (!this.mixpanelConfig.token) {\n throw new Error('Mixpanel token is required');\n }\n\n // Test connection with a simple request\n await this.testConnection();\n this.isReady = true;\n } catch (error) {\n internalError('Mixpanel transport initialization failed', error);\n throw error;\n }\n }\n\n protected async sendEntry(entry: TransportLogEntry): Promise<void> {\n const event = this.transformToMixpanelEvent(entry);\n await this.trackEvent(event);\n }\n\n protected async sendBatch(entries: TransportLogEntry[]): Promise<void> {\n const events = entries.map((entry) => this.transformToMixpanelEvent(entry));\n await this.trackEvents(events);\n }\n\n protected async cleanup(): Promise<void> {\n // Mixpanel doesn't require explicit cleanup\n }\n\n private transformToMixpanelEvent(entry: TransportLogEntry): AnalyticsEvent {\n const transformed = this.transformEntry(entry);\n\n return {\n name: `log_${entry.level}`,\n properties: {\n ...transformed,\n distinct_id: this.mixpanelConfig.distinct_id || 'anonymous',\n time: entry.timestamp.getTime(),\n $insert_id: this.generateInsertId(entry),\n // Add super properties if enabled\n ...(this.mixpanelConfig.enableSuperProperties ? this.mixpanelConfig.superProperties : {}),\n },\n timestamp: entry.timestamp,\n };\n }\n\n private async trackEvent(event: AnalyticsEvent): Promise<void> {\n const payload = {\n event: event.name,\n properties: {\n token: this.mixpanelConfig.token,\n ...event.properties,\n },\n };\n\n await this.makeRequest('/track', [payload]);\n }\n\n private async trackEvents(events: AnalyticsEvent[]): Promise<void> {\n const payload = events.map((event) => ({\n event: event.name,\n properties: {\n token: this.mixpanelConfig.token,\n ...event.properties,\n },\n }));\n\n await this.makeRequest('/track', payload);\n }\n\n private async makeRequest(endpoint: string, data: unknown): Promise<void> {\n const url = `${this.mixpanelConfig.endpoint || this.baseUrl}${endpoint}`;\n\n try {\n const response = await fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Accept: 'text/plain',\n },\n body: JSON.stringify(data),\n });\n\n if (!response.ok) {\n throw new Error(`Mixpanel API error: ${response.status} ${response.statusText}`);\n }\n\n const result = await response.text();\n if (result !== '1') {\n throw new Error(`Mixpanel API returned error: ${result}`);\n }\n } catch (error) {\n throw new Error(`Failed to send data to Mixpanel: ${(error as Error).message}`, {\n cause: error,\n });\n }\n }\n\n private async testConnection(): Promise<void> {\n // Send a test event to validate the connection\n const testEvent = {\n event: 'logitron_test',\n properties: {\n token: this.mixpanelConfig.token,\n distinct_id: 'test_user',\n test: true,\n time: Date.now(),\n },\n };\n\n await this.makeRequest('/track', [testEvent]);\n }\n\n private generateInsertId(entry: TransportLogEntry): string {\n // Generate a unique insert ID to prevent duplicate events\n const timestamp = entry.timestamp.getTime();\n const hash = this.simpleHash(entry.message + (entry.traceId || ''));\n return `${timestamp}_${hash}`;\n }\n\n private simpleHash(str: string): string {\n let hash = 0;\n for (let i = 0; i < str.length; i++) {\n const char = str.charCodeAt(i);\n hash = (hash << 5) - hash + char;\n hash = hash & hash; // Convert to 32-bit integer\n }\n return Math.abs(hash).toString(36);\n }\n\n // Public methods for additional Mixpanel functionality\n public async identifyUser(user: AnalyticsUser): Promise<void> {\n if (!this.mixpanelConfig.enableUserTracking) {\n return;\n }\n\n const payload = {\n $token: this.mixpanelConfig.token,\n $distinct_id: user.id,\n $set: user.properties || {},\n };\n\n await this.makeRequest('/engage', [payload]);\n }\n\n public async setUserProperties(\n userId: string,\n properties: Record<string, unknown>\n ): Promise<void> {\n if (!this.mixpanelConfig.enableUserTracking) {\n return;\n }\n\n const payload = {\n $token: this.mixpanelConfig.token,\n $distinct_id: userId,\n $set: properties,\n };\n\n await this.makeRequest('/engage', [payload]);\n }\n\n public async trackCustomEvent(\n eventName: string,\n properties: Record<string, unknown> = {}\n ): Promise<void> {\n if (!this.mixpanelConfig.enableEventTracking) {\n return;\n }\n\n const payload = {\n event: eventName,\n properties: {\n token: this.mixpanelConfig.token,\n distinct_id: this.mixpanelConfig.distinct_id || 'anonymous',\n time: Date.now(),\n ...properties,\n ...(this.mixpanelConfig.enableSuperProperties ? this.mixpanelConfig.superProperties : {}),\n },\n };\n\n await this.makeRequest('/track', [payload]);\n }\n}\n","import type { SegmentTransportConfig, TransportLogEntry } from '../types/transport.types';\nimport { internalError } from '../utils/internal-log';\nimport type { AnalyticsUser } from './analytics.transport';\nimport { AnalyticsTransport } from './analytics.transport';\n\nexport class SegmentTransport extends AnalyticsTransport {\n private segmentConfig: SegmentTransportConfig;\n private baseUrl: string;\n\n constructor(config: SegmentTransportConfig) {\n super('segment', config);\n this.segmentConfig = {\n enableBatching: true,\n maxBatchSize: 100,\n flushAt: 20,\n flushInterval: 10000,\n ...config,\n };\n\n this.baseUrl = config.dataPlaneUrl || 'https://api.segment.io';\n }\n\n protected async initialize(): Promise<void> {\n try {\n // Validate required configuration\n if (!this.segmentConfig.writeKey) {\n throw new Error('Segment Write Key is required');\n }\n\n // Test connection\n await this.testConnection();\n this.isReady = true;\n } catch (error) {\n internalError('Segment transport initialization failed', error);\n throw error;\n }\n }\n\n protected async sendEntry(entry: TransportLogEntry): Promise<void> {\n const segmentEvent = this.transformToSegmentEvent(entry);\n await this.track(segmentEvent);\n }\n\n protected async sendBatch(entries: TransportLogEntry[]): Promise<void> {\n if (!this.segmentConfig.enableBatching) {\n // Send individually if batching is disabled\n for (const entry of entries) {\n await this.sendEntry(entry);\n }\n return;\n }\n\n const segmentEvents = entries.map((entry) => this.transformToSegmentEvent(entry));\n await this.batchTrack(segmentEvents);\n }\n\n protected async cleanup(): Promise<void> {\n // Segment doesn't require explicit cleanup\n }\n\n private transformToSegmentEvent(entry: TransportLogEntry): Record<string, unknown> {\n const transformed = this.transformEntry(entry);\n\n return {\n type: 'track',\n event: `Log ${entry.level.charAt(0).toUpperCase() + entry.level.slice(1)}`,\n userId: this.extractUserId(entry),\n anonymousId: this.generateAnonymousId(),\n timestamp: entry.timestamp.toISOString(),\n properties: {\n level: entry.level,\n message: entry.message,\n logger: 'logixia',\n ...transformed,\n ...(entry.context && { context: entry.context }),\n ...(entry.traceId && { traceId: entry.traceId }),\n ...(entry.appName && { appName: entry.appName }),\n ...(entry.environment && { environment: entry.environment }),\n },\n context: {\n library: {\n name: 'logixia',\n version: '1.0.0',\n },\n app: {\n name: entry.appName || 'unknown',\n version: '1.0.0',\n environment: entry.environment || 'production',\n },\n ...(entry.traceId && {\n trace: {\n trace_id: entry.traceId,\n },\n }),\n },\n integrations: {\n // Disable integrations that might interfere\n All: false,\n 'Segment.io': true,\n },\n };\n }\n\n private async track(event: unknown): Promise<void> {\n await this.makeRequest('/v1/track', event);\n }\n\n private async batchTrack(events: unknown[]): Promise<void> {\n // Split into chunks based on maxBatchSize\n const chunks = this.chunkArray(events, this.segmentConfig.maxBatchSize || 100);\n\n for (const chunk of chunks) {\n const payload = {\n batch: chunk,\n };\n\n await this.makeRequest('/v1/batch', payload);\n }\n }\n\n private async makeRequest(endpoint: string, data: unknown): Promise<void> {\n const url = `${this.baseUrl}${endpoint}`;\n\n // Encode write key for basic auth\n const auth = Buffer.from(`${this.segmentConfig.writeKey}:`).toString('base64');\n\n try {\n const response = await fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Basic ${auth}`,\n 'User-Agent': 'logixia/1.0.0',\n },\n body: JSON.stringify(data),\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(\n `Segment API error: ${response.status} ${response.statusText} - ${errorText}`\n );\n }\n } catch (error) {\n throw new Error(`Failed to send data to Segment: ${(error as Error).message}`, {\n cause: error,\n });\n }\n }\n\n private async testConnection(): Promise<void> {\n // Send a test track event\n const testEvent = {\n type: 'track',\n event: 'Logixia Test',\n userId: 'test-user',\n anonymousId: this.generateAnonymousId(),\n timestamp: new Date().toISOString(),\n properties: {\n test: true,\n source: 'logixia',\n },\n context: {\n library: {\n name: 'logixia',\n version: '1.0.0',\n },\n },\n };\n\n await this.makeRequest('/v1/track', testEvent);\n }\n\n private extractUserId(entry: TransportLogEntry): string | undefined {\n // Try to extract user ID from entry data\n if (entry.data) {\n const d = entry.data as Record<string, unknown>;\n const id = d['userId'] ?? d['user_id'] ?? d['id'];\n return typeof id === 'string' ? id : undefined;\n }\n return undefined;\n }\n\n private generateAnonymousId(): string {\n // Generate a UUID-like anonymous ID (non-security use)\n return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {\n // eslint-disable-next-line sonarjs/pseudo-random -- non-security UUID generation\n const r = (Math.random() * 16) | 0;\n const v = c === 'x' ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n }\n\n private chunkArray<T>(array: T[], size: number): T[][] {\n const chunks: T[][] = [];\n for (let i = 0; i < array.length; i += size) {\n chunks.push(array.slice(i, i + size));\n }\n return chunks;\n }\n\n // Public methods for Segment-specific functionality\n public async identify(user: AnalyticsUser): Promise<void> {\n const payload = {\n type: 'identify',\n userId: user.id,\n anonymousId: this.generateAnonymousId(),\n timestamp: new Date().toISOString(),\n traits: {\n ...user.properties,\n ...user.traits,\n },\n context: {\n library: {\n name: 'logitron',\n version: '1.0.0',\n },\n },\n };\n\n await this.makeRequest('/v1/identify', payload);\n }\n\n public async page(name: string, properties: Record<string, unknown> = {}): Promise<void> {\n const payload = {\n type: 'page',\n name,\n anonymousId: this.generateAnonymousId(),\n timestamp: new Date().toISOString(),\n properties: {\n ...properties,\n url: properties.url || `/${name.toLowerCase().replace(/\\s+/g, '-')}`,\n title: properties.title || name,\n },\n context: {\n library: {\n name: 'logitron',\n version: '1.0.0',\n },\n page: {\n url: properties.url || `/${name.toLowerCase().replace(/\\s+/g, '-')}`,\n title: properties.title || name,\n },\n },\n };\n\n await this.makeRequest('/v1/page', payload);\n }\n\n public async screen(name: string, properties: Record<string, unknown> = {}): Promise<void> {\n const payload = {\n type: 'screen',\n name,\n anonymousId: this.generateAnonymousId(),\n timestamp: new Date().toISOString(),\n properties: {\n ...properties,\n },\n context: {\n library: {\n name: 'logitron',\n version: '1.0.0',\n },\n screen: {\n name,\n },\n },\n };\n\n await this.makeRequest('/v1/screen', payload);\n }\n\n public async group(\n groupId: string,\n traits: Record<string, unknown> = {},\n userId?: string\n ): Promise<void> {\n const payload = {\n type: 'group',\n groupId,\n userId,\n anonymousId: this.generateAnonymousId(),\n timestamp: new Date().toISOString(),\n traits,\n context: {\n library: {\n name: 'logitron',\n version: '1.0.0',\n },\n },\n };\n\n await this.makeRequest('/v1/group', payload);\n }\n\n public async alias(userId: string, previousId: string): Promise<void> {\n const payload = {\n type: 'alias',\n userId,\n previousId,\n timestamp: new Date().toISOString(),\n context: {\n library: {\n name: 'logitron',\n version: '1.0.0',\n },\n },\n };\n\n await this.makeRequest('/v1/alias', payload);\n }\n\n public async trackCustomEvent(\n eventName: string,\n properties: Record<string, unknown> = {},\n userId?: string\n ): Promise<void> {\n const payload = {\n type: 'track',\n event: eventName,\n userId,\n anonymousId: this.generateAnonymousId(),\n timestamp: new Date().toISOString(),\n properties,\n context: {\n library: {\n name: 'logitron',\n version: '1.0.0',\n },\n },\n };\n\n await this.makeRequest('/v1/track', payload);\n }\n\n // E-commerce tracking methods\n public async trackPurchase(\n orderId: string,\n products: unknown[],\n revenue: number,\n currency: string = 'USD'\n ): Promise<void> {\n const payload = {\n type: 'track',\n event: 'Order Completed',\n anonymousId: this.generateAnonymousId(),\n timestamp: new Date().toISOString(),\n properties: {\n orderId,\n revenue,\n currency,\n products,\n },\n context: {\n library: {\n name: 'logitron',\n version: '1.0.0',\n },\n },\n };\n\n await this.makeRequest('/v1/track', payload);\n }\n\n public async trackProductViewed(product: unknown): Promise<void> {\n const payload = {\n type: 'track',\n event: 'Product Viewed',\n anonymousId: this.generateAnonymousId(),\n timestamp: new Date().toISOString(),\n properties: product,\n context: {\n library: {\n name: 'logitron',\n version: '1.0.0',\n },\n },\n };\n\n await this.makeRequest('/v1/track', payload);\n }\n}\n","import { EventEmitter } from 'node:events';\nimport * as readline from 'node:readline';\n\nimport type { LogEntry } from '../types';\nimport type {\n IAsyncTransport,\n IBatchTransport,\n ITransport,\n TransportConfig,\n TransportLogEntry,\n TransportMetrics,\n TransportType,\n} from '../types/transport.types';\nimport { internalLog, internalWarn } from '../utils/internal-log';\nimport { ConsoleTransport } from './console.transport';\nimport { DatabaseTransport } from './database.transport';\nimport { DataDogTransport } from './datadog.transport';\nimport { FileTransport } from './file.transport';\nimport { GoogleAnalyticsTransport } from './google-analytics.transport';\nimport { MixpanelTransport } from './mixpanel.transport';\nimport { SegmentTransport } from './segment.transport';\n\nexport class TransportManager extends EventEmitter {\n private transports: Map<string, ITransport> = new Map();\n private metrics: Map<string, TransportMetrics> = new Map();\n private isShuttingDown = false;\n private transportLevelPreferences: Map<string, string[]> = new Map(); // Store user preferences for transport levels\n private promptForLevels: boolean = false; // Flag to enable/disable prompting\n\n constructor(config: TransportConfig = {}) {\n super();\n this.setupTransports(config);\n }\n\n private setupTransports(config: TransportConfig): void {\n if (config.console) {\n const consoleTransport = new ConsoleTransport(\n typeof config.console === 'object' ? config.console : {}\n );\n this.addTransport(consoleTransport, 'console');\n }\n\n // Setup file transports\n if (config.file) {\n const fileConfigs = Array.isArray(config.file) ? config.file : [config.file];\n for (const [index, fileConfig] of fileConfigs.entries()) {\n const fileTransport = new FileTransport(fileConfig);\n this.addTransport(fileTransport, `file-${index}`);\n }\n }\n\n // Setup database transports\n if (config.database) {\n const dbConfigs = Array.isArray(config.database) ? config.database : [config.database];\n for (const [index, dbConfig] of dbConfigs.entries()) {\n const dbTransport = new DatabaseTransport(dbConfig);\n this.addTransport(dbTransport, `database-${index}`);\n }\n }\n\n // Setup analytics transports\n if (config.analytics) {\n if (config.analytics.mixpanel) {\n const mixpanelConfigs = Array.isArray(config.analytics.mixpanel)\n ? config.analytics.mixpanel\n : [config.analytics.mixpanel];\n for (const [index, mixpanelConfig] of mixpanelConfigs.entries()) {\n const mixpanelTransport = new MixpanelTransport(mixpanelConfig);\n this.addTransport(mixpanelTransport, `mixpanel-${index}`);\n }\n }\n\n if (config.analytics.datadog) {\n const datadogConfigs = Array.isArray(config.analytics.datadog)\n ? config.analytics.datadog\n : [config.analytics.datadog];\n for (const [index, datadogConfig] of datadogConfigs.entries()) {\n const datadogTransport = new DataDogTransport(datadogConfig);\n this.addTransport(datadogTransport, `datadog-${index}`);\n }\n }\n\n if (config.analytics.googleAnalytics) {\n const gaConfigs = Array.isArray(config.analytics.googleAnalytics)\n ? config.analytics.googleAnalytics\n : [config.analytics.googleAnalytics];\n for (const [index, gaConfig] of gaConfigs.entries()) {\n const gaTransport = new GoogleAnalyticsTransport(gaConfig);\n this.addTransport(gaTransport, `google-analytics-${index}`);\n }\n }\n\n if (config.analytics.segment) {\n const segmentConfigs = Array.isArray(config.analytics.segment)\n ? config.analytics.segment\n : [config.analytics.segment];\n for (const [index, segmentConfig] of segmentConfigs.entries()) {\n const segmentTransport = new SegmentTransport(segmentConfig);\n this.addTransport(segmentTransport, `segment-${index}`);\n }\n }\n }\n\n // Setup custom transports\n if (config.custom) {\n for (const [index, transport] of config.custom.entries()) {\n this.addTransport(transport, `custom-${index}`);\n }\n }\n }\n\n addTransport(transport: ITransport, id?: string): void {\n const transportId = id || `${transport.name}-${Date.now()}`;\n this.transports.set(transportId, transport);\n\n // Initialize metrics\n this.metrics.set(transportId, {\n name: transportId,\n type: this.getTransportType(transport),\n logsWritten: 0,\n errors: 0,\n lastWrite: new Date(),\n averageWriteTime: 0,\n });\n\n this.emit('transport:added', transportId, transport);\n }\n\n removeTransport(id: string): boolean {\n const transport = this.transports.get(id);\n if (!transport) return false;\n\n this.transports.delete(id);\n this.metrics.delete(id);\n\n // Close transport if it has a close method\n if (transport.close) {\n transport.close().catch((error) => {\n this.emit('error', error, id);\n });\n }\n\n this.emit('transport:removed', id);\n return true;\n }\n\n async write(entry: LogEntry): Promise<void> {\n // Build the transport entry — exactOptionalPropertyTypes requires we only set\n // optional properties when they have a real value (not undefined).\n const transportEntry: TransportLogEntry = {\n timestamp: new Date(entry.timestamp),\n level: entry.level,\n message: entry.message,\n appName: entry.appName,\n };\n if (entry.payload !== undefined) transportEntry.data = entry.payload;\n if (entry.context !== undefined) transportEntry.context = entry.context;\n if (entry.traceId !== undefined) transportEntry.traceId = entry.traceId;\n if (entry.environment !== undefined) transportEntry.environment = entry.environment;\n if (this.isShuttingDown) {\n throw new Error('TransportManager is shutting down');\n }\n\n const writePromises: Promise<void>[] = [];\n\n for (const [id, transport] of this.transports) {\n // Configure transport levels if prompting is enabled\n if (this.promptForLevels && !this.transportLevelPreferences.has(id)) {\n await this.configureTransportLevels(id);\n }\n\n // Check if transport should handle this log level\n if (!this.shouldTransportHandle(transport, transportEntry.level, id)) {\n continue;\n }\n\n const writePromise = this.writeToTransport(id, transport, transportEntry);\n writePromises.push(writePromise);\n }\n\n // Wait for all transports to complete (or fail)\n const results = await Promise.allSettled(writePromises);\n\n // Check for any failures\n const failures = results.filter(\n (result) => result.status === 'rejected'\n ) as PromiseRejectedResult[];\n if (failures.length > 0) {\n const errors = failures.map((failure) => failure.reason);\n this.emit('error', new Error(`Transport write failures: ${errors.join(', ')}`), 'multiple');\n }\n }\n\n private async writeToTransport(\n id: string,\n transport: ITransport,\n entry: TransportLogEntry\n ): Promise<void> {\n const startTime = Date.now();\n const metrics = this.metrics.get(id)!;\n\n try {\n await transport.write(entry);\n\n // Update metrics (reuse startTime, avoid new Date() allocation)\n const writeTime = Date.now() - startTime;\n metrics.logsWritten++;\n metrics.lastWrite = new Date(startTime);\n metrics.averageWriteTime = (metrics.averageWriteTime + writeTime) / 2;\n\n this.emit('log', entry);\n } catch (error) {\n metrics.errors++;\n this.emit('error', error, id);\n throw error;\n }\n }\n\n private shouldTransportHandle(\n transport: ITransport,\n level: string,\n transportId?: string\n ): boolean {\n // Check user preferences first if transport ID is provided\n if (transportId && this.transportLevelPreferences.has(transportId)) {\n const allowedLevels = this.transportLevelPreferences.get(transportId)!;\n return allowedLevels.includes(level.toLowerCase());\n }\n\n if (!transport.level) return true;\n\n // Simple level comparison - you might want to implement proper level hierarchy\n const levels = ['error', 'warn', 'info', 'debug', 'trace', 'verbose'];\n const transportLevelIndex = levels.indexOf(transport.level.toLowerCase());\n const entryLevelIndex = levels.indexOf(level.toLowerCase());\n\n if (transportLevelIndex === -1 || entryLevelIndex === -1) return true;\n\n return entryLevelIndex <= transportLevelIndex;\n }\n\n private getTransportType(transport: ITransport): TransportType {\n if (transport.name === 'console') return 'console';\n if (transport.name === 'file') return 'file';\n if (transport.name === 'database') return 'database';\n if (\n transport.name === 'mixpanel' ||\n transport.name === 'datadog' ||\n transport.name === 'google-analytics' ||\n transport.name === 'segment'\n ) {\n return 'analytics' as TransportType;\n }\n return 'custom';\n }\n\n // Async transport management\n async waitForReady(): Promise<void> {\n const readyPromises: Promise<boolean>[] = [];\n\n for (const transport of this.transports.values()) {\n if (this.isAsyncTransport(transport)) {\n readyPromises.push(transport.isReady());\n }\n }\n\n if (readyPromises.length > 0) {\n await Promise.all(readyPromises);\n }\n }\n\n async flush(): Promise<void> {\n const flushPromises: Promise<void>[] = [];\n\n for (const [id, transport] of this.transports) {\n if (this.isBatchTransport(transport)) {\n const flushPromise = transport.flush().catch((error) => {\n this.emit('error', error, id);\n });\n flushPromises.push(flushPromise);\n }\n }\n\n await Promise.allSettled(flushPromises);\n this.emit('flush', 'all', this.transports.size);\n }\n\n async close(): Promise<void> {\n this.isShuttingDown = true;\n\n // Flush all transports first\n await this.flush();\n\n // Close all transports\n const closePromises: Promise<void>[] = [];\n\n for (const [id, transport] of this.transports) {\n if (transport.close) {\n const closePromise = transport.close().catch((error) => {\n this.emit('error', error, id);\n });\n closePromises.push(closePromise);\n }\n }\n\n await Promise.allSettled(closePromises);\n\n this.transports.clear();\n this.metrics.clear();\n this.removeAllListeners();\n }\n\n // Utility methods\n getTransports(): string[] {\n return Array.from(this.transports.keys());\n }\n\n getTransport(id: string): ITransport | undefined {\n return this.transports.get(id);\n }\n\n getMetrics(): TransportMetrics[] {\n return Array.from(this.metrics.values());\n }\n\n getMetricsForTransport(id: string): TransportMetrics | undefined {\n return this.metrics.get(id);\n }\n\n isTransportReady(id: string): Promise<boolean> {\n const transport = this.transports.get(id);\n if (!transport) return Promise.resolve(false);\n\n if (this.isAsyncTransport(transport)) {\n return transport.isReady();\n }\n\n return Promise.resolve(true);\n }\n\n // Type guards\n private isAsyncTransport(transport: ITransport): transport is IAsyncTransport {\n return (\n 'isReady' in transport && typeof (transport as Record<string, unknown>).isReady === 'function'\n );\n }\n\n private isBatchTransport(transport: ITransport): transport is IBatchTransport {\n return (\n 'flush' in transport && typeof (transport as Record<string, unknown>).flush === 'function'\n );\n }\n\n // Event handling helpers\n onLog(callback: (entry: TransportLogEntry) => void): void {\n this.on('log', callback);\n }\n\n onError(callback: (error: Error, transport: string) => void): void {\n this.on('error', callback);\n }\n\n onFlush(callback: (transport: string, count: number) => void): void {\n this.on('flush', callback);\n }\n\n onTransportAdded(callback: (id: string, transport: ITransport) => void): void {\n this.on('transport:added', callback);\n }\n\n onTransportRemoved(callback: (id: string) => void): void {\n this.on('transport:removed', callback);\n }\n\n // Health check\n async healthCheck(): Promise<{\n healthy: boolean;\n details: Record<string, unknown>;\n }> {\n const details: Record<string, unknown> = {};\n let healthy = true;\n\n for (const [id] of this.transports) {\n try {\n const isReady = await this.isTransportReady(id);\n details[id] = { ready: isReady, metrics: this.metrics.get(id) };\n if (!isReady) healthy = false;\n } catch (error) {\n details[id] = {\n error: error instanceof Error ? error.message : 'Unknown error',\n };\n healthy = false;\n }\n }\n\n return { healthy, details };\n }\n\n // Transport Level Configuration Methods\n enableLevelPrompting(): void {\n this.promptForLevels = true;\n internalLog('Transport level prompting enabled');\n }\n\n disableLevelPrompting(): void {\n this.promptForLevels = false;\n internalLog('Transport level prompting disabled');\n }\n\n async promptUserForTransportLevels(transportId: string): Promise<string[]> {\n const availableLevels = ['error', 'warn', 'info', 'debug', 'trace', 'verbose'];\n\n return new Promise((resolve) => {\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stdout,\n });\n\n process.stdout.write(`\\nConfigure log levels for transport '${transportId}'\\n`);\n process.stdout.write(`Available levels: ${availableLevels.join(', ')}\\n`);\n process.stdout.write(\n 'Enter levels separated by commas (e.g., error,warn,info) or \"all\" for all levels:\\n'\n );\n\n rl.question('> ', (answer) => {\n rl.close();\n\n if (answer.toLowerCase().trim() === 'all') {\n resolve(availableLevels);\n } else {\n const selectedLevels = answer\n .split(',')\n .map((level) => level.trim().toLowerCase())\n .filter((level) => availableLevels.includes(level));\n\n if (selectedLevels.length === 0) {\n internalWarn('No valid levels selected, using all levels');\n resolve(availableLevels);\n } else {\n internalLog(`Selected levels for ${transportId}: ${selectedLevels.join(', ')}`);\n resolve(selectedLevels);\n }\n }\n });\n });\n }\n\n async configureTransportLevels(transportId: string): Promise<void> {\n if (this.promptForLevels && !this.transportLevelPreferences.has(transportId)) {\n const selectedLevels = await this.promptUserForTransportLevels(transportId);\n this.transportLevelPreferences.set(transportId, selectedLevels);\n }\n }\n\n setTransportLevels(transportId: string, levels: string[]): void {\n this.transportLevelPreferences.set(transportId, levels);\n internalLog(`Transport '${transportId}' configured for levels: ${levels.join(', ')}`);\n }\n\n getTransportLevels(transportId: string): string[] | undefined {\n return this.transportLevelPreferences.get(transportId);\n }\n\n clearTransportLevelPreferences(): void {\n this.transportLevelPreferences.clear();\n internalLog('Transport level preferences cleared');\n }\n}\n"],"mappings":"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"}