@loggerjs/node 0.5.0 → 0.5.1

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 (102) hide show
  1. package/README.md +5 -1
  2. package/dist/bullmq-integration.cjs +169 -0
  3. package/dist/bullmq-integration.cjs.map +1 -0
  4. package/dist/bullmq-integration.js +168 -0
  5. package/dist/bullmq-integration.js.map +1 -0
  6. package/dist/cli-integration.cjs +116 -0
  7. package/dist/cli-integration.cjs.map +1 -0
  8. package/dist/cli-integration.js +115 -0
  9. package/dist/cli-integration.js.map +1 -0
  10. package/dist/context.cjs +37 -0
  11. package/dist/context.cjs.map +1 -0
  12. package/dist/context.js +35 -0
  13. package/dist/context.js.map +1 -0
  14. package/dist/database-integration.cjs +128 -0
  15. package/dist/database-integration.cjs.map +1 -0
  16. package/dist/database-integration.js +127 -0
  17. package/dist/database-integration.js.map +1 -0
  18. package/dist/diagnostics-channel-integration.cjs +66 -0
  19. package/dist/diagnostics-channel-integration.cjs.map +1 -0
  20. package/dist/diagnostics-channel-integration.js +65 -0
  21. package/dist/diagnostics-channel-integration.js.map +1 -0
  22. package/dist/express-integration.cjs +130 -0
  23. package/dist/express-integration.cjs.map +1 -0
  24. package/dist/express-integration.js +129 -0
  25. package/dist/express-integration.js.map +1 -0
  26. package/dist/fastify-integration.cjs +120 -0
  27. package/dist/fastify-integration.cjs.map +1 -0
  28. package/dist/fastify-integration.js +119 -0
  29. package/dist/fastify-integration.js.map +1 -0
  30. package/dist/file-transport.cjs +260 -0
  31. package/dist/file-transport.cjs.map +1 -0
  32. package/dist/file-transport.js +259 -0
  33. package/dist/file-transport.js.map +1 -0
  34. package/dist/hapi-integration.cjs +61 -0
  35. package/dist/hapi-integration.cjs.map +1 -0
  36. package/dist/hapi-integration.js +60 -0
  37. package/dist/hapi-integration.js.map +1 -0
  38. package/dist/http-transport.cjs +55 -0
  39. package/dist/http-transport.cjs.map +1 -0
  40. package/dist/http-transport.js +54 -0
  41. package/dist/http-transport.js.map +1 -0
  42. package/dist/koa-integration.cjs +57 -0
  43. package/dist/koa-integration.cjs.map +1 -0
  44. package/dist/koa-integration.js +56 -0
  45. package/dist/koa-integration.js.map +1 -0
  46. package/dist/logger-diagnostics.cjs +46 -0
  47. package/dist/logger-diagnostics.cjs.map +1 -0
  48. package/dist/logger-diagnostics.js +45 -0
  49. package/dist/logger-diagnostics.js.map +1 -0
  50. package/dist/nest-integration.cjs +138 -0
  51. package/dist/nest-integration.cjs.map +1 -0
  52. package/dist/nest-integration.js +137 -0
  53. package/dist/nest-integration.js.map +1 -0
  54. package/dist/node-fetch-integration.cjs +113 -0
  55. package/dist/node-fetch-integration.cjs.map +1 -0
  56. package/dist/node-fetch-integration.js +112 -0
  57. package/dist/node-fetch-integration.js.map +1 -0
  58. package/dist/node-http-client-integration.cjs +192 -0
  59. package/dist/node-http-client-integration.cjs.map +1 -0
  60. package/dist/node-http-client-integration.js +192 -0
  61. package/dist/node-http-client-integration.js.map +1 -0
  62. package/dist/payload-transforms.cjs +29 -0
  63. package/dist/payload-transforms.cjs.map +1 -0
  64. package/dist/payload-transforms.js +28 -0
  65. package/dist/payload-transforms.js.map +1 -0
  66. package/dist/prisma-integration.cjs +150 -0
  67. package/dist/prisma-integration.cjs.map +1 -0
  68. package/dist/prisma-integration.js +149 -0
  69. package/dist/prisma-integration.js.map +1 -0
  70. package/dist/process-integration.cjs +134 -0
  71. package/dist/process-integration.cjs.map +1 -0
  72. package/dist/process-integration.js +133 -0
  73. package/dist/process-integration.js.map +1 -0
  74. package/dist/queue-integration.cjs +148 -0
  75. package/dist/queue-integration.cjs.map +1 -0
  76. package/dist/queue-integration.js +147 -0
  77. package/dist/queue-integration.js.map +1 -0
  78. package/dist/redis-integration.cjs +154 -0
  79. package/dist/redis-integration.cjs.map +1 -0
  80. package/dist/redis-integration.js +153 -0
  81. package/dist/redis-integration.js.map +1 -0
  82. package/dist/rotating-file-transport.cjs +318 -0
  83. package/dist/rotating-file-transport.cjs.map +1 -0
  84. package/dist/rotating-file-transport.js +317 -0
  85. package/dist/rotating-file-transport.js.map +1 -0
  86. package/dist/serverless-integration.cjs +104 -0
  87. package/dist/serverless-integration.cjs.map +1 -0
  88. package/dist/serverless-integration.js +103 -0
  89. package/dist/serverless-integration.js.map +1 -0
  90. package/dist/stdout-transport.cjs +197 -0
  91. package/dist/stdout-transport.cjs.map +1 -0
  92. package/dist/stdout-transport.js +195 -0
  93. package/dist/stdout-transport.js.map +1 -0
  94. package/dist/syslog-transport.cjs +135 -0
  95. package/dist/syslog-transport.cjs.map +1 -0
  96. package/dist/syslog-transport.js +133 -0
  97. package/dist/syslog-transport.js.map +1 -0
  98. package/dist/worker-transport.cjs +285 -0
  99. package/dist/worker-transport.cjs.map +1 -0
  100. package/dist/worker-transport.js +284 -0
  101. package/dist/worker-transport.js.map +1 -0
  102. package/package.json +104 -77
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rotating-file-transport.cjs","names":[],"sources":["../src/node-destination.ts","../src/rotating-file-transport.ts"],"sourcesContent":["import { closeSync, createWriteStream, mkdirSync, openSync, writeSync, type WriteStream } from \"fs\";\nimport { dirname } from \"path\";\nimport type { TransportContext } from \"@loggerjs/core\";\nimport type { WritableLike } from \"./internal-types\";\n\nexport interface NodeDestination {\n stream?: WriteStream;\n write: (payload: string | Uint8Array, context?: TransportContext) => void;\n flush: () => Promise<void>;\n flushSync: () => void;\n close: () => Promise<void>;\n closeSync: () => void;\n releaseSync?: () => void;\n}\n\nexport interface NodeStreamDestinationOptions {\n name: string;\n stream: WritableLike;\n minLength?: number;\n ignoreEpipe?: boolean;\n reportOperation?: string;\n syncWrite?: (payload: string | Uint8Array) => void;\n}\n\nexport interface NodeFileDestinationOptions {\n name: string;\n path: string;\n flags?: string;\n append?: boolean;\n mkdir?: boolean;\n sync?: boolean;\n minLength?: number;\n}\n\ninterface FlushWaiter {\n resolve: () => void;\n reject: (error: Error) => void;\n}\n\nconst encoder = new TextEncoder();\n\nconst normalizeError = (error: unknown): Error =>\n error instanceof Error ? error : new Error(String(error));\n\nfunction byteLength(payload: string | Uint8Array): number {\n return typeof payload === \"string\" ? encoder.encode(payload).byteLength : payload.byteLength;\n}\n\nfunction coalescePayloads(payloads: Array<string | Uint8Array>): string | Uint8Array {\n if (payloads.every((payload) => typeof payload === \"string\")) {\n return payloads.join(\"\");\n }\n const buffers = payloads.map((payload) =>\n typeof payload === \"string\" ? Buffer.from(payload) : Buffer.from(payload),\n );\n return Buffer.concat(buffers);\n}\n\nfunction isEpipe(error: unknown): boolean {\n return (\n Boolean(error) && typeof error === \"object\" && (error as { code?: unknown }).code === \"EPIPE\"\n );\n}\n\nfunction normalizeMinLength(value: number | undefined): number {\n if (value === undefined || !Number.isFinite(value) || value <= 0) return 0;\n return Math.floor(value);\n}\n\nexport function createNodeStreamDestination(\n options: NodeStreamDestinationOptions,\n): NodeDestination {\n const minLength = normalizeMinLength(options.minLength);\n const ignoreEpipe = options.ignoreEpipe ?? false;\n const waiters: FlushWaiter[] = [];\n const buffer: Array<string | Uint8Array> = [];\n const pendingPayloads: Array<string | Uint8Array> = [];\n let bufferedBytes = 0;\n let pendingWrites = 0;\n let pendingDrains = 0;\n let lastError: Error | undefined;\n let lastContext: TransportContext | undefined;\n let closed = false;\n\n const reportInternalError = (error: unknown, operation: string) => {\n if (ignoreEpipe && isEpipe(error)) return;\n lastContext?.reportInternalError(error, {\n phase: \"transport\",\n transport: options.name,\n operation,\n });\n };\n\n const settleWaitersIfIdle = () => {\n if (pendingWrites + pendingDrains > 0) return;\n if (waiters.length === 0) return;\n const error = lastError;\n lastError = undefined;\n for (const waiter of waiters.splice(0)) {\n if (error) waiter.reject(error);\n else waiter.resolve();\n }\n };\n\n const recordError = (error: unknown, operation: string) => {\n if (ignoreEpipe && isEpipe(error)) {\n closed = true;\n return;\n }\n lastError = normalizeError(error);\n reportInternalError(lastError, operation);\n };\n\n const onStreamError = (error: Error) => {\n recordError(error, \"stream-error\");\n settleWaitersIfIdle();\n };\n const offError = () => options.stream.off?.(\"error\", onStreamError);\n options.stream.on?.(\"error\", onStreamError);\n\n const waitForDrain = () => {\n if (!options.stream.once) return;\n pendingDrains += 1;\n options.stream.once(\"drain\", () => {\n pendingDrains -= 1;\n settleWaitersIfIdle();\n });\n };\n\n const removePending = (payload: string | Uint8Array) => {\n const index = pendingPayloads.indexOf(payload);\n if (index >= 0) pendingPayloads.splice(index, 1);\n };\n\n const writeNow = (payload: string | Uint8Array) => {\n if (closed) return;\n pendingPayloads.push(payload);\n pendingWrites += 1;\n try {\n const result = options.stream.write(payload, (error?: Error | null) => {\n removePending(payload);\n pendingWrites -= 1;\n if (error) recordError(error, options.reportOperation ?? \"write\");\n settleWaitersIfIdle();\n });\n if (result === false) waitForDrain();\n } catch (error) {\n removePending(payload);\n pendingWrites -= 1;\n recordError(error, options.reportOperation ?? \"write\");\n settleWaitersIfIdle();\n }\n };\n\n const flushBuffered = () => {\n if (buffer.length === 0) return;\n const payload = coalescePayloads(buffer.splice(0));\n bufferedBytes = 0;\n writeNow(payload);\n };\n\n const destination: NodeDestination = {\n write(payload, context) {\n if (closed) return;\n lastContext = context;\n if (minLength > 0) {\n buffer.push(payload);\n bufferedBytes += byteLength(payload);\n if (bufferedBytes >= minLength) flushBuffered();\n return;\n }\n writeNow(payload);\n },\n flush() {\n flushBuffered();\n if (pendingWrites + pendingDrains === 0) {\n const error = lastError;\n lastError = undefined;\n if (error) return Promise.reject(error);\n return Promise.resolve();\n }\n return new Promise<void>((resolve, reject) => {\n waiters.push({ resolve, reject });\n });\n },\n flushSync() {\n if (!options.syncWrite) {\n flushBuffered();\n return;\n }\n for (const payload of buffer.splice(0)) options.syncWrite(payload);\n bufferedBytes = 0;\n for (const payload of pendingPayloads.splice(0)) options.syncWrite(payload);\n },\n close() {\n return destination.flush().then(\n () =>\n new Promise<void>((resolve, reject) => {\n if (!options.stream.end) {\n closed = true;\n offError();\n resolve();\n return;\n }\n options.stream.end((error?: Error | null) => {\n closed = true;\n offError();\n if (error && !(ignoreEpipe && isEpipe(error))) reject(error);\n else resolve();\n });\n }),\n (error: unknown) => {\n offError();\n return Promise.reject(error);\n },\n );\n },\n closeSync() {\n destination.flushSync();\n closed = true;\n offError();\n },\n };\n return destination;\n}\n\nexport function createNodeFileDestination(options: NodeFileDestinationOptions): NodeDestination {\n const flags = options.flags ?? (options.append === false ? \"w\" : \"a\");\n if (options.mkdir) mkdirSync(dirname(options.path), { recursive: true });\n\n let fd: number | undefined;\n const getFd = () => {\n fd ??= openSync(options.path, flags);\n return fd;\n };\n const syncWrite = (payload: string | Uint8Array) => {\n if (typeof payload === \"string\") writeSync(getFd(), payload);\n else writeSync(getFd(), payload);\n };\n\n if (options.sync) {\n let closed = false;\n const releaseSync = () => {\n if (fd !== undefined) {\n closeSync(fd);\n fd = undefined;\n }\n };\n return {\n write(payload) {\n if (closed) return;\n syncWrite(payload);\n },\n flush() {\n return Promise.resolve();\n },\n flushSync() {},\n close() {\n releaseSync();\n closed = true;\n return Promise.resolve();\n },\n closeSync() {\n releaseSync();\n closed = true;\n },\n releaseSync,\n };\n }\n\n const stream = createWriteStream(options.path, { flags });\n const destination = createNodeStreamDestination({\n name: options.name,\n stream,\n minLength: options.minLength,\n syncWrite,\n });\n const releaseSync = () => {\n if (fd !== undefined) {\n closeSync(fd);\n fd = undefined;\n }\n };\n return {\n ...destination,\n stream,\n close() {\n return destination.close().finally(releaseSync);\n },\n closeSync() {\n destination.closeSync();\n releaseSync();\n },\n releaseSync,\n };\n}\n","import { existsSync, renameSync, statSync, unlinkSync } from \"fs\";\nimport {\n ndjsonCodec,\n toLevelValue,\n type Codec,\n type LogEvent,\n type LoggerLevel,\n type Transport,\n} from \"@loggerjs/core\";\nimport { createNodeFileDestination } from \"./node-destination\";\n\nexport interface RotatingFileTransportOptions {\n path: string;\n name?: string;\n codec?: Codec<string | Uint8Array>;\n minLevel?: LoggerLevel;\n flags?: string;\n append?: boolean;\n mkdir?: boolean;\n maxBytes?: number;\n maxFiles?: number;\n archivePath?: (path: string, index: number) => string;\n}\n\nexport interface RotatingFileTransport extends Transport {\n rotate: () => void;\n flushSync: () => void;\n currentBytes: () => number;\n}\n\nconst textEncoder = new TextEncoder();\n\nfunction payloadBytes(payload: string | Uint8Array): number {\n return typeof payload === \"string\" ? textEncoder.encode(payload).byteLength : payload.byteLength;\n}\n\nfunction normalizePositiveInteger(value: number | undefined, fallback: number): number {\n if (value === undefined || !Number.isFinite(value) || value <= 0) return fallback;\n return Math.floor(value);\n}\n\nfunction normalizeNonNegativeInteger(value: number | undefined, fallback: number): number {\n if (value === undefined || !Number.isFinite(value) || value < 0) return fallback;\n return Math.floor(value);\n}\n\nfunction defaultArchivePath(path: string, index: number): string {\n return `${path}.${index}`;\n}\n\nfunction fileSize(path: string): number {\n try {\n return statSync(path).size;\n } catch {\n return 0;\n }\n}\n\nexport function rotatingFileTransport(\n options: RotatingFileTransportOptions,\n): RotatingFileTransport {\n const codec = options.codec ?? ndjsonCodec();\n const maxBytes = normalizePositiveInteger(options.maxBytes, 10 * 1024 * 1024);\n const maxFiles = normalizeNonNegativeInteger(options.maxFiles, 5);\n const archivePath = options.archivePath ?? defaultArchivePath;\n const destination = createNodeFileDestination({\n name: options.name ?? \"rotating-file\",\n path: options.path,\n flags: options.flags,\n append: options.append,\n mkdir: options.mkdir,\n sync: true,\n });\n let bytes = fileSize(options.path);\n\n const rotate = () => {\n destination.releaseSync?.();\n\n if (maxFiles === 0) {\n if (existsSync(options.path)) unlinkSync(options.path);\n bytes = 0;\n return;\n }\n\n const oldest = archivePath(options.path, maxFiles);\n if (existsSync(oldest)) unlinkSync(oldest);\n\n for (let index = maxFiles - 1; index >= 1; index -= 1) {\n const source = archivePath(options.path, index);\n if (existsSync(source)) renameSync(source, archivePath(options.path, index + 1));\n }\n\n if (existsSync(options.path)) renameSync(options.path, archivePath(options.path, 1));\n bytes = 0;\n };\n\n const writePayload = (payload: string | Uint8Array) => {\n const size = payloadBytes(payload);\n if (bytes > 0 && bytes + size > maxBytes) rotate();\n destination.write(payload);\n bytes += size;\n };\n\n const transport: RotatingFileTransport = {\n name: options.name ?? \"rotating-file\",\n minLevel: options.minLevel,\n log(event: LogEvent) {\n if (options.minLevel !== undefined && event.level < toLevelValue(options.minLevel)) return;\n writePayload(codec.encode(event));\n },\n logBatch(events: LogEvent[]) {\n for (const event of events) {\n if (options.minLevel !== undefined && event.level < toLevelValue(options.minLevel))\n continue;\n writePayload(codec.encode(event));\n }\n },\n flush() {\n return destination.flush();\n },\n flushSync: destination.flushSync,\n close() {\n return destination.close();\n },\n rotate,\n currentBytes: () => bytes,\n };\n\n return transport;\n}\n"],"mappings":";;;;;AAuCA,MAAM,UAAU,IAAI,YAAY;AAEhC,MAAM,kBAAkB,UACtB,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,OAAO,KAAK,CAAC;AAE1D,SAAS,WAAW,SAAsC;CACxD,OAAO,OAAO,YAAY,WAAW,QAAQ,OAAO,OAAO,CAAC,CAAC,aAAa,QAAQ;AACpF;AAEA,SAAS,iBAAiB,UAA2D;CACnF,IAAI,SAAS,OAAO,YAAY,OAAO,YAAY,QAAQ,GACzD,OAAO,SAAS,KAAK,EAAE;CAEzB,MAAM,UAAU,SAAS,KAAK,YAC5B,OAAO,YAAY,WAAW,OAAO,KAAK,OAAO,IAAI,OAAO,KAAK,OAAO,CAC1E;CACA,OAAO,OAAO,OAAO,OAAO;AAC9B;AAEA,SAAS,QAAQ,OAAyB;CACxC,OACE,QAAQ,KAAK,KAAK,OAAO,UAAU,YAAa,MAA6B,SAAS;AAE1F;AAEA,SAAS,mBAAmB,OAAmC;CAC7D,IAAI,UAAU,KAAA,KAAa,CAAC,OAAO,SAAS,KAAK,KAAK,SAAS,GAAG,OAAO;CACzE,OAAO,KAAK,MAAM,KAAK;AACzB;AAEA,SAAgB,4BACd,SACiB;CACjB,MAAM,YAAY,mBAAmB,QAAQ,SAAS;CACtD,MAAM,cAAc,QAAQ,eAAe;CAC3C,MAAM,UAAyB,CAAC;CAChC,MAAM,SAAqC,CAAC;CAC5C,MAAM,kBAA8C,CAAC;CACrD,IAAI,gBAAgB;CACpB,IAAI,gBAAgB;CACpB,IAAI,gBAAgB;CACpB,IAAI;CACJ,IAAI;CACJ,IAAI,SAAS;CAEb,MAAM,uBAAuB,OAAgB,cAAsB;EACjE,IAAI,eAAe,QAAQ,KAAK,GAAG;EACnC,aAAa,oBAAoB,OAAO;GACtC,OAAO;GACP,WAAW,QAAQ;GACnB;EACF,CAAC;CACH;CAEA,MAAM,4BAA4B;EAChC,IAAI,gBAAgB,gBAAgB,GAAG;EACvC,IAAI,QAAQ,WAAW,GAAG;EAC1B,MAAM,QAAQ;EACd,YAAY,KAAA;EACZ,KAAK,MAAM,UAAU,QAAQ,OAAO,CAAC,GACnC,IAAI,OAAO,OAAO,OAAO,KAAK;OACzB,OAAO,QAAQ;CAExB;CAEA,MAAM,eAAe,OAAgB,cAAsB;EACzD,IAAI,eAAe,QAAQ,KAAK,GAAG;GACjC,SAAS;GACT;EACF;EACA,YAAY,eAAe,KAAK;EAChC,oBAAoB,WAAW,SAAS;CAC1C;CAEA,MAAM,iBAAiB,UAAiB;EACtC,YAAY,OAAO,cAAc;EACjC,oBAAoB;CACtB;CACA,MAAM,iBAAiB,QAAQ,OAAO,MAAM,SAAS,aAAa;CAClE,QAAQ,OAAO,KAAK,SAAS,aAAa;CAE1C,MAAM,qBAAqB;EACzB,IAAI,CAAC,QAAQ,OAAO,MAAM;EAC1B,iBAAiB;EACjB,QAAQ,OAAO,KAAK,eAAe;GACjC,iBAAiB;GACjB,oBAAoB;EACtB,CAAC;CACH;CAEA,MAAM,iBAAiB,YAAiC;EACtD,MAAM,QAAQ,gBAAgB,QAAQ,OAAO;EAC7C,IAAI,SAAS,GAAG,gBAAgB,OAAO,OAAO,CAAC;CACjD;CAEA,MAAM,YAAY,YAAiC;EACjD,IAAI,QAAQ;EACZ,gBAAgB,KAAK,OAAO;EAC5B,iBAAiB;EACjB,IAAI;GAOF,IANe,QAAQ,OAAO,MAAM,UAAU,UAAyB;IACrE,cAAc,OAAO;IACrB,iBAAiB;IACjB,IAAI,OAAO,YAAY,OAAO,QAAQ,mBAAmB,OAAO;IAChE,oBAAoB;GACtB,CACS,MAAM,OAAO,aAAa;EACrC,SAAS,OAAO;GACd,cAAc,OAAO;GACrB,iBAAiB;GACjB,YAAY,OAAO,QAAQ,mBAAmB,OAAO;GACrD,oBAAoB;EACtB;CACF;CAEA,MAAM,sBAAsB;EAC1B,IAAI,OAAO,WAAW,GAAG;EACzB,MAAM,UAAU,iBAAiB,OAAO,OAAO,CAAC,CAAC;EACjD,gBAAgB;EAChB,SAAS,OAAO;CAClB;CAEA,MAAM,cAA+B;EACnC,MAAM,SAAS,SAAS;GACtB,IAAI,QAAQ;GACZ,cAAc;GACd,IAAI,YAAY,GAAG;IACjB,OAAO,KAAK,OAAO;IACnB,iBAAiB,WAAW,OAAO;IACnC,IAAI,iBAAiB,WAAW,cAAc;IAC9C;GACF;GACA,SAAS,OAAO;EAClB;EACA,QAAQ;GACN,cAAc;GACd,IAAI,gBAAgB,kBAAkB,GAAG;IACvC,MAAM,QAAQ;IACd,YAAY,KAAA;IACZ,IAAI,OAAO,OAAO,QAAQ,OAAO,KAAK;IACtC,OAAO,QAAQ,QAAQ;GACzB;GACA,OAAO,IAAI,SAAe,SAAS,WAAW;IAC5C,QAAQ,KAAK;KAAE;KAAS;IAAO,CAAC;GAClC,CAAC;EACH;EACA,YAAY;GACV,IAAI,CAAC,QAAQ,WAAW;IACtB,cAAc;IACd;GACF;GACA,KAAK,MAAM,WAAW,OAAO,OAAO,CAAC,GAAG,QAAQ,UAAU,OAAO;GACjE,gBAAgB;GAChB,KAAK,MAAM,WAAW,gBAAgB,OAAO,CAAC,GAAG,QAAQ,UAAU,OAAO;EAC5E;EACA,QAAQ;GACN,OAAO,YAAY,MAAM,CAAC,CAAC,WAEvB,IAAI,SAAe,SAAS,WAAW;IACrC,IAAI,CAAC,QAAQ,OAAO,KAAK;KACvB,SAAS;KACT,SAAS;KACT,QAAQ;KACR;IACF;IACA,QAAQ,OAAO,KAAK,UAAyB;KAC3C,SAAS;KACT,SAAS;KACT,IAAI,SAAS,EAAE,eAAe,QAAQ,KAAK,IAAI,OAAO,KAAK;UACtD,QAAQ;IACf,CAAC;GACH,CAAC,IACF,UAAmB;IAClB,SAAS;IACT,OAAO,QAAQ,OAAO,KAAK;GAC7B,CACF;EACF;EACA,YAAY;GACV,YAAY,UAAU;GACtB,SAAS;GACT,SAAS;EACX;CACF;CACA,OAAO;AACT;AAEA,SAAgB,0BAA0B,SAAsD;CAC9F,MAAM,QAAQ,QAAQ,UAAU,QAAQ,WAAW,QAAQ,MAAM;CACjE,IAAI,QAAQ,OAAO,CAAA,GAAA,GAAA,UAAA,EAAA,GAAA,KAAA,QAAA,CAAkB,QAAQ,IAAI,GAAG,EAAE,WAAW,KAAK,CAAC;CAEvE,IAAI;CACJ,MAAM,cAAc;EAClB,QAAA,GAAA,GAAA,SAAA,CAAgB,QAAQ,MAAM,KAAK;EACnC,OAAO;CACT;CACA,MAAM,aAAa,YAAiC;EAClD,IAAI,OAAO,YAAY,UAAU,CAAA,GAAA,GAAA,UAAA,CAAU,MAAM,GAAG,OAAO;OACtD,CAAA,GAAA,GAAA,UAAA,CAAU,MAAM,GAAG,OAAO;CACjC;CAEA,IAAI,QAAQ,MAAM;EAChB,IAAI,SAAS;EACb,MAAM,oBAAoB;GACxB,IAAI,OAAO,KAAA,GAAW;IACpB,CAAA,GAAA,GAAA,UAAA,CAAU,EAAE;IACZ,KAAK,KAAA;GACP;EACF;EACA,OAAO;GACL,MAAM,SAAS;IACb,IAAI,QAAQ;IACZ,UAAU,OAAO;GACnB;GACA,QAAQ;IACN,OAAO,QAAQ,QAAQ;GACzB;GACA,YAAY,CAAC;GACb,QAAQ;IACN,YAAY;IACZ,SAAS;IACT,OAAO,QAAQ,QAAQ;GACzB;GACA,YAAY;IACV,YAAY;IACZ,SAAS;GACX;GACA;EACF;CACF;CAEA,MAAM,UAAA,GAAA,GAAA,kBAAA,CAA2B,QAAQ,MAAM,EAAE,MAAM,CAAC;CACxD,MAAM,cAAc,4BAA4B;EAC9C,MAAM,QAAQ;EACd;EACA,WAAW,QAAQ;EACnB;CACF,CAAC;CACD,MAAM,oBAAoB;EACxB,IAAI,OAAO,KAAA,GAAW;GACpB,CAAA,GAAA,GAAA,UAAA,CAAU,EAAE;GACZ,KAAK,KAAA;EACP;CACF;CACA,OAAO;EACL,GAAG;EACH;EACA,QAAQ;GACN,OAAO,YAAY,MAAM,CAAC,CAAC,QAAQ,WAAW;EAChD;EACA,YAAY;GACV,YAAY,UAAU;GACtB,YAAY;EACd;EACA;CACF;AACF;;;ACzQA,MAAM,cAAc,IAAI,YAAY;AAEpC,SAAS,aAAa,SAAsC;CAC1D,OAAO,OAAO,YAAY,WAAW,YAAY,OAAO,OAAO,CAAC,CAAC,aAAa,QAAQ;AACxF;AAEA,SAAS,yBAAyB,OAA2B,UAA0B;CACrF,IAAI,UAAU,KAAA,KAAa,CAAC,OAAO,SAAS,KAAK,KAAK,SAAS,GAAG,OAAO;CACzE,OAAO,KAAK,MAAM,KAAK;AACzB;AAEA,SAAS,4BAA4B,OAA2B,UAA0B;CACxF,IAAI,UAAU,KAAA,KAAa,CAAC,OAAO,SAAS,KAAK,KAAK,QAAQ,GAAG,OAAO;CACxE,OAAO,KAAK,MAAM,KAAK;AACzB;AAEA,SAAS,mBAAmB,MAAc,OAAuB;CAC/D,OAAO,GAAG,KAAK,GAAG;AACpB;AAEA,SAAS,SAAS,MAAsB;CACtC,IAAI;EACF,QAAA,GAAA,GAAA,SAAA,CAAgB,IAAI,CAAC,CAAC;CACxB,QAAQ;EACN,OAAO;CACT;AACF;AAEA,SAAgB,sBACd,SACuB;CACvB,MAAM,QAAQ,QAAQ,UAAA,GAAA,eAAA,YAAA,CAAqB;CAC3C,MAAM,WAAW,yBAAyB,QAAQ,UAAU,KAAK,OAAO,IAAI;CAC5E,MAAM,WAAW,4BAA4B,QAAQ,UAAU,CAAC;CAChE,MAAM,cAAc,QAAQ,eAAe;CAC3C,MAAM,cAAc,0BAA0B;EAC5C,MAAM,QAAQ,QAAQ;EACtB,MAAM,QAAQ;EACd,OAAO,QAAQ;EACf,QAAQ,QAAQ;EAChB,OAAO,QAAQ;EACf,MAAM;CACR,CAAC;CACD,IAAI,QAAQ,SAAS,QAAQ,IAAI;CAEjC,MAAM,eAAe;EACnB,YAAY,cAAc;EAE1B,IAAI,aAAa,GAAG;GAClB,KAAA,GAAA,GAAA,WAAA,CAAe,QAAQ,IAAI,GAAG,CAAA,GAAA,GAAA,WAAA,CAAW,QAAQ,IAAI;GACrD,QAAQ;GACR;EACF;EAEA,MAAM,SAAS,YAAY,QAAQ,MAAM,QAAQ;EACjD,KAAA,GAAA,GAAA,WAAA,CAAe,MAAM,GAAG,CAAA,GAAA,GAAA,WAAA,CAAW,MAAM;EAEzC,KAAK,IAAI,QAAQ,WAAW,GAAG,SAAS,GAAG,SAAS,GAAG;GACrD,MAAM,SAAS,YAAY,QAAQ,MAAM,KAAK;GAC9C,KAAA,GAAA,GAAA,WAAA,CAAe,MAAM,GAAG,CAAA,GAAA,GAAA,WAAA,CAAW,QAAQ,YAAY,QAAQ,MAAM,QAAQ,CAAC,CAAC;EACjF;EAEA,KAAA,GAAA,GAAA,WAAA,CAAe,QAAQ,IAAI,GAAG,CAAA,GAAA,GAAA,WAAA,CAAW,QAAQ,MAAM,YAAY,QAAQ,MAAM,CAAC,CAAC;EACnF,QAAQ;CACV;CAEA,MAAM,gBAAgB,YAAiC;EACrD,MAAM,OAAO,aAAa,OAAO;EACjC,IAAI,QAAQ,KAAK,QAAQ,OAAO,UAAU,OAAO;EACjD,YAAY,MAAM,OAAO;EACzB,SAAS;CACX;CA2BA,OAAO;EAxBL,MAAM,QAAQ,QAAQ;EACtB,UAAU,QAAQ;EAClB,IAAI,OAAiB;GACnB,IAAI,QAAQ,aAAa,KAAA,KAAa,MAAM,SAAA,GAAA,eAAA,aAAA,CAAqB,QAAQ,QAAQ,GAAG;GACpF,aAAa,MAAM,OAAO,KAAK,CAAC;EAClC;EACA,SAAS,QAAoB;GAC3B,KAAK,MAAM,SAAS,QAAQ;IAC1B,IAAI,QAAQ,aAAa,KAAA,KAAa,MAAM,SAAA,GAAA,eAAA,aAAA,CAAqB,QAAQ,QAAQ,GAC/E;IACF,aAAa,MAAM,OAAO,KAAK,CAAC;GAClC;EACF;EACA,QAAQ;GACN,OAAO,YAAY,MAAM;EAC3B;EACA,WAAW,YAAY;EACvB,QAAQ;GACN,OAAO,YAAY,MAAM;EAC3B;EACA;EACA,oBAAoB;CAGP;AACjB"}
@@ -0,0 +1,317 @@
1
+ import { closeSync, createWriteStream, existsSync, mkdirSync, openSync, renameSync, statSync, unlinkSync, writeSync } from "fs";
2
+ import { ndjsonCodec, toLevelValue } from "@loggerjs/core";
3
+ import { dirname } from "path";
4
+ //#region src/node-destination.ts
5
+ const encoder = new TextEncoder();
6
+ const normalizeError = (error) => error instanceof Error ? error : new Error(String(error));
7
+ function byteLength(payload) {
8
+ return typeof payload === "string" ? encoder.encode(payload).byteLength : payload.byteLength;
9
+ }
10
+ function coalescePayloads(payloads) {
11
+ if (payloads.every((payload) => typeof payload === "string")) return payloads.join("");
12
+ const buffers = payloads.map((payload) => typeof payload === "string" ? Buffer.from(payload) : Buffer.from(payload));
13
+ return Buffer.concat(buffers);
14
+ }
15
+ function isEpipe(error) {
16
+ return Boolean(error) && typeof error === "object" && error.code === "EPIPE";
17
+ }
18
+ function normalizeMinLength(value) {
19
+ if (value === void 0 || !Number.isFinite(value) || value <= 0) return 0;
20
+ return Math.floor(value);
21
+ }
22
+ function createNodeStreamDestination(options) {
23
+ const minLength = normalizeMinLength(options.minLength);
24
+ const ignoreEpipe = options.ignoreEpipe ?? false;
25
+ const waiters = [];
26
+ const buffer = [];
27
+ const pendingPayloads = [];
28
+ let bufferedBytes = 0;
29
+ let pendingWrites = 0;
30
+ let pendingDrains = 0;
31
+ let lastError;
32
+ let lastContext;
33
+ let closed = false;
34
+ const reportInternalError = (error, operation) => {
35
+ if (ignoreEpipe && isEpipe(error)) return;
36
+ lastContext?.reportInternalError(error, {
37
+ phase: "transport",
38
+ transport: options.name,
39
+ operation
40
+ });
41
+ };
42
+ const settleWaitersIfIdle = () => {
43
+ if (pendingWrites + pendingDrains > 0) return;
44
+ if (waiters.length === 0) return;
45
+ const error = lastError;
46
+ lastError = void 0;
47
+ for (const waiter of waiters.splice(0)) if (error) waiter.reject(error);
48
+ else waiter.resolve();
49
+ };
50
+ const recordError = (error, operation) => {
51
+ if (ignoreEpipe && isEpipe(error)) {
52
+ closed = true;
53
+ return;
54
+ }
55
+ lastError = normalizeError(error);
56
+ reportInternalError(lastError, operation);
57
+ };
58
+ const onStreamError = (error) => {
59
+ recordError(error, "stream-error");
60
+ settleWaitersIfIdle();
61
+ };
62
+ const offError = () => options.stream.off?.("error", onStreamError);
63
+ options.stream.on?.("error", onStreamError);
64
+ const waitForDrain = () => {
65
+ if (!options.stream.once) return;
66
+ pendingDrains += 1;
67
+ options.stream.once("drain", () => {
68
+ pendingDrains -= 1;
69
+ settleWaitersIfIdle();
70
+ });
71
+ };
72
+ const removePending = (payload) => {
73
+ const index = pendingPayloads.indexOf(payload);
74
+ if (index >= 0) pendingPayloads.splice(index, 1);
75
+ };
76
+ const writeNow = (payload) => {
77
+ if (closed) return;
78
+ pendingPayloads.push(payload);
79
+ pendingWrites += 1;
80
+ try {
81
+ if (options.stream.write(payload, (error) => {
82
+ removePending(payload);
83
+ pendingWrites -= 1;
84
+ if (error) recordError(error, options.reportOperation ?? "write");
85
+ settleWaitersIfIdle();
86
+ }) === false) waitForDrain();
87
+ } catch (error) {
88
+ removePending(payload);
89
+ pendingWrites -= 1;
90
+ recordError(error, options.reportOperation ?? "write");
91
+ settleWaitersIfIdle();
92
+ }
93
+ };
94
+ const flushBuffered = () => {
95
+ if (buffer.length === 0) return;
96
+ const payload = coalescePayloads(buffer.splice(0));
97
+ bufferedBytes = 0;
98
+ writeNow(payload);
99
+ };
100
+ const destination = {
101
+ write(payload, context) {
102
+ if (closed) return;
103
+ lastContext = context;
104
+ if (minLength > 0) {
105
+ buffer.push(payload);
106
+ bufferedBytes += byteLength(payload);
107
+ if (bufferedBytes >= minLength) flushBuffered();
108
+ return;
109
+ }
110
+ writeNow(payload);
111
+ },
112
+ flush() {
113
+ flushBuffered();
114
+ if (pendingWrites + pendingDrains === 0) {
115
+ const error = lastError;
116
+ lastError = void 0;
117
+ if (error) return Promise.reject(error);
118
+ return Promise.resolve();
119
+ }
120
+ return new Promise((resolve, reject) => {
121
+ waiters.push({
122
+ resolve,
123
+ reject
124
+ });
125
+ });
126
+ },
127
+ flushSync() {
128
+ if (!options.syncWrite) {
129
+ flushBuffered();
130
+ return;
131
+ }
132
+ for (const payload of buffer.splice(0)) options.syncWrite(payload);
133
+ bufferedBytes = 0;
134
+ for (const payload of pendingPayloads.splice(0)) options.syncWrite(payload);
135
+ },
136
+ close() {
137
+ return destination.flush().then(() => new Promise((resolve, reject) => {
138
+ if (!options.stream.end) {
139
+ closed = true;
140
+ offError();
141
+ resolve();
142
+ return;
143
+ }
144
+ options.stream.end((error) => {
145
+ closed = true;
146
+ offError();
147
+ if (error && !(ignoreEpipe && isEpipe(error))) reject(error);
148
+ else resolve();
149
+ });
150
+ }), (error) => {
151
+ offError();
152
+ return Promise.reject(error);
153
+ });
154
+ },
155
+ closeSync() {
156
+ destination.flushSync();
157
+ closed = true;
158
+ offError();
159
+ }
160
+ };
161
+ return destination;
162
+ }
163
+ function createNodeFileDestination(options) {
164
+ const flags = options.flags ?? (options.append === false ? "w" : "a");
165
+ if (options.mkdir) mkdirSync(dirname(options.path), { recursive: true });
166
+ let fd;
167
+ const getFd = () => {
168
+ fd ??= openSync(options.path, flags);
169
+ return fd;
170
+ };
171
+ const syncWrite = (payload) => {
172
+ if (typeof payload === "string") writeSync(getFd(), payload);
173
+ else writeSync(getFd(), payload);
174
+ };
175
+ if (options.sync) {
176
+ let closed = false;
177
+ const releaseSync = () => {
178
+ if (fd !== void 0) {
179
+ closeSync(fd);
180
+ fd = void 0;
181
+ }
182
+ };
183
+ return {
184
+ write(payload) {
185
+ if (closed) return;
186
+ syncWrite(payload);
187
+ },
188
+ flush() {
189
+ return Promise.resolve();
190
+ },
191
+ flushSync() {},
192
+ close() {
193
+ releaseSync();
194
+ closed = true;
195
+ return Promise.resolve();
196
+ },
197
+ closeSync() {
198
+ releaseSync();
199
+ closed = true;
200
+ },
201
+ releaseSync
202
+ };
203
+ }
204
+ const stream = createWriteStream(options.path, { flags });
205
+ const destination = createNodeStreamDestination({
206
+ name: options.name,
207
+ stream,
208
+ minLength: options.minLength,
209
+ syncWrite
210
+ });
211
+ const releaseSync = () => {
212
+ if (fd !== void 0) {
213
+ closeSync(fd);
214
+ fd = void 0;
215
+ }
216
+ };
217
+ return {
218
+ ...destination,
219
+ stream,
220
+ close() {
221
+ return destination.close().finally(releaseSync);
222
+ },
223
+ closeSync() {
224
+ destination.closeSync();
225
+ releaseSync();
226
+ },
227
+ releaseSync
228
+ };
229
+ }
230
+ //#endregion
231
+ //#region src/rotating-file-transport.ts
232
+ const textEncoder = new TextEncoder();
233
+ function payloadBytes(payload) {
234
+ return typeof payload === "string" ? textEncoder.encode(payload).byteLength : payload.byteLength;
235
+ }
236
+ function normalizePositiveInteger(value, fallback) {
237
+ if (value === void 0 || !Number.isFinite(value) || value <= 0) return fallback;
238
+ return Math.floor(value);
239
+ }
240
+ function normalizeNonNegativeInteger(value, fallback) {
241
+ if (value === void 0 || !Number.isFinite(value) || value < 0) return fallback;
242
+ return Math.floor(value);
243
+ }
244
+ function defaultArchivePath(path, index) {
245
+ return `${path}.${index}`;
246
+ }
247
+ function fileSize(path) {
248
+ try {
249
+ return statSync(path).size;
250
+ } catch {
251
+ return 0;
252
+ }
253
+ }
254
+ function rotatingFileTransport(options) {
255
+ const codec = options.codec ?? ndjsonCodec();
256
+ const maxBytes = normalizePositiveInteger(options.maxBytes, 10 * 1024 * 1024);
257
+ const maxFiles = normalizeNonNegativeInteger(options.maxFiles, 5);
258
+ const archivePath = options.archivePath ?? defaultArchivePath;
259
+ const destination = createNodeFileDestination({
260
+ name: options.name ?? "rotating-file",
261
+ path: options.path,
262
+ flags: options.flags,
263
+ append: options.append,
264
+ mkdir: options.mkdir,
265
+ sync: true
266
+ });
267
+ let bytes = fileSize(options.path);
268
+ const rotate = () => {
269
+ destination.releaseSync?.();
270
+ if (maxFiles === 0) {
271
+ if (existsSync(options.path)) unlinkSync(options.path);
272
+ bytes = 0;
273
+ return;
274
+ }
275
+ const oldest = archivePath(options.path, maxFiles);
276
+ if (existsSync(oldest)) unlinkSync(oldest);
277
+ for (let index = maxFiles - 1; index >= 1; index -= 1) {
278
+ const source = archivePath(options.path, index);
279
+ if (existsSync(source)) renameSync(source, archivePath(options.path, index + 1));
280
+ }
281
+ if (existsSync(options.path)) renameSync(options.path, archivePath(options.path, 1));
282
+ bytes = 0;
283
+ };
284
+ const writePayload = (payload) => {
285
+ const size = payloadBytes(payload);
286
+ if (bytes > 0 && bytes + size > maxBytes) rotate();
287
+ destination.write(payload);
288
+ bytes += size;
289
+ };
290
+ return {
291
+ name: options.name ?? "rotating-file",
292
+ minLevel: options.minLevel,
293
+ log(event) {
294
+ if (options.minLevel !== void 0 && event.level < toLevelValue(options.minLevel)) return;
295
+ writePayload(codec.encode(event));
296
+ },
297
+ logBatch(events) {
298
+ for (const event of events) {
299
+ if (options.minLevel !== void 0 && event.level < toLevelValue(options.minLevel)) continue;
300
+ writePayload(codec.encode(event));
301
+ }
302
+ },
303
+ flush() {
304
+ return destination.flush();
305
+ },
306
+ flushSync: destination.flushSync,
307
+ close() {
308
+ return destination.close();
309
+ },
310
+ rotate,
311
+ currentBytes: () => bytes
312
+ };
313
+ }
314
+ //#endregion
315
+ export { rotatingFileTransport };
316
+
317
+ //# sourceMappingURL=rotating-file-transport.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rotating-file-transport.js","names":[],"sources":["../src/node-destination.ts","../src/rotating-file-transport.ts"],"sourcesContent":["import { closeSync, createWriteStream, mkdirSync, openSync, writeSync, type WriteStream } from \"fs\";\nimport { dirname } from \"path\";\nimport type { TransportContext } from \"@loggerjs/core\";\nimport type { WritableLike } from \"./internal-types\";\n\nexport interface NodeDestination {\n stream?: WriteStream;\n write: (payload: string | Uint8Array, context?: TransportContext) => void;\n flush: () => Promise<void>;\n flushSync: () => void;\n close: () => Promise<void>;\n closeSync: () => void;\n releaseSync?: () => void;\n}\n\nexport interface NodeStreamDestinationOptions {\n name: string;\n stream: WritableLike;\n minLength?: number;\n ignoreEpipe?: boolean;\n reportOperation?: string;\n syncWrite?: (payload: string | Uint8Array) => void;\n}\n\nexport interface NodeFileDestinationOptions {\n name: string;\n path: string;\n flags?: string;\n append?: boolean;\n mkdir?: boolean;\n sync?: boolean;\n minLength?: number;\n}\n\ninterface FlushWaiter {\n resolve: () => void;\n reject: (error: Error) => void;\n}\n\nconst encoder = new TextEncoder();\n\nconst normalizeError = (error: unknown): Error =>\n error instanceof Error ? error : new Error(String(error));\n\nfunction byteLength(payload: string | Uint8Array): number {\n return typeof payload === \"string\" ? encoder.encode(payload).byteLength : payload.byteLength;\n}\n\nfunction coalescePayloads(payloads: Array<string | Uint8Array>): string | Uint8Array {\n if (payloads.every((payload) => typeof payload === \"string\")) {\n return payloads.join(\"\");\n }\n const buffers = payloads.map((payload) =>\n typeof payload === \"string\" ? Buffer.from(payload) : Buffer.from(payload),\n );\n return Buffer.concat(buffers);\n}\n\nfunction isEpipe(error: unknown): boolean {\n return (\n Boolean(error) && typeof error === \"object\" && (error as { code?: unknown }).code === \"EPIPE\"\n );\n}\n\nfunction normalizeMinLength(value: number | undefined): number {\n if (value === undefined || !Number.isFinite(value) || value <= 0) return 0;\n return Math.floor(value);\n}\n\nexport function createNodeStreamDestination(\n options: NodeStreamDestinationOptions,\n): NodeDestination {\n const minLength = normalizeMinLength(options.minLength);\n const ignoreEpipe = options.ignoreEpipe ?? false;\n const waiters: FlushWaiter[] = [];\n const buffer: Array<string | Uint8Array> = [];\n const pendingPayloads: Array<string | Uint8Array> = [];\n let bufferedBytes = 0;\n let pendingWrites = 0;\n let pendingDrains = 0;\n let lastError: Error | undefined;\n let lastContext: TransportContext | undefined;\n let closed = false;\n\n const reportInternalError = (error: unknown, operation: string) => {\n if (ignoreEpipe && isEpipe(error)) return;\n lastContext?.reportInternalError(error, {\n phase: \"transport\",\n transport: options.name,\n operation,\n });\n };\n\n const settleWaitersIfIdle = () => {\n if (pendingWrites + pendingDrains > 0) return;\n if (waiters.length === 0) return;\n const error = lastError;\n lastError = undefined;\n for (const waiter of waiters.splice(0)) {\n if (error) waiter.reject(error);\n else waiter.resolve();\n }\n };\n\n const recordError = (error: unknown, operation: string) => {\n if (ignoreEpipe && isEpipe(error)) {\n closed = true;\n return;\n }\n lastError = normalizeError(error);\n reportInternalError(lastError, operation);\n };\n\n const onStreamError = (error: Error) => {\n recordError(error, \"stream-error\");\n settleWaitersIfIdle();\n };\n const offError = () => options.stream.off?.(\"error\", onStreamError);\n options.stream.on?.(\"error\", onStreamError);\n\n const waitForDrain = () => {\n if (!options.stream.once) return;\n pendingDrains += 1;\n options.stream.once(\"drain\", () => {\n pendingDrains -= 1;\n settleWaitersIfIdle();\n });\n };\n\n const removePending = (payload: string | Uint8Array) => {\n const index = pendingPayloads.indexOf(payload);\n if (index >= 0) pendingPayloads.splice(index, 1);\n };\n\n const writeNow = (payload: string | Uint8Array) => {\n if (closed) return;\n pendingPayloads.push(payload);\n pendingWrites += 1;\n try {\n const result = options.stream.write(payload, (error?: Error | null) => {\n removePending(payload);\n pendingWrites -= 1;\n if (error) recordError(error, options.reportOperation ?? \"write\");\n settleWaitersIfIdle();\n });\n if (result === false) waitForDrain();\n } catch (error) {\n removePending(payload);\n pendingWrites -= 1;\n recordError(error, options.reportOperation ?? \"write\");\n settleWaitersIfIdle();\n }\n };\n\n const flushBuffered = () => {\n if (buffer.length === 0) return;\n const payload = coalescePayloads(buffer.splice(0));\n bufferedBytes = 0;\n writeNow(payload);\n };\n\n const destination: NodeDestination = {\n write(payload, context) {\n if (closed) return;\n lastContext = context;\n if (minLength > 0) {\n buffer.push(payload);\n bufferedBytes += byteLength(payload);\n if (bufferedBytes >= minLength) flushBuffered();\n return;\n }\n writeNow(payload);\n },\n flush() {\n flushBuffered();\n if (pendingWrites + pendingDrains === 0) {\n const error = lastError;\n lastError = undefined;\n if (error) return Promise.reject(error);\n return Promise.resolve();\n }\n return new Promise<void>((resolve, reject) => {\n waiters.push({ resolve, reject });\n });\n },\n flushSync() {\n if (!options.syncWrite) {\n flushBuffered();\n return;\n }\n for (const payload of buffer.splice(0)) options.syncWrite(payload);\n bufferedBytes = 0;\n for (const payload of pendingPayloads.splice(0)) options.syncWrite(payload);\n },\n close() {\n return destination.flush().then(\n () =>\n new Promise<void>((resolve, reject) => {\n if (!options.stream.end) {\n closed = true;\n offError();\n resolve();\n return;\n }\n options.stream.end((error?: Error | null) => {\n closed = true;\n offError();\n if (error && !(ignoreEpipe && isEpipe(error))) reject(error);\n else resolve();\n });\n }),\n (error: unknown) => {\n offError();\n return Promise.reject(error);\n },\n );\n },\n closeSync() {\n destination.flushSync();\n closed = true;\n offError();\n },\n };\n return destination;\n}\n\nexport function createNodeFileDestination(options: NodeFileDestinationOptions): NodeDestination {\n const flags = options.flags ?? (options.append === false ? \"w\" : \"a\");\n if (options.mkdir) mkdirSync(dirname(options.path), { recursive: true });\n\n let fd: number | undefined;\n const getFd = () => {\n fd ??= openSync(options.path, flags);\n return fd;\n };\n const syncWrite = (payload: string | Uint8Array) => {\n if (typeof payload === \"string\") writeSync(getFd(), payload);\n else writeSync(getFd(), payload);\n };\n\n if (options.sync) {\n let closed = false;\n const releaseSync = () => {\n if (fd !== undefined) {\n closeSync(fd);\n fd = undefined;\n }\n };\n return {\n write(payload) {\n if (closed) return;\n syncWrite(payload);\n },\n flush() {\n return Promise.resolve();\n },\n flushSync() {},\n close() {\n releaseSync();\n closed = true;\n return Promise.resolve();\n },\n closeSync() {\n releaseSync();\n closed = true;\n },\n releaseSync,\n };\n }\n\n const stream = createWriteStream(options.path, { flags });\n const destination = createNodeStreamDestination({\n name: options.name,\n stream,\n minLength: options.minLength,\n syncWrite,\n });\n const releaseSync = () => {\n if (fd !== undefined) {\n closeSync(fd);\n fd = undefined;\n }\n };\n return {\n ...destination,\n stream,\n close() {\n return destination.close().finally(releaseSync);\n },\n closeSync() {\n destination.closeSync();\n releaseSync();\n },\n releaseSync,\n };\n}\n","import { existsSync, renameSync, statSync, unlinkSync } from \"fs\";\nimport {\n ndjsonCodec,\n toLevelValue,\n type Codec,\n type LogEvent,\n type LoggerLevel,\n type Transport,\n} from \"@loggerjs/core\";\nimport { createNodeFileDestination } from \"./node-destination\";\n\nexport interface RotatingFileTransportOptions {\n path: string;\n name?: string;\n codec?: Codec<string | Uint8Array>;\n minLevel?: LoggerLevel;\n flags?: string;\n append?: boolean;\n mkdir?: boolean;\n maxBytes?: number;\n maxFiles?: number;\n archivePath?: (path: string, index: number) => string;\n}\n\nexport interface RotatingFileTransport extends Transport {\n rotate: () => void;\n flushSync: () => void;\n currentBytes: () => number;\n}\n\nconst textEncoder = new TextEncoder();\n\nfunction payloadBytes(payload: string | Uint8Array): number {\n return typeof payload === \"string\" ? textEncoder.encode(payload).byteLength : payload.byteLength;\n}\n\nfunction normalizePositiveInteger(value: number | undefined, fallback: number): number {\n if (value === undefined || !Number.isFinite(value) || value <= 0) return fallback;\n return Math.floor(value);\n}\n\nfunction normalizeNonNegativeInteger(value: number | undefined, fallback: number): number {\n if (value === undefined || !Number.isFinite(value) || value < 0) return fallback;\n return Math.floor(value);\n}\n\nfunction defaultArchivePath(path: string, index: number): string {\n return `${path}.${index}`;\n}\n\nfunction fileSize(path: string): number {\n try {\n return statSync(path).size;\n } catch {\n return 0;\n }\n}\n\nexport function rotatingFileTransport(\n options: RotatingFileTransportOptions,\n): RotatingFileTransport {\n const codec = options.codec ?? ndjsonCodec();\n const maxBytes = normalizePositiveInteger(options.maxBytes, 10 * 1024 * 1024);\n const maxFiles = normalizeNonNegativeInteger(options.maxFiles, 5);\n const archivePath = options.archivePath ?? defaultArchivePath;\n const destination = createNodeFileDestination({\n name: options.name ?? \"rotating-file\",\n path: options.path,\n flags: options.flags,\n append: options.append,\n mkdir: options.mkdir,\n sync: true,\n });\n let bytes = fileSize(options.path);\n\n const rotate = () => {\n destination.releaseSync?.();\n\n if (maxFiles === 0) {\n if (existsSync(options.path)) unlinkSync(options.path);\n bytes = 0;\n return;\n }\n\n const oldest = archivePath(options.path, maxFiles);\n if (existsSync(oldest)) unlinkSync(oldest);\n\n for (let index = maxFiles - 1; index >= 1; index -= 1) {\n const source = archivePath(options.path, index);\n if (existsSync(source)) renameSync(source, archivePath(options.path, index + 1));\n }\n\n if (existsSync(options.path)) renameSync(options.path, archivePath(options.path, 1));\n bytes = 0;\n };\n\n const writePayload = (payload: string | Uint8Array) => {\n const size = payloadBytes(payload);\n if (bytes > 0 && bytes + size > maxBytes) rotate();\n destination.write(payload);\n bytes += size;\n };\n\n const transport: RotatingFileTransport = {\n name: options.name ?? \"rotating-file\",\n minLevel: options.minLevel,\n log(event: LogEvent) {\n if (options.minLevel !== undefined && event.level < toLevelValue(options.minLevel)) return;\n writePayload(codec.encode(event));\n },\n logBatch(events: LogEvent[]) {\n for (const event of events) {\n if (options.minLevel !== undefined && event.level < toLevelValue(options.minLevel))\n continue;\n writePayload(codec.encode(event));\n }\n },\n flush() {\n return destination.flush();\n },\n flushSync: destination.flushSync,\n close() {\n return destination.close();\n },\n rotate,\n currentBytes: () => bytes,\n };\n\n return transport;\n}\n"],"mappings":"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"}
@@ -0,0 +1,104 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ let _loggerjs_core = require("@loggerjs/core");
3
+ //#region src/serverless-integration.ts
4
+ const defaultRandom = () => Math.random();
5
+ let coldStart = true;
6
+ function isPromiseLike(value) {
7
+ return typeof value === "object" && value !== null && typeof value.then === "function";
8
+ }
9
+ function defaultLevel(error) {
10
+ return error ? "error" : "info";
11
+ }
12
+ function defaultRequestId(event, context) {
13
+ const ctx = context;
14
+ const evt = event;
15
+ return ctx?.awsRequestId ?? evt?.requestContext?.requestId ?? evt?.headers?.["x-request-id"] ?? evt?.headers?.["X-Request-Id"];
16
+ }
17
+ function defaultOperation(event, context) {
18
+ const ctx = context;
19
+ const evt = event;
20
+ return evt?.routeKey ?? evt?.requestContext?.routeKey ?? (evt?.requestContext?.http?.method && evt.requestContext.http.path ? `${evt.requestContext.http.method} ${evt.requestContext.http.path}` : void 0) ?? (evt?.httpMethod && (evt.rawPath ?? evt.path) ? `${evt.httpMethod} ${evt.rawPath ?? evt.path}` : void 0) ?? ctx?.functionName;
21
+ }
22
+ function normalizeUnknown(value) {
23
+ return (0, _loggerjs_core.normalizeValue)(value, {
24
+ maxDepth: 5,
25
+ maxObjectKeys: 120
26
+ });
27
+ }
28
+ function serverlessIntegration(logger, handler, options = {}) {
29
+ const name = options.name ?? "serverless";
30
+ const platform = options.platform ?? "serverless";
31
+ const captureSuccessful = options.captureSuccessful ?? options.captureAll ?? true;
32
+ const sampleRate = options.sampleRate ?? 1;
33
+ const random = options.random ?? defaultRandom;
34
+ const bindContext = options.bindContext ?? true;
35
+ const levelFor = options.level ?? defaultLevel;
36
+ return (event, context, callback) => {
37
+ const started = Date.now();
38
+ const currentColdStart = coldStart;
39
+ coldStart = false;
40
+ const requestId = options.getRequestId?.(event, context) ?? defaultRequestId(event, context);
41
+ const operation = options.getOperation?.(event, context) ?? defaultOperation(event, context);
42
+ let captured = false;
43
+ const shouldCapture = (error) => {
44
+ if (error) return true;
45
+ if (!captureSuccessful) return false;
46
+ return sampleRate >= 1 || random() < sampleRate;
47
+ };
48
+ const capture = (error, result) => {
49
+ if (captured || !shouldCapture(error)) return;
50
+ captured = true;
51
+ const durationMs = Date.now() - started;
52
+ const info = {
53
+ context,
54
+ event,
55
+ operation,
56
+ requestId
57
+ };
58
+ logger.log(levelFor(error, durationMs, info), `Serverless ${operation ?? name}`, {
59
+ error,
60
+ serverless: {
61
+ kind: name,
62
+ platform,
63
+ operation,
64
+ requestId,
65
+ coldStart: currentColdStart,
66
+ durationMs,
67
+ event: options.captureEvent ? options.normalizeEvent?.(event) ?? normalizeUnknown(event) : void 0,
68
+ result: options.captureResult && result !== void 0 ? options.normalizeResult?.(result) ?? normalizeUnknown(result) : void 0
69
+ }
70
+ });
71
+ };
72
+ const wrappedCallback = callback ? (error, result) => {
73
+ capture(error, result);
74
+ callback(error, result);
75
+ } : void 0;
76
+ const invoke = () => {
77
+ try {
78
+ const result = handler(event, context, wrappedCallback);
79
+ if (isPromiseLike(result)) return result.then((value) => {
80
+ capture(void 0, value);
81
+ return value;
82
+ }, (error) => {
83
+ capture(error);
84
+ throw error;
85
+ });
86
+ if (result !== void 0 || !wrappedCallback) capture(void 0, result);
87
+ return result;
88
+ } catch (error) {
89
+ capture(error);
90
+ throw error;
91
+ }
92
+ };
93
+ if (!bindContext) return invoke();
94
+ return (0, _loggerjs_core.withContext)({
95
+ functionName: context?.functionName,
96
+ requestId,
97
+ serverlessPlatform: platform
98
+ }, invoke);
99
+ };
100
+ }
101
+ //#endregion
102
+ exports.serverlessIntegration = serverlessIntegration;
103
+
104
+ //# sourceMappingURL=serverless-integration.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"serverless-integration.cjs","names":[],"sources":["../src/serverless-integration.ts"],"sourcesContent":["import {\n normalizeValue,\n withContext,\n type LoggerLevel,\n type LoggerLike,\n type LogData,\n} from \"@loggerjs/core\";\n\nexport type ServerlessCallback<TResult> = (error?: unknown, result?: TResult) => void;\n\nexport type ServerlessHandler<TEvent, TContext, TResult> = (\n event: TEvent,\n context: TContext,\n callback?: ServerlessCallback<TResult>,\n) => TResult | Promise<TResult> | void;\n\nexport interface ServerlessContextLike {\n awsRequestId?: string;\n functionName?: string;\n functionVersion?: string;\n invokedFunctionArn?: string;\n [key: string]: unknown;\n}\n\nexport interface ServerlessEventLike {\n httpMethod?: string;\n path?: string;\n rawPath?: string;\n routeKey?: string;\n headers?: Record<string, string | undefined>;\n requestContext?: {\n requestId?: string;\n http?: {\n method?: string;\n path?: string;\n };\n routeKey?: string;\n };\n [key: string]: unknown;\n}\n\nexport interface ServerlessInvocationInfo<TEvent, TContext> {\n event: TEvent;\n context: TContext;\n requestId?: string;\n operation?: string;\n}\n\nexport interface ServerlessIntegrationOptions<TEvent, TContext, TResult> {\n name?: string;\n platform?: string;\n captureSuccessful?: boolean;\n captureAll?: boolean;\n sampleRate?: number;\n random?: () => number;\n captureEvent?: boolean;\n captureResult?: boolean;\n bindContext?: boolean;\n getRequestId?: (event: TEvent, context: TContext) => string | undefined;\n getOperation?: (event: TEvent, context: TContext) => string | undefined;\n level?: (\n error: unknown,\n durationMs: number,\n info: ServerlessInvocationInfo<TEvent, TContext>,\n ) => LoggerLevel;\n normalizeEvent?: (event: TEvent) => unknown;\n normalizeResult?: (result: TResult) => unknown;\n}\n\nconst defaultRandom = () => Math.random();\nlet coldStart = true;\n\nfunction isPromiseLike<TResult>(value: unknown): value is PromiseLike<TResult> {\n return (\n typeof value === \"object\" &&\n value !== null &&\n typeof (value as { then?: unknown }).then === \"function\"\n );\n}\n\nfunction defaultLevel(error: unknown): LoggerLevel {\n return error ? \"error\" : \"info\";\n}\n\nfunction defaultRequestId(event: unknown, context: unknown): string | undefined {\n const ctx = context as ServerlessContextLike | undefined;\n const evt = event as ServerlessEventLike | undefined;\n return (\n ctx?.awsRequestId ??\n evt?.requestContext?.requestId ??\n evt?.headers?.[\"x-request-id\"] ??\n evt?.headers?.[\"X-Request-Id\"]\n );\n}\n\nfunction defaultOperation(event: unknown, context: unknown): string | undefined {\n const ctx = context as ServerlessContextLike | undefined;\n const evt = event as ServerlessEventLike | undefined;\n return (\n evt?.routeKey ??\n evt?.requestContext?.routeKey ??\n (evt?.requestContext?.http?.method && evt.requestContext.http.path\n ? `${evt.requestContext.http.method} ${evt.requestContext.http.path}`\n : undefined) ??\n (evt?.httpMethod && (evt.rawPath ?? evt.path)\n ? `${evt.httpMethod} ${evt.rawPath ?? evt.path}`\n : undefined) ??\n ctx?.functionName\n );\n}\n\nfunction normalizeUnknown(value: unknown) {\n return normalizeValue(value, { maxDepth: 5, maxObjectKeys: 120 });\n}\n\nexport function serverlessIntegration<TEvent, TContext, TResult>(\n logger: LoggerLike,\n handler: ServerlessHandler<TEvent, TContext, TResult>,\n options: ServerlessIntegrationOptions<TEvent, TContext, TResult> = {},\n): ServerlessHandler<TEvent, TContext, TResult> {\n const name = options.name ?? \"serverless\";\n const platform = options.platform ?? \"serverless\";\n const captureSuccessful = options.captureSuccessful ?? options.captureAll ?? true;\n const sampleRate = options.sampleRate ?? 1;\n const random = options.random ?? defaultRandom;\n const bindContext = options.bindContext ?? true;\n const levelFor = options.level ?? defaultLevel;\n\n return (event, context, callback) => {\n const started = Date.now();\n const currentColdStart = coldStart;\n coldStart = false;\n const requestId = options.getRequestId?.(event, context) ?? defaultRequestId(event, context);\n const operation = options.getOperation?.(event, context) ?? defaultOperation(event, context);\n let captured = false;\n\n const shouldCapture = (error: unknown) => {\n if (error) return true;\n if (!captureSuccessful) return false;\n return sampleRate >= 1 || random() < sampleRate;\n };\n\n const capture = (error: unknown, result?: TResult) => {\n if (captured || !shouldCapture(error)) return;\n captured = true;\n const durationMs = Date.now() - started;\n const info: ServerlessInvocationInfo<TEvent, TContext> = {\n context,\n event,\n operation,\n requestId,\n };\n logger.log(levelFor(error, durationMs, info), `Serverless ${operation ?? name}`, {\n error,\n serverless: {\n kind: name,\n platform,\n operation,\n requestId,\n coldStart: currentColdStart,\n durationMs,\n event: options.captureEvent\n ? (options.normalizeEvent?.(event) ?? normalizeUnknown(event))\n : undefined,\n result:\n options.captureResult && result !== undefined\n ? (options.normalizeResult?.(result) ?? normalizeUnknown(result))\n : undefined,\n },\n } as LogData);\n };\n\n const wrappedCallback = callback\n ? (error?: unknown, result?: TResult) => {\n capture(error, result);\n callback(error, result);\n }\n : undefined;\n\n const invoke = () => {\n try {\n const result = handler(event, context, wrappedCallback);\n if (isPromiseLike<TResult>(result)) {\n return result.then(\n (value) => {\n capture(undefined, value);\n return value;\n },\n (error) => {\n capture(error);\n throw error;\n },\n );\n }\n if (result !== undefined || !wrappedCallback) capture(undefined, result as TResult);\n return result;\n } catch (error) {\n capture(error);\n throw error;\n }\n };\n\n if (!bindContext) return invoke();\n return withContext(\n {\n functionName: (context as ServerlessContextLike | undefined)?.functionName,\n requestId,\n serverlessPlatform: platform,\n },\n invoke,\n );\n };\n}\n"],"mappings":"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"}
@@ -0,0 +1,103 @@
1
+ import { normalizeValue, withContext } from "@loggerjs/core";
2
+ //#region src/serverless-integration.ts
3
+ const defaultRandom = () => Math.random();
4
+ let coldStart = true;
5
+ function isPromiseLike(value) {
6
+ return typeof value === "object" && value !== null && typeof value.then === "function";
7
+ }
8
+ function defaultLevel(error) {
9
+ return error ? "error" : "info";
10
+ }
11
+ function defaultRequestId(event, context) {
12
+ const ctx = context;
13
+ const evt = event;
14
+ return ctx?.awsRequestId ?? evt?.requestContext?.requestId ?? evt?.headers?.["x-request-id"] ?? evt?.headers?.["X-Request-Id"];
15
+ }
16
+ function defaultOperation(event, context) {
17
+ const ctx = context;
18
+ const evt = event;
19
+ return evt?.routeKey ?? evt?.requestContext?.routeKey ?? (evt?.requestContext?.http?.method && evt.requestContext.http.path ? `${evt.requestContext.http.method} ${evt.requestContext.http.path}` : void 0) ?? (evt?.httpMethod && (evt.rawPath ?? evt.path) ? `${evt.httpMethod} ${evt.rawPath ?? evt.path}` : void 0) ?? ctx?.functionName;
20
+ }
21
+ function normalizeUnknown(value) {
22
+ return normalizeValue(value, {
23
+ maxDepth: 5,
24
+ maxObjectKeys: 120
25
+ });
26
+ }
27
+ function serverlessIntegration(logger, handler, options = {}) {
28
+ const name = options.name ?? "serverless";
29
+ const platform = options.platform ?? "serverless";
30
+ const captureSuccessful = options.captureSuccessful ?? options.captureAll ?? true;
31
+ const sampleRate = options.sampleRate ?? 1;
32
+ const random = options.random ?? defaultRandom;
33
+ const bindContext = options.bindContext ?? true;
34
+ const levelFor = options.level ?? defaultLevel;
35
+ return (event, context, callback) => {
36
+ const started = Date.now();
37
+ const currentColdStart = coldStart;
38
+ coldStart = false;
39
+ const requestId = options.getRequestId?.(event, context) ?? defaultRequestId(event, context);
40
+ const operation = options.getOperation?.(event, context) ?? defaultOperation(event, context);
41
+ let captured = false;
42
+ const shouldCapture = (error) => {
43
+ if (error) return true;
44
+ if (!captureSuccessful) return false;
45
+ return sampleRate >= 1 || random() < sampleRate;
46
+ };
47
+ const capture = (error, result) => {
48
+ if (captured || !shouldCapture(error)) return;
49
+ captured = true;
50
+ const durationMs = Date.now() - started;
51
+ const info = {
52
+ context,
53
+ event,
54
+ operation,
55
+ requestId
56
+ };
57
+ logger.log(levelFor(error, durationMs, info), `Serverless ${operation ?? name}`, {
58
+ error,
59
+ serverless: {
60
+ kind: name,
61
+ platform,
62
+ operation,
63
+ requestId,
64
+ coldStart: currentColdStart,
65
+ durationMs,
66
+ event: options.captureEvent ? options.normalizeEvent?.(event) ?? normalizeUnknown(event) : void 0,
67
+ result: options.captureResult && result !== void 0 ? options.normalizeResult?.(result) ?? normalizeUnknown(result) : void 0
68
+ }
69
+ });
70
+ };
71
+ const wrappedCallback = callback ? (error, result) => {
72
+ capture(error, result);
73
+ callback(error, result);
74
+ } : void 0;
75
+ const invoke = () => {
76
+ try {
77
+ const result = handler(event, context, wrappedCallback);
78
+ if (isPromiseLike(result)) return result.then((value) => {
79
+ capture(void 0, value);
80
+ return value;
81
+ }, (error) => {
82
+ capture(error);
83
+ throw error;
84
+ });
85
+ if (result !== void 0 || !wrappedCallback) capture(void 0, result);
86
+ return result;
87
+ } catch (error) {
88
+ capture(error);
89
+ throw error;
90
+ }
91
+ };
92
+ if (!bindContext) return invoke();
93
+ return withContext({
94
+ functionName: context?.functionName,
95
+ requestId,
96
+ serverlessPlatform: platform
97
+ }, invoke);
98
+ };
99
+ }
100
+ //#endregion
101
+ export { serverlessIntegration };
102
+
103
+ //# sourceMappingURL=serverless-integration.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"serverless-integration.js","names":[],"sources":["../src/serverless-integration.ts"],"sourcesContent":["import {\n normalizeValue,\n withContext,\n type LoggerLevel,\n type LoggerLike,\n type LogData,\n} from \"@loggerjs/core\";\n\nexport type ServerlessCallback<TResult> = (error?: unknown, result?: TResult) => void;\n\nexport type ServerlessHandler<TEvent, TContext, TResult> = (\n event: TEvent,\n context: TContext,\n callback?: ServerlessCallback<TResult>,\n) => TResult | Promise<TResult> | void;\n\nexport interface ServerlessContextLike {\n awsRequestId?: string;\n functionName?: string;\n functionVersion?: string;\n invokedFunctionArn?: string;\n [key: string]: unknown;\n}\n\nexport interface ServerlessEventLike {\n httpMethod?: string;\n path?: string;\n rawPath?: string;\n routeKey?: string;\n headers?: Record<string, string | undefined>;\n requestContext?: {\n requestId?: string;\n http?: {\n method?: string;\n path?: string;\n };\n routeKey?: string;\n };\n [key: string]: unknown;\n}\n\nexport interface ServerlessInvocationInfo<TEvent, TContext> {\n event: TEvent;\n context: TContext;\n requestId?: string;\n operation?: string;\n}\n\nexport interface ServerlessIntegrationOptions<TEvent, TContext, TResult> {\n name?: string;\n platform?: string;\n captureSuccessful?: boolean;\n captureAll?: boolean;\n sampleRate?: number;\n random?: () => number;\n captureEvent?: boolean;\n captureResult?: boolean;\n bindContext?: boolean;\n getRequestId?: (event: TEvent, context: TContext) => string | undefined;\n getOperation?: (event: TEvent, context: TContext) => string | undefined;\n level?: (\n error: unknown,\n durationMs: number,\n info: ServerlessInvocationInfo<TEvent, TContext>,\n ) => LoggerLevel;\n normalizeEvent?: (event: TEvent) => unknown;\n normalizeResult?: (result: TResult) => unknown;\n}\n\nconst defaultRandom = () => Math.random();\nlet coldStart = true;\n\nfunction isPromiseLike<TResult>(value: unknown): value is PromiseLike<TResult> {\n return (\n typeof value === \"object\" &&\n value !== null &&\n typeof (value as { then?: unknown }).then === \"function\"\n );\n}\n\nfunction defaultLevel(error: unknown): LoggerLevel {\n return error ? \"error\" : \"info\";\n}\n\nfunction defaultRequestId(event: unknown, context: unknown): string | undefined {\n const ctx = context as ServerlessContextLike | undefined;\n const evt = event as ServerlessEventLike | undefined;\n return (\n ctx?.awsRequestId ??\n evt?.requestContext?.requestId ??\n evt?.headers?.[\"x-request-id\"] ??\n evt?.headers?.[\"X-Request-Id\"]\n );\n}\n\nfunction defaultOperation(event: unknown, context: unknown): string | undefined {\n const ctx = context as ServerlessContextLike | undefined;\n const evt = event as ServerlessEventLike | undefined;\n return (\n evt?.routeKey ??\n evt?.requestContext?.routeKey ??\n (evt?.requestContext?.http?.method && evt.requestContext.http.path\n ? `${evt.requestContext.http.method} ${evt.requestContext.http.path}`\n : undefined) ??\n (evt?.httpMethod && (evt.rawPath ?? evt.path)\n ? `${evt.httpMethod} ${evt.rawPath ?? evt.path}`\n : undefined) ??\n ctx?.functionName\n );\n}\n\nfunction normalizeUnknown(value: unknown) {\n return normalizeValue(value, { maxDepth: 5, maxObjectKeys: 120 });\n}\n\nexport function serverlessIntegration<TEvent, TContext, TResult>(\n logger: LoggerLike,\n handler: ServerlessHandler<TEvent, TContext, TResult>,\n options: ServerlessIntegrationOptions<TEvent, TContext, TResult> = {},\n): ServerlessHandler<TEvent, TContext, TResult> {\n const name = options.name ?? \"serverless\";\n const platform = options.platform ?? \"serverless\";\n const captureSuccessful = options.captureSuccessful ?? options.captureAll ?? true;\n const sampleRate = options.sampleRate ?? 1;\n const random = options.random ?? defaultRandom;\n const bindContext = options.bindContext ?? true;\n const levelFor = options.level ?? defaultLevel;\n\n return (event, context, callback) => {\n const started = Date.now();\n const currentColdStart = coldStart;\n coldStart = false;\n const requestId = options.getRequestId?.(event, context) ?? defaultRequestId(event, context);\n const operation = options.getOperation?.(event, context) ?? defaultOperation(event, context);\n let captured = false;\n\n const shouldCapture = (error: unknown) => {\n if (error) return true;\n if (!captureSuccessful) return false;\n return sampleRate >= 1 || random() < sampleRate;\n };\n\n const capture = (error: unknown, result?: TResult) => {\n if (captured || !shouldCapture(error)) return;\n captured = true;\n const durationMs = Date.now() - started;\n const info: ServerlessInvocationInfo<TEvent, TContext> = {\n context,\n event,\n operation,\n requestId,\n };\n logger.log(levelFor(error, durationMs, info), `Serverless ${operation ?? name}`, {\n error,\n serverless: {\n kind: name,\n platform,\n operation,\n requestId,\n coldStart: currentColdStart,\n durationMs,\n event: options.captureEvent\n ? (options.normalizeEvent?.(event) ?? normalizeUnknown(event))\n : undefined,\n result:\n options.captureResult && result !== undefined\n ? (options.normalizeResult?.(result) ?? normalizeUnknown(result))\n : undefined,\n },\n } as LogData);\n };\n\n const wrappedCallback = callback\n ? (error?: unknown, result?: TResult) => {\n capture(error, result);\n callback(error, result);\n }\n : undefined;\n\n const invoke = () => {\n try {\n const result = handler(event, context, wrappedCallback);\n if (isPromiseLike<TResult>(result)) {\n return result.then(\n (value) => {\n capture(undefined, value);\n return value;\n },\n (error) => {\n capture(error);\n throw error;\n },\n );\n }\n if (result !== undefined || !wrappedCallback) capture(undefined, result as TResult);\n return result;\n } catch (error) {\n capture(error);\n throw error;\n }\n };\n\n if (!bindContext) return invoke();\n return withContext(\n {\n functionName: (context as ServerlessContextLike | undefined)?.functionName,\n requestId,\n serverlessPlatform: platform,\n },\n invoke,\n );\n };\n}\n"],"mappings":"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"}