@mks2508/better-logger 0.18.2-alpha.1 → 0.18.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +38 -336
- package/dist/Logger.d.ts +356 -157
- package/dist/Logger.d.ts.map +1 -1
- package/dist/ScopedLogger.d.ts +549 -9
- package/dist/ScopedLogger.d.ts.map +1 -1
- package/dist/chunks/HookBridge-C-AvXmPD.cjs +504 -0
- package/dist/chunks/HookBridge-C-AvXmPD.cjs.map +1 -0
- package/dist/chunks/HookBridge-CI2PH79S.js +487 -0
- package/dist/chunks/HookBridge-CI2PH79S.js.map +1 -0
- package/dist/chunks/{LogContext-L7HzynFw.cjs → LogContext-BaMXleWj.cjs} +19 -4
- package/dist/chunks/LogContext-BaMXleWj.cjs.map +1 -0
- package/dist/chunks/LogContext-DZasm_P5.cjs +141 -0
- package/dist/chunks/LogContext-DZasm_P5.cjs.map +1 -0
- package/dist/chunks/{LogContext-Cwn-1Zzb.js → LogContext-DjlITOzZ.js} +19 -4
- package/dist/chunks/LogContext-DjlITOzZ.js.map +1 -0
- package/dist/chunks/LogContext-Dyzs61XG.js +136 -0
- package/dist/chunks/LogContext-Dyzs61XG.js.map +1 -0
- package/dist/chunks/SerializerBridge-Ba43Mk7j.js +393 -0
- package/dist/chunks/SerializerBridge-Ba43Mk7j.js.map +1 -0
- package/dist/chunks/SerializerBridge-C4a9Z37F.cjs +410 -0
- package/dist/chunks/SerializerBridge-C4a9Z37F.cjs.map +1 -0
- package/dist/chunks/{StyleManager-CIpd6wbO.cjs → StyleManager-DQ6UNRB-.cjs} +37 -11
- package/dist/chunks/StyleManager-DQ6UNRB-.cjs.map +1 -0
- package/dist/chunks/StyleManager-DjwAYbxE.js +113 -0
- package/dist/chunks/StyleManager-DjwAYbxE.js.map +1 -0
- package/dist/chunks/{core-PoT7RrTK.js → core-Blfi2klP.js} +1 -4
- package/dist/chunks/core-Blfi2klP.js.map +1 -0
- package/dist/chunks/{core-Dzz7agGa.cjs → core-CqS_UBzJ.cjs} +1 -4
- package/dist/chunks/core-CqS_UBzJ.cjs.map +1 -0
- package/dist/chunks/{environment-detector-CI3TrWK_.js → environment-detector-7NvnYUfr.js} +11 -11
- package/dist/chunks/environment-detector-7NvnYUfr.js.map +1 -0
- package/dist/chunks/{environment-detector-Cnn6wr6O.cjs → environment-detector-D-tHkKWA.cjs} +11 -11
- package/dist/chunks/environment-detector-D-tHkKWA.cjs.map +1 -0
- package/dist/chunks/server-fallback-CaCPjWby.cjs +119 -0
- package/dist/chunks/server-fallback-CaCPjWby.cjs.map +1 -0
- package/dist/chunks/server-fallback-jj0T6XaK.js +114 -0
- package/dist/chunks/server-fallback-jj0T6XaK.js.map +1 -0
- package/dist/chunks/{spinner-DNvxbM9a.cjs → spinner-BHyYEXsM.cjs} +319 -37
- package/dist/chunks/spinner-BHyYEXsM.cjs.map +1 -0
- package/dist/chunks/{spinner-D3FsF78o.js → spinner-BtkwpzYv.js} +319 -37
- package/dist/chunks/spinner-BtkwpzYv.js.map +1 -0
- package/dist/chunks/styling-CRw3KQW4.js +1592 -0
- package/dist/chunks/styling-CRw3KQW4.js.map +1 -0
- package/dist/chunks/styling-Cel2wPRy.cjs +1645 -0
- package/dist/chunks/styling-Cel2wPRy.cjs.map +1 -0
- package/dist/chunks/transports-BGfwwakw.js +1237 -0
- package/dist/chunks/transports-BGfwwakw.js.map +1 -0
- package/dist/chunks/transports-BZ-Mc2IT.cjs +1450 -0
- package/dist/chunks/transports-BZ-Mc2IT.cjs.map +1 -0
- package/dist/chunks/transports-DvaLAeGJ.js +1403 -0
- package/dist/chunks/transports-DvaLAeGJ.js.map +1 -0
- package/dist/chunks/transports-yK6CL0Ml.cjs +1278 -0
- package/dist/chunks/transports-yK6CL0Ml.cjs.map +1 -0
- package/dist/chunks/{utils-BqlFYocD.cjs → utils-W_cxqriN.cjs} +44 -37
- package/dist/chunks/utils-W_cxqriN.cjs.map +1 -0
- package/dist/chunks/{utils-VETbVpkR.js → utils-tKfBAWUM.js} +44 -37
- package/dist/chunks/utils-tKfBAWUM.js.map +1 -0
- package/dist/cli/CommandProcessor.d.ts +166 -19
- package/dist/cli/CommandProcessor.d.ts.map +1 -1
- package/dist/cli/commands/ConfigCommand.d.ts +36 -1
- package/dist/cli/commands/ConfigCommand.d.ts.map +1 -1
- package/dist/cli/commands/ExportCommand.d.ts +49 -3
- package/dist/cli/commands/ExportCommand.d.ts.map +1 -1
- package/dist/cli/commands/ThemeCommand.d.ts +62 -3
- package/dist/cli/commands/ThemeCommand.d.ts.map +1 -1
- package/dist/cli/help.d.ts +30 -2
- package/dist/cli/help.d.ts.map +1 -1
- package/dist/cli/index.d.ts +29 -2
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli.cjs +2 -2
- package/dist/cli.js +2 -2
- package/dist/context/LogContext.d.ts +167 -70
- package/dist/context/LogContext.d.ts.map +1 -1
- package/dist/context.cjs +1 -1
- package/dist/context.js +1 -1
- package/dist/core.cjs +52 -29
- package/dist/core.cjs.map +1 -1
- package/dist/core.d.ts +50 -27
- package/dist/core.d.ts.map +1 -1
- package/dist/core.js +52 -29
- package/dist/core.js.map +1 -1
- package/dist/hooks/HookBridge.d.ts +15 -9
- package/dist/hooks/HookBridge.d.ts.map +1 -1
- package/dist/hooks/HookManager.d.ts +295 -2
- package/dist/hooks/HookManager.d.ts.map +1 -1
- package/dist/hooks.cjs +1 -1
- package/dist/hooks.js +1 -1
- package/dist/index.cjs +1415 -214
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +5 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1413 -215
- package/dist/index.js.map +1 -1
- package/dist/playground/TerminalBridge.d.ts +23 -16
- package/dist/playground/TerminalBridge.d.ts.map +1 -1
- package/dist/playground/box.d.ts +36 -5
- package/dist/playground/box.d.ts.map +1 -1
- package/dist/playground/cli-table.d.ts +41 -5
- package/dist/playground/cli-table.d.ts.map +1 -1
- package/dist/playground/divider.d.ts +22 -3
- package/dist/playground/divider.d.ts.map +1 -1
- package/dist/playground/header.d.ts +21 -4
- package/dist/playground/header.d.ts.map +1 -1
- package/dist/playground/server-fallback.d.ts +96 -9
- package/dist/playground/server-fallback.d.ts.map +1 -1
- package/dist/playground/spinner.d.ts +159 -10
- package/dist/playground/spinner.d.ts.map +1 -1
- package/dist/playground/step.d.ts +25 -6
- package/dist/playground/step.d.ts.map +1 -1
- package/dist/playground.cjs +1 -1
- package/dist/playground.js +1 -1
- package/dist/serializers/SerializerBridge.d.ts +13 -6
- package/dist/serializers/SerializerBridge.d.ts.map +1 -1
- package/dist/serializers/SerializerRegistry.d.ts +236 -0
- package/dist/serializers/SerializerRegistry.d.ts.map +1 -1
- package/dist/serializers.cjs +1 -1
- package/dist/serializers.js +1 -1
- package/dist/styles/StyleManager.d.ts +138 -31
- package/dist/styles/StyleManager.d.ts.map +1 -1
- package/dist/styles.cjs +2 -2
- package/dist/styles.js +2 -2
- package/dist/styling/SmartPresets.d.ts +100 -6
- package/dist/styling/SmartPresets.d.ts.map +1 -1
- package/dist/styling/StyleBuilder.d.ts +453 -32
- package/dist/styling/StyleBuilder.d.ts.map +1 -1
- package/dist/styling/banners.d.ts +83 -7
- package/dist/styling/banners.d.ts.map +1 -1
- package/dist/styling/themes.d.ts +41 -2
- package/dist/styling/themes.d.ts.map +1 -1
- package/dist/transports/ConsoleTransport.d.ts +95 -0
- package/dist/transports/ConsoleTransport.d.ts.map +1 -1
- package/dist/transports/FileTransport.d.ts +99 -18
- package/dist/transports/FileTransport.d.ts.map +1 -1
- package/dist/transports/HttpTransport.d.ts +135 -22
- package/dist/transports/HttpTransport.d.ts.map +1 -1
- package/dist/transports/OtlpTraceTransport.d.ts +118 -0
- package/dist/transports/OtlpTraceTransport.d.ts.map +1 -0
- package/dist/transports/OtlpTransport.d.ts +80 -37
- package/dist/transports/OtlpTransport.d.ts.map +1 -1
- package/dist/transports/SpanRuntime.d.ts +73 -0
- package/dist/transports/SpanRuntime.d.ts.map +1 -0
- package/dist/transports/TransportBridge.d.ts +19 -13
- package/dist/transports/TransportBridge.d.ts.map +1 -1
- package/dist/transports/TransportManager.d.ts +232 -10
- package/dist/transports/TransportManager.d.ts.map +1 -1
- package/dist/transports/index.d.ts +1 -0
- package/dist/transports/index.d.ts.map +1 -1
- package/dist/transports-module.d.ts +3 -1
- package/dist/transports-module.d.ts.map +1 -1
- package/dist/transports.cjs +2 -1
- package/dist/transports.js +2 -2
- package/dist/types/core.d.ts +155 -59
- package/dist/types/core.d.ts.map +1 -1
- package/dist/types/hooks.d.ts +92 -14
- package/dist/types/hooks.d.ts.map +1 -1
- package/dist/types/index.d.ts +1 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/serializers.d.ts +72 -0
- package/dist/types/serializers.d.ts.map +1 -1
- package/dist/types/transports.d.ts +163 -39
- package/dist/types/transports.d.ts.map +1 -1
- package/dist/utils/ansi-colors.d.ts +15 -15
- package/dist/utils/asyncLocalStorage.d.ts +33 -0
- package/dist/utils/asyncLocalStorage.d.ts.map +1 -0
- package/dist/utils/environment-detector.d.ts +11 -11
- package/dist/utils/formatting.d.ts +8 -8
- package/dist/utils/output.d.ts +9 -9
- package/dist/utils/output.d.ts.map +1 -1
- package/dist/utils/stackTrace.d.ts +2 -2
- package/package.json +24 -25
- package/dist/chunks/HookBridge-CiRfR67f.cjs +0 -190
- package/dist/chunks/HookBridge-CiRfR67f.cjs.map +0 -1
- package/dist/chunks/HookBridge-SgMmbXZB.js +0 -173
- package/dist/chunks/HookBridge-SgMmbXZB.js.map +0 -1
- package/dist/chunks/LogContext-Cwn-1Zzb.js.map +0 -1
- package/dist/chunks/LogContext-L7HzynFw.cjs.map +0 -1
- package/dist/chunks/SerializerBridge-BaOQOb8q.cjs +0 -166
- package/dist/chunks/SerializerBridge-BaOQOb8q.cjs.map +0 -1
- package/dist/chunks/SerializerBridge-BkpQu5c9.js +0 -149
- package/dist/chunks/SerializerBridge-BkpQu5c9.js.map +0 -1
- package/dist/chunks/StyleManager-CIpd6wbO.cjs.map +0 -1
- package/dist/chunks/StyleManager-LCvVlVdx.js +0 -87
- package/dist/chunks/StyleManager-LCvVlVdx.js.map +0 -1
- package/dist/chunks/core-Dzz7agGa.cjs.map +0 -1
- package/dist/chunks/core-PoT7RrTK.js.map +0 -1
- package/dist/chunks/environment-detector-CI3TrWK_.js.map +0 -1
- package/dist/chunks/environment-detector-Cnn6wr6O.cjs.map +0 -1
- package/dist/chunks/server-fallback-BUKjdLS7.cjs +0 -42
- package/dist/chunks/server-fallback-BUKjdLS7.cjs.map +0 -1
- package/dist/chunks/server-fallback-BsuWH1Dk.js +0 -37
- package/dist/chunks/server-fallback-BsuWH1Dk.js.map +0 -1
- package/dist/chunks/spinner-D3FsF78o.js.map +0 -1
- package/dist/chunks/spinner-DNvxbM9a.cjs.map +0 -1
- package/dist/chunks/styling-84N8T97t.js +0 -941
- package/dist/chunks/styling-84N8T97t.js.map +0 -1
- package/dist/chunks/styling-Cg5saQ46.cjs +0 -994
- package/dist/chunks/styling-Cg5saQ46.cjs.map +0 -1
- package/dist/chunks/transports-BiDk345e.js +0 -715
- package/dist/chunks/transports-BiDk345e.js.map +0 -1
- package/dist/chunks/transports-COPWmlF1.cjs +0 -756
- package/dist/chunks/transports-COPWmlF1.cjs.map +0 -1
- package/dist/chunks/utils-BqlFYocD.cjs.map +0 -1
- package/dist/chunks/utils-VETbVpkR.js.map +0 -1
- package/dist/example.d.ts +0 -18
- package/dist/example.d.ts.map +0 -1
- package/dist/main.d.ts +0 -2
- package/dist/main.d.ts.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"transports-BiDk345e.js","names":["proc"],"sources":["../../src/types/transports.ts","../../src/transports/ConsoleTransport.ts","../../src/transports/FileTransport.ts","../../src/transports/HttpTransport.ts","../../src/transports/OtlpTransport.ts","../../src/transports/TransportManager.ts"],"sourcesContent":["import type { LogLevel, LogTag, StackInfo } from './core.js';\n\n/**\n * Map a `LogLevel` to the OpenTelemetry numeric severity (1-24) used by\n * SigNoz / any OTLP/HTTP backend. Spec-compliant banded values:\n * TRACE=1-4, DEBUG=5-8, INFO=9-12, WARN=13-16, ERROR=17-20, FATAL=21-24\n * We use the canonical mid-band value per level.\n *\n * @see https://opentelemetry.io/docs/specs/otel/logs/data-model/#severity-fields\n */\nexport const LOG_LEVEL_TO_SEVERITY_NUMBER: Record<LogLevel, number> = {\n trace: 1, // TRACE\n debug: 5, // DEBUG\n info: 9, // INFO\n warn: 13, // WARN\n error: 17, // ERROR\n critical: 21 // FATAL\n} as const;\n\n/**\n * Map a `LogLevel` to its OpenTelemetry severity name (uppercase, OTel spec).\n */\nexport const LOG_LEVEL_TO_SEVERITY_TEXT: Record<LogLevel, string> = {\n trace: 'TRACE',\n debug: 'DEBUG',\n info: 'INFO',\n warn: 'WARN',\n error: 'ERROR',\n critical: 'FATAL'\n} as const;\n\n/**\n * OTel resource attributes attached once per batch (service.name, version, env, ...).\n * Values are string-coerced by the transport layer.\n */\nexport interface ILogResource {\n 'service.name': string;\n 'service.version'?: string;\n 'deployment.environment'?: string;\n [key: string]: string | undefined;\n}\n\n/**\n * Structured attribute bag (OpenTelemetry-compatible). Every key maps to\n * a typed value; the transport layer decides how to serialise it.\n */\nexport type LogAttributeValue = string | number | boolean | null | LogAttributeValue[] | { [k: string]: LogAttributeValue };\nexport interface ILogAttributes {\n [key: string]: LogAttributeValue;\n}\n\n/**\n * The payload sent to every transport on each `log()` call. Fields are\n * deliberately explicit (no `[key: string]: any` safety hatch) so transport\n * implementations like `OtlpTransport` can map 1:1 to OTLP `logRecords`.\n */\nexport interface TransportRecord {\n /** Canonical log level (trace/debug/info/warn/error/critical). */\n level: LogLevel;\n /** Numeric severity, copied from `LOG_LEVELS[level]`. */\n levelValue: number;\n /** OTel numeric severity (1-24). Set automatically by Logger. */\n severityNumber: number;\n /** OTel severity name (TRACE/DEBUG/INFO/WARN/ERROR/FATAL). */\n severityText: string;\n /** Epoch milliseconds at log time. */\n time: number;\n /** Final, post-hook message text. */\n msg: string;\n /** Optional logical scope (e.g. \"Auth\", \"API:Users\"). */\n prefix?: string;\n /** Caller location, only when `enableStackTrace` is true. */\n location?: {\n file: string;\n line: number;\n column: number;\n function?: string;\n };\n /** 32-char hex trace id (OTel), when correlated with an active span. */\n traceId?: string;\n /** 16-char hex span id (OTel), when correlated with an active span. */\n spanId?: string;\n /** Structured attributes (requestId, userId, custom tags). */\n attributes?: ILogAttributes;\n /** Per-log resource (overrides Transport-level resource). */\n resource?: Partial<ILogResource>;\n /** Special \"success\" tag — set by `Logger.success()`. */\n tag?: LogTag;\n}\n\n/**\n * Options accepted by any transport at registration time.\n */\nexport interface TransportOptions {\n level?: LogLevel;\n /** Transform the record before it's serialised. Return null to drop. */\n transform?: (record: TransportRecord) => TransportRecord | null;\n /** Flush once the buffer reaches this many records. */\n batchSize?: number;\n /** Flush periodically at this interval (ms). */\n flushInterval?: number;\n /** Hard cap on buffered records. Older entries are dropped on overflow. */\n maxBufferSize?: number;\n}\n\n/**\n * A transport registration. `target` can be:\n * - An `ITransport` instance (legacy / inline).\n * - A string registered in `TransportManager`'s built-in registry\n * (`'console' | 'file' | 'http' | 'otlp'`).\n */\nexport interface TransportTarget {\n target: string | ITransport;\n options?: TransportOptions;\n level?: LogLevel;\n}\n\n/**\n * Minimal contract every transport must satisfy.\n */\nexport interface ITransport {\n readonly name: string;\n write(record: TransportRecord): void | Promise<void>;\n flush?(): void | Promise<void>;\n close?(): void | Promise<void>;\n isReady?(): boolean;\n}\n\n/**\n * Buffered transport contract. Concrete transports like `HttpTransport`,\n * `FileTransport` and `OtlpTransport` extend this.\n */\nexport interface IBufferedTransport extends ITransport {\n readonly bufferSize: number;\n readonly maxBufferSize: number;\n flush(): Promise<void>;\n}\n\n/**\n * Transport registry / dispatch contract.\n */\nexport interface ITransportManager {\n add(target: TransportTarget): string;\n remove(id: string): boolean;\n write(record: TransportRecord): Promise<void>;\n flush(): Promise<void>;\n close(): Promise<void>;\n}\n","import type { TransportRecord, TransportOptions, ITransport, LogLevel } from '../types/index.js';\n\nexport class ConsoleTransport implements ITransport {\n readonly name = 'console';\n\n constructor(private options?: TransportOptions) {}\n\n write(record: TransportRecord): void {\n const method = this.getConsoleMethod(record.level);\n const prefix = record.prefix ? `[${record.prefix}] ` : '';\n const location = record.location\n ? ` (${record.location.file}:${record.location.line})`\n : '';\n\n console[method](`[${record.level.toUpperCase()}]${prefix} ${record.msg}${location}`);\n }\n\n private getConsoleMethod(level: LogLevel): 'log' | 'info' | 'warn' | 'error' {\n switch (level) {\n case 'debug': return 'log';\n case 'info': return 'info';\n case 'warn': return 'warn';\n case 'error':\n case 'critical': return 'error';\n default: return 'log';\n }\n }\n}\n","import type {\n TransportRecord,\n TransportOptions,\n ITransport,\n IBufferedTransport,\n HookLogEntry,\n HookEvent\n} from '../types/index.js';\n\nconst MAX_BUFFER_DEFAULT = 10_000;\nconst BATCH_SIZE_DEFAULT = 100;\nconst FS_PROMISES_LOAD_TIMEOUT_MS = 50;\nconst LOCAL_STORAGE_KEY_PREFIX = 'better-logger:';\n\n/**\n * Options for {@link FileTransport}. Uses `destination` as the file path in\n * Node and as a `localStorage` key in the browser (the path component is\n * sanitised to `[a-zA-Z0-9_-]`).\n *\n */\nexport interface FileTransportOptions extends TransportOptions {\n /**\n * Where to write. In Node this is a file path (resolved relative to\n * `process.cwd()` and sanitised against path traversal). In the browser\n * this is a localStorage key (sanitised to alphanumeric + `-_`).\n * @default 'app.log' (Node) | 'better-logger:default' (browser)\n */\n destination?: string;\n /**\n * Optional hook fired when the transport cannot write (FS error,\n * quota exceeded, browser tab in private mode, ...). Receives a\n * synthetic {@link HookLogEntry}.\n */\n onError?: (entry: HookLogEntry) => void | Promise<void>;\n}\n\n/**\n * File-based transport.\n *\n * - In Node, writes batches via `fs.promises.appendFile` (non-blocking).\n * - In the browser, writes batches into `localStorage` (fallback no-op if\n * `localStorage` is unavailable — e.g. private mode, sandboxed iframes).\n *\n * Fixed in 5.1.0:\n * - BUG-N3: uses async `fs.promises.appendFile` instead of sync `appendFileSync`.\n * - BUG-N4: destination is sanitised to reject path traversal (`..`, `~`, abs paths).\n * - BUG-N5: dynamic `import('node:fs/promises')` instead of CJS `require('fs')`.\n * - BUG-N6: browser case uses `localStorage` with try/catch (was silent no-op).\n *\n */\nexport class FileTransport implements IBufferedTransport {\n readonly name = 'file';\n\n private buffer: string[] = [];\n private flushTimer?: ReturnType<typeof setInterval>;\n private options: FileTransportOptions;\n private closed = false;\n\n constructor(options?: FileTransportOptions) {\n this.options = {\n batchSize: BATCH_SIZE_DEFAULT,\n maxBufferSize: MAX_BUFFER_DEFAULT,\n ...(options ?? {})\n };\n\n if (this.options.flushInterval) {\n this.flushTimer = setInterval(() => {\n void this.flush();\n }, this.options.flushInterval);\n }\n }\n\n get bufferSize(): number {\n return this.buffer.length;\n }\n\n get maxBufferSize(): number {\n return this.options.maxBufferSize ?? MAX_BUFFER_DEFAULT;\n }\n\n isReady(): boolean {\n return !this.closed;\n }\n\n write(record: TransportRecord): void {\n if (this.closed) return;\n\n // Drop the oldest record when the buffer is already at the cap\n // (BUG-N3 follow-up — without this the file transport grows\n // unbounded under a sustained outage, mirroring the old HttpTransport\n // leak that F005 already fixed).\n if (this.buffer.length >= this.maxBufferSize) {\n const dropped = this.buffer.shift();\n if (dropped && this.options.onError) {\n const entry: HookLogEntry = {\n level: 'warn',\n message: 'FileTransport buffer overflow: oldest record dropped',\n args: [],\n timestamp: new Date().toISOString(),\n hookEvent: 'onError' as HookEvent,\n error: new Error('FileTransport buffer overflow'),\n extra: { droppedRecord: dropped }\n };\n void this.options.onError(entry);\n }\n }\n\n this.buffer.push(JSON.stringify(record) + '\\n');\n\n const batchSize = this.options.batchSize ?? BATCH_SIZE_DEFAULT;\n if (this.buffer.length >= batchSize) {\n void this.flush();\n }\n }\n\n async flush(): Promise<void> {\n if (this.closed || this.buffer.length === 0) return;\n\n const payload = this.buffer.join('');\n this.buffer = [];\n\n if (isNodeLike()) {\n await this.flushNode(payload);\n } else {\n await this.flushBrowser(payload);\n }\n }\n\n private async flushNode(payload: string): Promise<void> {\n const destination = this.resolveNodeDestination();\n try {\n // Dynamic import so we don't ship Node-only code into the\n // browser bundle and so ESM consumers don't have to deal with\n // `require` being undefined.\n const fsPromises = await loadNodeFsPromises();\n await fsPromises.appendFile(destination, payload, 'utf8');\n } catch (error) {\n this.emitError('FileTransport failed to write to disk', error);\n }\n }\n\n private async flushBrowser(payload: string): Promise<void> {\n if (typeof localStorage === 'undefined') {\n this.emitError('FileTransport: localStorage is not available in this environment', null);\n return;\n }\n try {\n const key = LOCAL_STORAGE_KEY_PREFIX + this.resolveBrowserKey();\n const existing = localStorage.getItem(key) ?? '';\n localStorage.setItem(key, existing + payload);\n } catch (error) {\n this.emitError('FileTransport: localStorage write failed (quota? private mode?)', error);\n }\n }\n\n async close(): Promise<void> {\n this.closed = true;\n if (this.flushTimer) {\n clearInterval(this.flushTimer);\n this.flushTimer = undefined;\n }\n await this.flush();\n }\n\n private resolveNodeDestination(): string {\n const requested = this.options.destination ?? 'app.log';\n const sanitised = sanitiseNodePath(requested);\n if (sanitised === null) {\n this.emitError(`FileTransport: refusing destination with traversal segment: ${requested}`, null);\n return 'app.log';\n }\n return sanitised;\n }\n\n private resolveBrowserKey(): string {\n const requested = this.options.destination ?? 'default';\n return sanitiseBrowserKey(requested);\n }\n\n private emitError(message: string, cause: unknown): void {\n if (!this.options.onError) return;\n const entry: HookLogEntry = {\n level: 'error',\n message,\n args: [],\n timestamp: new Date().toISOString(),\n hookEvent: 'onError' as HookEvent,\n error: cause instanceof Error ? cause : new Error(String(cause))\n };\n void this.options.onError(entry);\n }\n}\n\n// ===== Environment helpers =====\n\nfunction isNodeLike(): boolean {\n return typeof process !== 'undefined'\n && process.versions != null\n && process.versions.node != null;\n}\n\n// ===== Sanitisers =====\n\n/**\n * Reject paths that escape the working directory. Allows relative paths\n * under `cwd/`. Absolute paths are rejected by default — if a caller needs\n * an absolute location, pass it through a documented escape hatch (not\n * exposed here on purpose).\n */\nfunction sanitiseNodePath(input: string): string | null {\n if (!input) return null;\n const normalised = input.replace(/\\\\/g, '/').trim();\n if (normalised.length === 0) return null;\n if (normalised.startsWith('/') || /^[a-zA-Z]:\\//.test(normalised)) return null;\n const segments = normalised.split('/').filter(s => s.length > 0 && s !== '.');\n if (segments.some(s => s === '..' || s === '~')) return null;\n return segments.join('/');\n}\n\nfunction sanitiseBrowserKey(input: string): string {\n return input.replace(/[^a-zA-Z0-9_-]/g, '_').slice(0, 64) || 'default';\n}\n\n// ===== Node fs loader =====\n\n/**\n * Cached dynamic import of `node:fs/promises`. The cache is intentionally\n * module-scoped so subsequent flushes don't pay the import cost.\n */\nlet _fsPromisesPromise: Promise<typeof import('node:fs/promises')> | null = null;\n\nasync function loadNodeFsPromises(): Promise<typeof import('node:fs/promises')> {\n if (_fsPromisesPromise) return _fsPromisesPromise;\n\n // Race the dynamic import against a short timeout so a hung Node\n // environment (corrupted native bindings, etc.) doesn't block the\n // transport forever.\n const importPromise = import('node:fs/promises');\n const timeoutPromise = new Promise<never>((_, reject) => {\n setTimeout(() => reject(new Error(`fs/promises import timed out after ${FS_PROMISES_LOAD_TIMEOUT_MS}ms`)), FS_PROMISES_LOAD_TIMEOUT_MS);\n });\n _fsPromisesPromise = Promise.race([importPromise, timeoutPromise]).catch(err => {\n _fsPromisesPromise = null;\n throw err;\n }) as Promise<typeof import('node:fs/promises')>;\n return _fsPromisesPromise;\n}","import type {\n TransportRecord,\n TransportOptions,\n ITransport,\n IBufferedTransport,\n HookEvent,\n HookLogEntry\n} from '../types/index.js';\n\n/**\n * Configuration for {@link HttpTransport}. Extends {@link TransportOptions}\n * with HTTP-specific knobs.\n *\n */\nexport interface HttpTransportOptions extends TransportOptions {\n /** Target URL. POST is used with a JSON-encoded body. */\n url?: string;\n /** Extra request headers (e.g. `Authorization: Bearer ...`). */\n headers?: Record<string, string>;\n /** Hard cap on buffered records. Older entries dropped on overflow. */\n maxBufferSize?: number;\n /** Max consecutive retry attempts per batch before the entries are dropped. */\n maxRetries?: number;\n /** Initial backoff in ms. Doubles per attempt up to `maxBackoffMs`. */\n initialBackoffMs?: number;\n /** Backoff ceiling in ms. */\n maxBackoffMs?: number;\n /** Fetch timeout in ms (per attempt). Default 10_000. */\n fetchTimeoutMs?: number;\n /**\n * Optional hook fired when the buffer overflows or a batch is dropped\n * after `maxRetries`. The hook receives a synthetic {@link HookLogEntry}.\n */\n onError?: (entry: HookLogEntry) => void | Promise<void>;\n}\n\nconst DEFAULT_MAX_BUFFER = 10_000;\nconst DEFAULT_BATCH_SIZE = 50;\nconst DEFAULT_MAX_RETRIES = 3;\nconst DEFAULT_INITIAL_BACKOFF = 250;\nconst DEFAULT_MAX_BACKOFF = 5_000;\nconst DEFAULT_FETCH_TIMEOUT = 10_000;\n\n/**\n * HTTP-based transport. Buffers records, batches them on size or interval,\n * POSTs the batch as JSON, and surfaces failures via retry, bounded buffer,\n * and an `onError` hook — never a silent `.catch(() => {})`.\n *\n * Extending this class is the recommended way to ship a new transport:\n * see {@link OtlpTransport}.\n *\n */\nexport class HttpTransport implements IBufferedTransport {\n readonly name: string = 'http';\n\n private buffer: TransportRecord[] = [];\n private flushTimer?: ReturnType<typeof setInterval>;\n private closed = false;\n\n /** Options bag — `protected` so subclasses (e.g. {@link OtlpTransport}) can read or extend it. */\n protected options: HttpTransportOptions;\n\n constructor(options?: HttpTransportOptions) {\n this.options = {\n batchSize: DEFAULT_BATCH_SIZE,\n maxBufferSize: DEFAULT_MAX_BUFFER,\n maxRetries: DEFAULT_MAX_RETRIES,\n initialBackoffMs: DEFAULT_INITIAL_BACKOFF,\n maxBackoffMs: DEFAULT_MAX_BACKOFF,\n fetchTimeoutMs: DEFAULT_FETCH_TIMEOUT,\n ...(options ?? {})\n };\n\n if (this.options.flushInterval) {\n this.flushTimer = setInterval(() => {\n void this.flush();\n }, this.options.flushInterval);\n }\n }\n\n get bufferSize(): number {\n return this.buffer.length;\n }\n\n get maxBufferSize(): number {\n return this.options.maxBufferSize ?? DEFAULT_MAX_BUFFER;\n }\n\n isReady(): boolean {\n return !this.closed && Boolean(this.options.url);\n }\n\n write(record: TransportRecord): void {\n if (this.closed) return;\n\n if (this.buffer.length >= this.maxBufferSize) {\n this.applyOverflowPolicy();\n }\n\n this.buffer.push(record);\n\n const batchSize = this.options.batchSize ?? DEFAULT_BATCH_SIZE;\n if (this.buffer.length >= batchSize) {\n void this.flush();\n }\n }\n\n /**\n * Serialises a batch into the request body. Subclasses override to\n * switch encodings (e.g. {@link OtlpTransport} produces OTLP/HTTP JSON\n * instead of the default `{ logs: [...] }` envelope).\n *\n */\n protected serializeBody(records: TransportRecord[]): string {\n return JSON.stringify({ logs: records });\n }\n\n /**\n * Builds the request headers. Subclasses may prepend transport-specific\n * headers (e.g. `signoz-ingestion-key`).\n *\n */\n protected buildHeaders(): Record<string, string> {\n return {\n 'Content-Type': 'application/json',\n ...(this.options.headers ?? {})\n };\n }\n\n private applyOverflowPolicy(): void {\n const dropped = this.buffer.shift();\n if (dropped && this.options.onError) {\n const entry: HookLogEntry = {\n level: 'warn',\n message: 'HttpTransport buffer overflow: oldest record dropped',\n args: [dropped],\n timestamp: new Date().toISOString(),\n hookEvent: 'onError' as HookEvent,\n error: new Error('HttpTransport buffer overflow'),\n extra: { droppedRecord: dropped }\n };\n void this.options.onError(entry);\n }\n }\n\n async flush(): Promise<void> {\n if (this.closed || this.buffer.length === 0 || !this.options.url) return;\n\n const records = [...this.buffer];\n this.buffer = [];\n\n const success = await this.sendWithRetry(records);\n if (!success) {\n // Re-buffer at the front to preserve order; if we'd overflow\n // again, the policy above will trim the oldest and surface it.\n const combined = records.concat(this.buffer);\n if (combined.length > this.maxBufferSize) {\n const trimmed = combined.slice(combined.length - this.maxBufferSize);\n const droppedCount = combined.length - trimmed.length;\n if (droppedCount > 0 && this.options.onError) {\n const entry: HookLogEntry = {\n level: 'error',\n message: `HttpTransport dropped ${droppedCount} records after retry exhaustion`,\n args: [],\n timestamp: new Date().toISOString(),\n hookEvent: 'onError' as HookEvent,\n error: new Error('HttpTransport retry exhaustion'),\n extra: { droppedCount }\n };\n void this.options.onError(entry);\n }\n this.buffer = trimmed;\n } else {\n this.buffer = combined;\n }\n }\n }\n\n private async sendWithRetry(records: TransportRecord[]): Promise<boolean> {\n const url = this.options.url;\n if (!url) return false;\n\n const maxRetries = this.options.maxRetries ?? DEFAULT_MAX_RETRIES;\n const initialBackoff = this.options.initialBackoffMs ?? DEFAULT_INITIAL_BACKOFF;\n const maxBackoff = this.options.maxBackoffMs ?? DEFAULT_MAX_BACKOFF;\n const fetchTimeout = this.options.fetchTimeoutMs ?? DEFAULT_FETCH_TIMEOUT;\n const body = this.serializeBody(records);\n const headers = this.buildHeaders();\n\n let attempt = 0;\n let backoff = initialBackoff;\n\n while (attempt <= maxRetries) {\n try {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), fetchTimeout);\n\n const response = await fetch(url, {\n method: 'POST',\n headers,\n body,\n signal: controller.signal\n });\n clearTimeout(timeoutId);\n\n if (response.ok) {\n return true;\n }\n\n // Non-2xx is a logical failure — do NOT retry on 4xx (client\n // mistakes are not transient). 5xx is retried.\n if (response.status >= 400 && response.status < 500) {\n if (this.options.onError) {\n const entry: HookLogEntry = {\n level: 'error',\n message: `HttpTransport ${response.status} ${response.statusText} (not retried)`,\n args: [],\n timestamp: new Date().toISOString(),\n hookEvent: 'onError' as HookEvent,\n error: new Error(`HTTP ${response.status}`),\n extra: { responseStatus: response.status }\n };\n void this.options.onError(entry);\n }\n return false;\n }\n\n // 5xx → retry with backoff\n if (attempt === maxRetries) break;\n await sleep(backoff);\n backoff = Math.min(backoff * 2, maxBackoff);\n } catch (error) {\n if (attempt === maxRetries) {\n if (this.options.onError) {\n const entry: HookLogEntry = {\n level: 'error',\n message: `HttpTransport fetch failed after ${maxRetries + 1} attempts`,\n args: [],\n timestamp: new Date().toISOString(),\n hookEvent: 'onError' as HookEvent,\n error: error instanceof Error ? error : new Error(String(error))\n };\n void this.options.onError(entry);\n }\n return false;\n }\n await sleep(backoff);\n backoff = Math.min(backoff * 2, maxBackoff);\n }\n attempt++;\n }\n return false;\n }\n\n async close(): Promise<void> {\n this.closed = true;\n if (this.flushTimer) {\n clearInterval(this.flushTimer);\n this.flushTimer = undefined;\n }\n await this.flush();\n }\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms));\n}","import type {\n TransportRecord,\n HookLogEntry,\n HookEvent,\n ILogResource\n} from '../types/index.js';\nimport { LOG_LEVEL_TO_SEVERITY_NUMBER } from '../types/index.js';\nimport { HttpTransport, type HttpTransportOptions } from './HttpTransport.js';\n\n/**\n * Options for {@link OtlpTransport}.\n *\n */\nexport interface OtlpTransportOptions {\n /**\n * OTLP/HTTP collector base URL, e.g. `https://collector.example.com:4318`.\n * The transport POSTs to `<endpoint>/v1/logs`.\n */\n endpoint: string;\n /** `service.name` resource attribute. Required by OTel spec. */\n serviceName: string;\n /** `service.version` resource attribute. Recommended. */\n serviceVersion?: string;\n /** `deployment.environment` resource attribute (production/staging/dev). */\n environment?: string;\n /** Extra resource attributes merged into the resource block. */\n resourceAttributes?: Record<string, string>;\n /**\n * Name of an env var whose value is sent as the `signoz-ingestion-key`\n * header. The transport reads `process.env[ingestKeyEnvVar]` at\n * construction time — never from a string literal. If the env var is\n * unset, the header is silently omitted (OTLP collector uses default\n * no-auth path).\n */\n ingestKeyEnvVar?: string;\n /** Extra headers merged in (Authorization, custom X-*). */\n headers?: Record<string, string>;\n /** Batch size (records per POST). Default 50. */\n batchSize?: number;\n /** Flush interval in ms. */\n flushInterval?: number;\n /** Hard cap on buffered records. Default 10_000. */\n maxBufferSize?: number;\n /** Max retry attempts per batch. Default 3. */\n maxRetries?: number;\n /** Initial backoff in ms. Default 250. */\n initialBackoffMs?: number;\n /** Backoff ceiling in ms. Default 5_000. */\n maxBackoffMs?: number;\n /** Per-fetch timeout in ms. Default 10_000. */\n fetchTimeoutMs?: number;\n /** Hook fired on transport failure (drop, retry exhaustion, ...). */\n onError?: (entry: HookLogEntry) => void | Promise<void>;\n}\n\n/**\n * Shape of the OTLP/HTTP JSON request body. Matches the `LogsData` proto\n * JSON mapping for `/v1/logs`. See\n * https://opentelemetry.io/docs/specs/otlp/#json-protobuf-encoding\n */\ninterface OtlpLogsPayload {\n resourceLogs: Array<{\n resource: {\n attributes: Array<{ key: string; value: { stringValue: string } }>;\n };\n scopeLogs: Array<{\n scope: {\n name: string;\n version: string;\n };\n logRecords: Array<OtlpLogRecord>;\n }>;\n }>;\n}\n\ninterface OtlpLogRecord {\n timeUnixNano: string;\n observedTimeUnixNano: string;\n severityNumber: number;\n severityText: string;\n body: { stringValue: string };\n attributes?: Array<{ key: string; value: OtlpAttributeValue }>;\n traceId?: string;\n spanId?: string;\n}\n\ntype OtlpAttributeValue =\n | { stringValue: string }\n | { intValue: number }\n | { doubleValue: number }\n | { boolValue: boolean }\n | { arrayValue: { values: OtlpAttributeValue[] } };\n\n/**\n * OTLP/HTTP transport for SigNoz (or any OTLP-compliant backend).\n *\n * Extends {@link HttpTransport} — inherits retry, bounded buffer, status\n * check, async close, and the on-error hook. Overrides only the payload\n * shape and the request headers.\n *\n * ```ts\n * logger.addTransport({\n * target: new OtlpTransport({\n * endpoint: 'https://otelcollector.example.com:4318',\n * serviceName: 'my-app',\n * serviceVersion: '1.2.3',\n * environment: 'production',\n * ingestKeyEnvVar: 'SIGNOZ_KEY'\n * })\n * });\n * ```\n *\n */\nexport class OtlpTransport extends HttpTransport {\n override readonly name = 'otlp';\n\n private readonly resource: ILogResource;\n /** Resolved at construction. Never logged, never written to source. */\n private readonly ingestKeyValue: string | undefined;\n\n constructor(options: OtlpTransportOptions) {\n if (!options.endpoint) {\n throw new Error('OtlpTransport: `endpoint` is required');\n }\n if (!options.serviceName) {\n throw new Error('OtlpTransport: `serviceName` is required');\n }\n\n const ingestKey = readIngestKey(options.ingestKeyEnvVar);\n\n const httpOptions: HttpTransportOptions = {\n url: `${stripTrailingSlash(options.endpoint)}/v1/logs`,\n headers: {\n ...(ingestKey ? { 'signoz-ingestion-key': ingestKey } : {}),\n ...(options.headers ?? {})\n },\n batchSize: options.batchSize,\n flushInterval: options.flushInterval,\n maxBufferSize: options.maxBufferSize,\n maxRetries: options.maxRetries,\n initialBackoffMs: options.initialBackoffMs,\n maxBackoffMs: options.maxBackoffMs,\n fetchTimeoutMs: options.fetchTimeoutMs,\n onError: options.onError\n };\n\n super(httpOptions);\n\n this.resource = {\n 'service.name': options.serviceName,\n ...(options.serviceVersion ? { 'service.version': options.serviceVersion } : {}),\n ...(options.environment ? { 'deployment.environment': options.environment } : {}),\n ...(options.resourceAttributes ?? {})\n };\n this.ingestKeyValue = ingestKey;\n }\n\n /**\n * Builds the OTLP/HTTP JSON payload from the currently buffered records.\n * One `resourceLogs` block per batch (matches OTel collector batching\n * guidance). Exposed for tests + custom transport subclasses.\n *\n */\n buildPayload(records: TransportRecord[]): OtlpLogsPayload {\n const resourceAttrs = Object.entries(this.resource)\n .filter((entry): entry is [string, string] => typeof entry[1] === 'string')\n .map(([key, value]) => ({ key, value: { stringValue: value } }));\n\n return {\n resourceLogs: [\n {\n resource: { attributes: resourceAttrs },\n scopeLogs: [\n {\n scope: {\n name: 'better-logger',\n version: '5.1.0'\n },\n logRecords: records.map(r => this.toLogRecord(r))\n }\n ]\n }\n ]\n };\n }\n\n /**\n * Serialises a batch into the OTLP/HTTP JSON request body. Overrides\n * {@link HttpTransport.serializeBody}.\n *\n */\n protected override serializeBody(records: TransportRecord[]): string {\n return JSON.stringify(this.buildPayload(records));\n }\n\n /**\n * Builds request headers. Adds `signoz-ingestion-key` from the value\n * resolved at construction time (never logged, never written to source).\n *\n */\n protected override buildHeaders(): Record<string, string> {\n return {\n 'Content-Type': 'application/json',\n ...(this.ingestKeyValue ? { 'signoz-ingestion-key': this.ingestKeyValue } : {}),\n ...(this.options.headers ?? {})\n };\n }\n\n private toLogRecord(record: TransportRecord): OtlpLogRecord {\n const timeUnixNano = String(BigInt(record.time) * 1_000_000n);\n const observedTimeUnixNano = timeUnixNano;\n const severityNumber = LOG_LEVEL_TO_SEVERITY_NUMBER[record.level];\n\n const base: OtlpLogRecord = {\n timeUnixNano,\n observedTimeUnixNano,\n severityNumber,\n severityText: record.severityText,\n body: { stringValue: record.msg }\n };\n\n const attributes = collectAttributes(record);\n if (attributes.length > 0) {\n base.attributes = attributes;\n }\n\n if (record.traceId) base.traceId = record.traceId;\n if (record.spanId) base.spanId = record.spanId;\n\n return base;\n }\n}\n\n// ===== Internal helpers =====\n\nfunction stripTrailingSlash(value: string): string {\n return value.endsWith('/') ? value.slice(0, -1) : value;\n}\n\n/**\n * Reads the ingest API key from `process.env[name]`. Returns undefined\n * silently if `process` is unavailable (strict browser bundles) or the\n * variable is unset. Never throws, never logs the value.\n */\nfunction readIngestKey(envVarName: string | undefined): string | undefined {\n if (!envVarName) return undefined;\n if (typeof process === 'undefined') return undefined;\n const proc = process as { env?: Record<string, string | undefined> };\n const value = proc.env?.[envVarName];\n if (!value) return undefined;\n return value;\n}\n\nfunction collectAttributes(record: TransportRecord): Array<{ key: string; value: OtlpAttributeValue }> {\n const out: Array<{ key: string; value: OtlpAttributeValue }> = [];\n\n if (record.prefix) {\n out.push({ key: 'logger.prefix', value: { stringValue: record.prefix } });\n }\n if (record.tag) {\n out.push({ key: 'logger.tag', value: { stringValue: record.tag } });\n }\n if (record.location) {\n out.push({ key: 'code.filepath', value: { stringValue: record.location.file } });\n out.push({ key: 'code.lineno', value: { intValue: record.location.line } });\n if (record.location.function) {\n out.push({ key: 'code.function', value: { stringValue: record.location.function } });\n }\n }\n\n if (record.attributes) {\n for (const [key, value] of Object.entries(record.attributes)) {\n const mapped = toOtlpAttribute(value);\n if (mapped) out.push({ key, value: mapped });\n }\n }\n\n return out;\n}\n\nfunction toOtlpAttribute(value: unknown): OtlpAttributeValue | null {\n if (value === null || value === undefined) return null;\n if (typeof value === 'string') return { stringValue: value };\n if (typeof value === 'number') {\n if (Number.isInteger(value)) return { intValue: value };\n return { doubleValue: value };\n }\n if (typeof value === 'boolean') return { boolValue: value };\n if (Array.isArray(value)) {\n return {\n arrayValue: {\n values: value\n .map(v => toOtlpAttribute(v))\n .filter((v): v is OtlpAttributeValue => v !== null)\n }\n };\n }\n return { stringValue: JSON.stringify(value) };\n}","import type {\n TransportRecord,\n TransportTarget,\n TransportOptions,\n ITransport,\n ITransportManager,\n LogLevel\n} from '../types/index.js';\nimport { LOG_LEVELS } from '../types/index.js';\nimport { ConsoleTransport } from './ConsoleTransport.js';\nimport { FileTransport } from './FileTransport.js';\nimport { HttpTransport } from './HttpTransport.js';\nimport { OtlpTransport } from './OtlpTransport.js';\n\nfunction generateTransportId(): string {\n return `transport-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;\n}\n\n/**\n * Constructor signature for transports registered in the built-in registry.\n * Accepts the transport's own options type; pass-through is enforced at\n * registration time via TypeScript but erased at runtime.\n */\nexport type TransportConstructor = new (options?: TransportOptions) => ITransport;\n\n/**\n * Built-in registry of named transports. Users can call\n * {@link TransportManager.register} to add their own (e.g. a custom\n * Datadog or Loki transport) and then instantiate it via\n * `addTransport({ target: 'datadog', options })`.\n *\n * The four built-ins are registered automatically:\n * - `'console'` → {@link ConsoleTransport}\n * - `'file'` → {@link FileTransport}\n * - `'http'` → {@link HttpTransport}\n * - `'otlp'` → {@link OtlpTransport}\n */\nconst BUILTIN_REGISTRY: Map<string, TransportConstructor> = new Map([\n ['console', ConsoleTransport as unknown as TransportConstructor],\n ['file', FileTransport as unknown as TransportConstructor],\n ['http', HttpTransport as unknown as TransportConstructor],\n ['otlp', OtlpTransport as unknown as TransportConstructor]\n]);\n\ninterface TransportEntry {\n id: string;\n transport: ITransport;\n options: TransportOptions;\n level: LogLevel;\n levelValue: number;\n}\n\nexport class TransportManager implements ITransportManager {\n private transports: Map<string, TransportEntry> = new Map();\n private defaultLevel: LogLevel = 'info';\n private readonly registry: Map<string, TransportConstructor> = new Map(BUILTIN_REGISTRY);\n\n constructor(defaultLevel?: LogLevel) {\n if (defaultLevel) {\n this.defaultLevel = defaultLevel;\n }\n }\n\n /**\n * Registers a custom transport under a string name. Once registered,\n * `addTransport({ target: 'name', options })` instantiates it.\n *\n * @example\n * transportManager.register('datadog', DatadogTransport);\n * transportManager.add({ target: 'datadog', options: { apiKey: env('DD_KEY') } });\n *\n */\n register(name: string, ctor: TransportConstructor): void {\n if (BUILTIN_REGISTRY.has(name)) {\n throw new Error(`TransportManager.register: '${name}' is a built-in and cannot be overridden`);\n }\n this.registry.set(name, ctor);\n }\n\n /**\n * Lists all registered transport names (built-ins + custom).\n *\n */\n listRegistered(): string[] {\n return [...this.registry.keys()];\n }\n\n add(target: TransportTarget): string {\n const id = generateTransportId();\n const level = target.level || this.defaultLevel;\n\n let transport: ITransport;\n\n if (typeof target.target === 'string') {\n const ctor = this.registry.get(target.target);\n if (!ctor) {\n throw new Error(\n `TransportManager.add: unknown transport name '${target.target}'. ` +\n `Registered: ${this.listRegistered().join(', ')}`\n );\n }\n transport = new ctor(target.options ?? {});\n } else {\n transport = target.target;\n }\n\n const entry: TransportEntry = {\n id,\n transport,\n options: target.options || {},\n level,\n levelValue: LOG_LEVELS[level]\n };\n\n this.transports.set(id, entry);\n return id;\n }\n\n remove(id: string): boolean {\n const entry = this.transports.get(id);\n if (entry) {\n const closeResult = entry.transport.close?.();\n if (closeResult instanceof Promise) {\n void closeResult.catch(() => {\n // close failures are best-effort during remove\n });\n }\n return this.transports.delete(id);\n }\n return false;\n }\n\n async write(record: TransportRecord): Promise<void> {\n const promises: Promise<unknown>[] = [];\n\n for (const entry of this.transports.values()) {\n if (record.levelValue < entry.levelValue) {\n continue;\n }\n\n let transformedRecord: TransportRecord = record;\n if (entry.options.transform) {\n const result = entry.options.transform(record);\n if (result === null) continue;\n transformedRecord = result;\n }\n\n try {\n const result = entry.transport.write(transformedRecord);\n if (result instanceof Promise) {\n promises.push(\n result.catch(err => {\n // Surface write failures through console (no silent drop)\n // without throwing — the logger's main path stays sync.\n // eslint-disable-next-line no-console\n console.error('TransportManager.write: transport failed:', err);\n })\n );\n }\n } catch (error) {\n // Synchronous write errors are surfaced but never break the log call.\n // eslint-disable-next-line no-console\n console.error('TransportManager.write: transport threw synchronously:', error);\n }\n }\n\n await Promise.all(promises);\n }\n\n async flush(): Promise<void> {\n const promises: Promise<unknown>[] = [];\n\n for (const entry of this.transports.values()) {\n if (entry.transport.flush) {\n try {\n const result = entry.transport.flush();\n if (result instanceof Promise) {\n promises.push(result.catch(err => {\n // eslint-disable-next-line no-console\n console.error('TransportManager.flush: transport failed:', err);\n }));\n }\n } catch (error) {\n // eslint-disable-next-line no-console\n console.error('TransportManager.flush: transport threw synchronously:', error);\n }\n }\n }\n\n await Promise.all(promises);\n }\n\n async close(): Promise<void> {\n await this.flush();\n\n const promises: Promise<unknown>[] = [];\n\n for (const entry of this.transports.values()) {\n if (entry.transport.close) {\n try {\n const result = entry.transport.close();\n if (result instanceof Promise) {\n promises.push(result.catch(err => {\n // eslint-disable-next-line no-console\n console.error('TransportManager.close: transport failed:', err);\n }));\n }\n } catch (error) {\n // eslint-disable-next-line no-console\n console.error('TransportManager.close: transport threw synchronously:', error);\n }\n }\n }\n\n await Promise.all(promises);\n this.transports.clear();\n }\n\n get count(): number {\n return this.transports.size;\n }\n\n list(): string[] {\n return Array.from(this.transports.keys());\n }\n}"],"mappings":"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"}
|