logixia 1.8.2 → 1.8.4
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/dist/.tsbuildinfo +1 -1
- package/dist/{index-CthBT3t8.d.mts → index-DknhKCCg.d.ts} +12 -1
- package/dist/index-DknhKCCg.d.ts.map +1 -0
- package/dist/{index-ClPZrfIU.d.ts → index-DnhKoNBG.d.mts} +12 -1
- package/dist/index-DnhKoNBG.d.mts.map +1 -0
- package/dist/index.d.mts +87 -16
- package/dist/index.d.mts.map +1 -1
- package/dist/index.d.ts +86 -15
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +78 -40
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +77 -37
- package/dist/index.mjs.map +1 -1
- package/dist/{logitron-logger.module-Dx2mUz-g.d.ts → logitron-logger.module-BkPXi0He.d.ts} +97 -5
- package/dist/logitron-logger.module-BkPXi0He.d.ts.map +1 -0
- package/dist/logitron-logger.module-CMDM61Iz.js +2566 -0
- package/dist/logitron-logger.module-CMDM61Iz.js.map +1 -0
- package/dist/{logitron-logger.module-KU_L04y1.d.mts → logitron-logger.module-Cd5M_59H.d.mts} +97 -5
- package/dist/logitron-logger.module-Cd5M_59H.d.mts.map +1 -0
- package/dist/logitron-logger.module-uyg1-Khn.mjs +2285 -0
- package/dist/logitron-logger.module-uyg1-Khn.mjs.map +1 -0
- package/dist/middleware.d.mts +1 -1
- package/dist/middleware.d.mts.map +1 -1
- package/dist/middleware.d.ts +1 -1
- package/dist/middleware.d.ts.map +1 -1
- package/dist/middleware.js +4 -1
- package/dist/middleware.js.map +1 -1
- package/dist/middleware.mjs +4 -1
- package/dist/middleware.mjs.map +1 -1
- package/dist/nest.d.mts +4 -44
- package/dist/nest.d.mts.map +1 -1
- package/dist/nest.d.ts +4 -44
- package/dist/nest.d.ts.map +1 -1
- package/dist/nest.js +3 -93
- package/dist/nest.mjs +3 -92
- package/dist/search.d.mts +1 -1
- package/dist/search.js +1 -1
- package/dist/search.mjs +1 -1
- package/dist/testing.d.mts +1 -1
- package/dist/testing.d.ts +1 -1
- package/dist/{transport.manager-BCnLEmOy.mjs → transport.manager-D3U03fJg.mjs} +21 -11
- package/dist/transport.manager-D3U03fJg.mjs.map +1 -0
- package/dist/{transport.manager-DU1W0wV3.js → transport.manager-DPjB-dFH.js} +49 -15
- package/dist/transport.manager-DPjB-dFH.js.map +1 -0
- package/dist/transports.d.mts +3 -1
- package/dist/transports.d.mts.map +1 -1
- package/dist/transports.d.ts +3 -1
- package/dist/transports.d.ts.map +1 -1
- package/dist/transports.js +1 -1
- package/dist/transports.mjs +1 -1
- package/package.json +24 -23
- package/dist/build-DOx-YxF1.js +0 -536
- package/dist/build-DOx-YxF1.js.map +0 -1
- package/dist/build-DWmxA6A2.mjs +0 -536
- package/dist/build-DWmxA6A2.mjs.map +0 -1
- package/dist/chunk-BTgCAUrQ.js +0 -53
- package/dist/chunk-uEZWKkIX.mjs +0 -32
- package/dist/esm-1Ra90uql.mjs +0 -4256
- package/dist/esm-1Ra90uql.mjs.map +0 -1
- package/dist/esm-FNhqFIqG.js +0 -4267
- package/dist/esm-FNhqFIqG.js.map +0 -1
- package/dist/index-ClPZrfIU.d.ts.map +0 -1
- package/dist/index-CthBT3t8.d.mts.map +0 -1
- package/dist/lib-8XKCHDOH.mjs +0 -66301
- package/dist/lib-8XKCHDOH.mjs.map +0 -1
- package/dist/lib-BNEYXXTQ.js +0 -66304
- package/dist/lib-BNEYXXTQ.js.map +0 -1
- package/dist/logitron-logger.module-DucvDnxZ.mjs +0 -10986
- package/dist/logitron-logger.module-DucvDnxZ.mjs.map +0 -1
- package/dist/logitron-logger.module-Dx2mUz-g.d.ts.map +0 -1
- package/dist/logitron-logger.module-Fof9Er2E.js +0 -11260
- package/dist/logitron-logger.module-Fof9Er2E.js.map +0 -1
- package/dist/logitron-logger.module-KU_L04y1.d.mts.map +0 -1
- package/dist/nest.js.map +0 -1
- package/dist/nest.mjs.map +0 -1
- package/dist/promise-BI-3eI4n.js +0 -22743
- package/dist/promise-BI-3eI4n.js.map +0 -1
- package/dist/promise-BrZcjavs.mjs +0 -22740
- package/dist/promise-BrZcjavs.mjs.map +0 -1
- package/dist/sqlite3-CSkpjC90.js +0 -420
- package/dist/sqlite3-CSkpjC90.js.map +0 -1
- package/dist/sqlite3-DD2_nRRH.mjs +0 -417
- package/dist/sqlite3-DD2_nRRH.mjs.map +0 -1
- package/dist/transport.manager-BCnLEmOy.mjs.map +0 -1
- package/dist/transport.manager-DU1W0wV3.js.map +0 -1
- /package/dist/{search-DanSf_yc.d.mts → search-DN676Dnz.d.mts} +0 -0
- /package/dist/{search-1txemGPh.mjs → search-DOvSI-mb.mjs} +0 -0
- /package/dist/{search-DeZHhWxB.js → search-DoZF3RZj.js} +0 -0
package/dist/middleware.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"middleware.mjs","names":["out: Record<string, unknown>","fields: Record<string, unknown>"],"sources":["../src/middleware/http-logger.ts"],"sourcesContent":["/**\n * HTTP request/response logging middleware — Morgan replacement.\n *\n * Fixes every documented Morgan bug:\n * - statusCode always captured correctly, even for requests > 20 s\n * - Logs request START (with traceId) and response FINISH (with duration)\n * - Captures errors before and after response\n * - Auto-redacts Authorization / Cookie / Set-Cookie headers\n * - Slow-request warnings\n * - Skip predicates for health-check routes / static assets\n *\n * @example Express\n * ```ts\n * import { createExpressMiddleware } from 'logixia/middleware';\n * app.use(createExpressMiddleware(logger));\n * ```\n *\n * @example Fastify\n * ```ts\n * import { createFastifyPlugin } from 'logixia/middleware';\n * await fastify.register(createFastifyPlugin(logger));\n * ```\n */\n\n/* eslint-disable sonarjs/void-use -- intentional fire-and-forget in sync middleware callbacks */\nimport type { IBaseLogger } from '../types';\n\n// ── Shared types ─────────────────────────────────────────────────────────────\n\nexport interface HttpLoggerOptions {\n /**\n * Skip logging for a request. Called before any I/O.\n * @example `skip: (req) => req.url === '/health'`\n */\n skip?: (req: IncomingRequest) => boolean;\n /**\n * Log request body (POST/PUT/PATCH). Capped at `bodyMaxBytes` (default: 4096).\n * Redaction still applies to the captured body.\n * Default: false.\n */\n logBody?: boolean;\n /** Max bytes of body to capture. Default: 4096. */\n bodyMaxBytes?: number;\n /**\n * Emit a WARN log when a request duration exceeds this threshold (ms).\n * Default: 1000.\n */\n slowRequestThresholdMs?: number;\n /**\n * Additional fields to include in every log entry.\n * @example `extraFields: (req) => ({ tenantId: req.headers['x-tenant-id'] })`\n */\n extraFields?: (req: IncomingRequest) => Record<string, unknown>;\n /**\n * Trace ID header. Default: 'x-trace-id'.\n * If the header is absent, a short random ID is generated.\n */\n traceIdHeader?: string;\n /**\n * Headers to redact from logged output.\n * Default: ['authorization', 'cookie', 'set-cookie', 'x-api-key'].\n */\n redactHeaders?: string[];\n /**\n * Log level for request-start entries. Default: 'debug'.\n * Set to 'silent' to suppress request-start logs entirely.\n */\n requestLevel?: string;\n /** Log level for successful response entries. Default: 'info'. */\n responseLevel?: string;\n /** Log level for error responses (status ≥ 500). Default: 'error'. */\n errorLevel?: string;\n}\n\n// Minimal structural types so we don't need @types/express / fastify in core\nexport interface IncomingRequest {\n method?: string;\n url?: string;\n headers?: Record<string, string | string[] | undefined>;\n body?: unknown;\n socket?: { remoteAddress?: string };\n ip?: string;\n}\n\nexport interface OutgoingResponse {\n statusCode?: number;\n on?: (event: string, cb: () => void) => void;\n once?: (event: string, cb: () => void) => void;\n getHeader?: (name: string) => string | number | string[] | undefined;\n}\n\n// ── Helpers ───────────────────────────────────────────────────────────────────\n\nconst DEFAULT_REDACT_HEADERS = new Set(['authorization', 'cookie', 'set-cookie', 'x-api-key']);\n\nfunction sanitizeHeaders(\n headers: Record<string, string | string[] | undefined> | undefined,\n redactSet: Set<string>\n): Record<string, unknown> {\n if (!headers) return {};\n const out: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(headers)) {\n out[k] = redactSet.has(k.toLowerCase()) ? '[REDACTED]' : v;\n }\n return out;\n}\n\nfunction shortId(): string {\n // eslint-disable-next-line sonarjs/pseudo-random -- non-security request ID\n return Math.random().toString(36).slice(2, 10);\n}\n\nfunction buildBaseFields(\n req: IncomingRequest,\n traceId: string,\n options: HttpLoggerOptions\n): Record<string, unknown> {\n const redactSet = options.redactHeaders\n ? new Set(options.redactHeaders.map((h) => h.toLowerCase()))\n : DEFAULT_REDACT_HEADERS;\n\n const fields: Record<string, unknown> = {\n traceId,\n method: req.method?.toUpperCase() ?? 'UNKNOWN',\n url: req.url ?? '/',\n ip: req.ip ?? req.socket?.remoteAddress ?? 'unknown',\n headers: sanitizeHeaders(req.headers, redactSet),\n };\n\n if (options.extraFields) {\n Object.assign(fields, options.extraFields(req));\n }\n\n return fields;\n}\n\n// ── Express middleware ────────────────────────────────────────────────────────\n\n/**\n * Create an Express / Connect compatible middleware that replaces Morgan.\n */\nexport function createExpressMiddleware(\n logger: IBaseLogger,\n options: HttpLoggerOptions = {}\n): (req: IncomingRequest, res: OutgoingResponse, next: () => void) => void {\n const {\n skip,\n logBody,\n bodyMaxBytes,\n traceIdHeader = 'x-trace-id',\n requestLevel = 'debug',\n responseLevel = 'info',\n errorLevel = 'error',\n slowRequestThresholdMs = 1000,\n } = options;\n\n return function logixiaHttpMiddleware(\n req: IncomingRequest,\n res: OutgoingResponse,\n next: () => void\n ): void {\n if (skip?.(req)) {\n next();\n return;\n }\n\n const traceId = (req.headers?.[traceIdHeader] as string | undefined) ?? shortId();\n const startMs = Date.now();\n const baseFields = buildBaseFields(req, traceId, options);\n\n // Log request start\n if (requestLevel !== 'silent') {\n void logger.logLevel(requestLevel, 'request started', {\n ...baseFields,\n ...(logBody && req.body ? { body: truncateBody(req.body, bodyMaxBytes) } : {}),\n });\n }\n\n // Hook into the response 'finish' event — fires after headers + body are sent.\n // This is what Morgan gets wrong for slow requests (it uses 'close' which may\n // fire before the status code is set on some Node versions).\n const onFinish = (): void => {\n const duration = Date.now() - startMs;\n const status = res.statusCode ?? 0;\n const level = status >= 500 ? errorLevel : responseLevel;\n\n void logger.logLevel(level, 'request completed', {\n ...baseFields,\n statusCode: status,\n duration,\n });\n\n if (duration > slowRequestThresholdMs) {\n void logger.warn('slow request detected', {\n ...baseFields,\n statusCode: status,\n duration,\n threshold: slowRequestThresholdMs,\n });\n }\n };\n\n res.once?.('finish', onFinish);\n // Fallback: also listen to 'close' (client disconnected before response finished)\n res.once?.('close', () => {\n if ((res.statusCode ?? 0) === 0) onFinish();\n });\n\n next();\n };\n}\n\n// ── Fastify plugin ─────────────────────────────────────────────────────────────\n\nexport interface FastifyInstance {\n addHook: (name: string, fn: (req: unknown, reply: unknown, done: () => void) => void) => void;\n}\n\n/**\n * Create a Fastify plugin (a function you pass to `fastify.register()`).\n *\n * @example\n * ```ts\n * await fastify.register(createFastifyPlugin(logger, { slowRequestThresholdMs: 500 }));\n * ```\n */\nexport function createFastifyPlugin(logger: IBaseLogger, options: HttpLoggerOptions = {}) {\n const {\n skip,\n traceIdHeader = 'x-trace-id',\n requestLevel = 'debug',\n responseLevel = 'info',\n errorLevel = 'error',\n slowRequestThresholdMs = 1000,\n } = options;\n\n return function logixiaFastifyPlugin(\n fastify: FastifyInstance,\n _opts: unknown,\n done: () => void\n ): void {\n fastify.addHook('onRequest', (request: unknown, _reply: unknown, hookDone: () => void) => {\n const req = request as IncomingRequest & { _logixiaStart?: number; _logixiaId?: string };\n if (skip?.(req)) {\n hookDone();\n return;\n }\n\n const traceId = (req.headers?.[traceIdHeader] as string | undefined) ?? shortId();\n req._logixiaStart = Date.now();\n req._logixiaId = traceId;\n\n if (requestLevel !== 'silent') {\n void logger.logLevel(\n requestLevel,\n 'request started',\n buildBaseFields(req, traceId, options)\n );\n }\n hookDone();\n });\n\n fastify.addHook('onResponse', (request: unknown, reply: unknown, hookDone: () => void) => {\n const req = request as IncomingRequest & { _logixiaStart?: number; _logixiaId?: string };\n const rep = reply as { statusCode?: number };\n const duration = Date.now() - (req._logixiaStart ?? Date.now());\n const status = rep.statusCode ?? 0;\n const traceId = req._logixiaId ?? shortId();\n const level = status >= 500 ? errorLevel : responseLevel;\n\n void logger.logLevel(level, 'request completed', {\n ...buildBaseFields(req, traceId, options),\n statusCode: status,\n duration,\n });\n\n if (duration > slowRequestThresholdMs) {\n void logger.warn('slow request detected', {\n traceId,\n url: req.url,\n method: req.method,\n duration,\n threshold: slowRequestThresholdMs,\n });\n }\n\n hookDone();\n });\n\n done();\n };\n}\n\n// ── Internal helpers ──────────────────────────────────────────────────────────\n\nfunction truncateBody(body: unknown, maxBytes = 4096): unknown {\n if (typeof body === 'string') {\n return body.length > maxBytes ? body.slice(0, maxBytes) + '…[truncated]' : body;\n }\n if (body && typeof body === 'object') {\n const str = JSON.stringify(body);\n if (str.length > maxBytes) {\n return str.slice(0, maxBytes) + '…[truncated]';\n }\n }\n return body;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"middleware.mjs","names":["out: Record<string, unknown>","fields: Record<string, unknown>"],"sources":["../src/middleware/http-logger.ts"],"sourcesContent":["/**\n * HTTP request/response logging middleware — Morgan replacement.\n *\n * Fixes every documented Morgan bug:\n * - statusCode always captured correctly, even for requests > 20 s\n * - Logs request START (with traceId) and response FINISH (with duration)\n * - Captures errors before and after response\n * - Auto-redacts Authorization / Cookie / Set-Cookie headers\n * - Slow-request warnings\n * - Skip predicates for health-check routes / static assets\n *\n * @example Express\n * ```ts\n * import { createExpressMiddleware } from 'logixia/middleware';\n * app.use(createExpressMiddleware(logger));\n * ```\n *\n * @example Fastify\n * ```ts\n * import { createFastifyPlugin } from 'logixia/middleware';\n * await fastify.register(createFastifyPlugin(logger));\n * ```\n */\n\n/* eslint-disable sonarjs/void-use -- intentional fire-and-forget in sync middleware callbacks */\nimport type { IBaseLogger } from '../types';\n\n// ── Shared types ─────────────────────────────────────────────────────────────\n\nexport interface HttpLoggerOptions {\n /**\n * Skip logging for a request. Called before any I/O.\n * @example `skip: (req) => req.url === '/health'`\n */\n skip?: (req: IncomingRequest) => boolean;\n /**\n * Log request body (POST/PUT/PATCH). Capped at `bodyMaxBytes` (default: 4096).\n * Redaction still applies to the captured body.\n * Default: false.\n */\n logBody?: boolean;\n /** Max bytes of body to capture. Default: 4096. */\n bodyMaxBytes?: number;\n /**\n * Emit a WARN log when a request duration exceeds this threshold (ms).\n * Default: 1000.\n */\n slowRequestThresholdMs?: number;\n /**\n * Additional fields to include in every log entry.\n * @example `extraFields: (req) => ({ tenantId: req.headers['x-tenant-id'] })`\n */\n extraFields?: (req: IncomingRequest) => Record<string, unknown>;\n /**\n * Trace ID header. Default: 'x-trace-id'.\n * If the header is absent, a short random ID is generated.\n */\n traceIdHeader?: string;\n /**\n * Headers to redact from logged output.\n * Default: ['authorization', 'cookie', 'set-cookie', 'x-api-key'].\n */\n redactHeaders?: string[];\n /**\n * Log level for request-start entries. Default: 'debug'.\n * Set to 'silent' to suppress request-start logs entirely.\n */\n requestLevel?: string;\n /** Log level for successful response entries. Default: 'info'. */\n responseLevel?: string;\n /** Log level for error responses (status ≥ 500). Default: 'error'. */\n errorLevel?: string;\n}\n\n// Minimal structural types so we don't need @types/express / fastify in core\nexport interface IncomingRequest {\n method?: string;\n url?: string;\n headers?: Record<string, string | string[] | undefined>;\n body?: unknown;\n socket?: { remoteAddress?: string };\n ip?: string;\n}\n\nexport interface OutgoingResponse {\n statusCode?: number;\n on?: (event: string, cb: () => void) => void;\n once?: (event: string, cb: () => void) => void;\n getHeader?: (name: string) => string | number | string[] | undefined;\n}\n\n// ── Helpers ───────────────────────────────────────────────────────────────────\n\nconst DEFAULT_REDACT_HEADERS = new Set(['authorization', 'cookie', 'set-cookie', 'x-api-key']);\n\nfunction sanitizeHeaders(\n headers: Record<string, string | string[] | undefined> | undefined,\n redactSet: Set<string>\n): Record<string, unknown> {\n if (!headers) return {};\n const out: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(headers)) {\n if (k === '__proto__' || k === 'constructor' || k === 'prototype') continue;\n out[k] = redactSet.has(k.toLowerCase()) ? '[REDACTED]' : v;\n }\n return out;\n}\n\nfunction shortId(): string {\n // eslint-disable-next-line sonarjs/pseudo-random -- non-security request ID\n return Math.random().toString(36).slice(2, 10);\n}\n\nfunction buildBaseFields(\n req: IncomingRequest,\n traceId: string,\n options: HttpLoggerOptions\n): Record<string, unknown> {\n const redactSet = options.redactHeaders\n ? new Set(options.redactHeaders.map((h) => h.toLowerCase()))\n : DEFAULT_REDACT_HEADERS;\n\n const fields: Record<string, unknown> = {\n traceId,\n method: req.method?.toUpperCase() ?? 'UNKNOWN',\n url: req.url ?? '/',\n ip: req.ip ?? req.socket?.remoteAddress ?? 'unknown',\n headers: sanitizeHeaders(req.headers, redactSet),\n };\n\n if (options.extraFields) {\n Object.assign(fields, options.extraFields(req));\n }\n\n return fields;\n}\n\n// ── Express middleware ────────────────────────────────────────────────────────\n\n/**\n * Create an Express / Connect compatible middleware that replaces Morgan.\n */\nexport function createExpressMiddleware(\n logger: IBaseLogger,\n options: HttpLoggerOptions = {}\n): (req: IncomingRequest, res: OutgoingResponse, next: () => void) => void {\n const {\n skip,\n logBody,\n bodyMaxBytes,\n traceIdHeader = 'x-trace-id',\n requestLevel = 'debug',\n responseLevel = 'info',\n errorLevel = 'error',\n slowRequestThresholdMs = 1000,\n } = options;\n\n return function logixiaHttpMiddleware(\n req: IncomingRequest,\n res: OutgoingResponse,\n next: () => void\n ): void {\n if (skip?.(req)) {\n next();\n return;\n }\n\n const traceId = (req.headers?.[traceIdHeader] as string | undefined) ?? shortId();\n const startMs = Date.now();\n const baseFields = buildBaseFields(req, traceId, options);\n\n // Log request start\n if (requestLevel !== 'silent') {\n void logger.logLevel(requestLevel, 'request started', {\n ...baseFields,\n ...(logBody && req.body ? { body: truncateBody(req.body, bodyMaxBytes) } : {}),\n });\n }\n\n // Hook into the response 'finish' event — fires after headers + body are sent.\n // This is what Morgan gets wrong for slow requests (it uses 'close' which may\n // fire before the status code is set on some Node versions).\n const onFinish = (): void => {\n const duration = Date.now() - startMs;\n const status = res.statusCode ?? 0;\n const level = status >= 500 ? errorLevel : responseLevel;\n\n void logger.logLevel(level, 'request completed', {\n ...baseFields,\n statusCode: status,\n duration,\n });\n\n if (duration > slowRequestThresholdMs) {\n void logger.warn('slow request detected', {\n ...baseFields,\n statusCode: status,\n duration,\n threshold: slowRequestThresholdMs,\n });\n }\n };\n\n res.once?.('finish', onFinish);\n // Fallback: also listen to 'close' (client disconnected before response finished)\n res.once?.('close', () => {\n if ((res.statusCode ?? 0) === 0) onFinish();\n });\n\n next();\n };\n}\n\n// ── Fastify plugin ─────────────────────────────────────────────────────────────\n\nexport interface FastifyInstance {\n addHook: (name: string, fn: (req: unknown, reply: unknown, done: () => void) => void) => void;\n}\n\n/**\n * Create a Fastify plugin (a function you pass to `fastify.register()`).\n *\n * @example\n * ```ts\n * await fastify.register(createFastifyPlugin(logger, { slowRequestThresholdMs: 500 }));\n * ```\n */\nexport function createFastifyPlugin(logger: IBaseLogger, options: HttpLoggerOptions = {}) {\n const {\n skip,\n traceIdHeader = 'x-trace-id',\n requestLevel = 'debug',\n responseLevel = 'info',\n errorLevel = 'error',\n slowRequestThresholdMs = 1000,\n } = options;\n\n return function logixiaFastifyPlugin(\n fastify: FastifyInstance,\n _opts: unknown,\n done: () => void\n ): void {\n fastify.addHook('onRequest', (request: unknown, _reply: unknown, hookDone: () => void) => {\n const req = request as IncomingRequest & { _logixiaStart?: number; _logixiaId?: string };\n if (skip?.(req)) {\n hookDone();\n return;\n }\n\n const traceId = (req.headers?.[traceIdHeader] as string | undefined) ?? shortId();\n req._logixiaStart = Date.now();\n req._logixiaId = traceId;\n\n if (requestLevel !== 'silent') {\n void logger.logLevel(\n requestLevel,\n 'request started',\n buildBaseFields(req, traceId, options)\n );\n }\n hookDone();\n });\n\n fastify.addHook('onResponse', (request: unknown, reply: unknown, hookDone: () => void) => {\n const req = request as IncomingRequest & { _logixiaStart?: number; _logixiaId?: string };\n const rep = reply as { statusCode?: number };\n const duration = Date.now() - (req._logixiaStart ?? Date.now());\n const status = rep.statusCode ?? 0;\n const traceId = req._logixiaId ?? shortId();\n const level = status >= 500 ? errorLevel : responseLevel;\n\n void logger.logLevel(level, 'request completed', {\n ...buildBaseFields(req, traceId, options),\n statusCode: status,\n duration,\n });\n\n if (duration > slowRequestThresholdMs) {\n void logger.warn('slow request detected', {\n traceId,\n url: req.url,\n method: req.method,\n duration,\n threshold: slowRequestThresholdMs,\n });\n }\n\n hookDone();\n });\n\n done();\n };\n}\n\n// ── Internal helpers ──────────────────────────────────────────────────────────\n\nfunction truncateBody(body: unknown, maxBytes = 4096): unknown {\n if (typeof body === 'string') {\n return body.length > maxBytes ? body.slice(0, maxBytes) + '…[truncated]' : body;\n }\n if (body && typeof body === 'object') {\n const str = JSON.stringify(body);\n if (str.length > maxBytes) {\n return str.slice(0, maxBytes) + '…[truncated]';\n }\n }\n return body;\n}\n"],"mappings":"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"}
|
package/dist/nest.d.mts
CHANGED
|
@@ -1,50 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { a as LogixiaOptionsFactory, c as LogixiaLoggerService, i as LogixiaLoggerModule, n as LOGIXIA_LOGGER_PREFIX, o as WebSocketTraceInterceptor, r as LogixiaAsyncOptions, s as KafkaTraceInterceptor, t as LOGIXIA_LOGGER_CONFIG } from "./logitron-logger.module-
|
|
1
|
+
import { T as TraceIdConfig } from "./index-DnhKoNBG.mjs";
|
|
2
|
+
import { a as LogixiaOptionsFactory, c as LogixiaLoggerService, i as LogixiaLoggerModule, l as LogixiaServiceWith, n as LOGIXIA_LOGGER_PREFIX, o as WebSocketTraceInterceptor, r as LogixiaAsyncOptions, s as KafkaTraceInterceptor, t as LOGIXIA_LOGGER_CONFIG, u as LogixiaServiceWithLevels } from "./logitron-logger.module-Cd5M_59H.mjs";
|
|
3
3
|
import { NestMiddleware } from "@nestjs/common";
|
|
4
4
|
import { NextFunction, Request, Response } from "express";
|
|
5
5
|
|
|
6
|
-
//#region src/core/request-context.d.ts
|
|
7
|
-
declare class RequestContextManager {
|
|
8
|
-
private static contexts;
|
|
9
|
-
/**
|
|
10
|
-
* Create a new request context
|
|
11
|
-
*/
|
|
12
|
-
static createContext(request: HttpRequest, traceId?: string): RequestContext;
|
|
13
|
-
/**
|
|
14
|
-
* Update request context with response data
|
|
15
|
-
*/
|
|
16
|
-
static updateContext(traceId: string, response?: HttpResponse, error?: Error): RequestContext | undefined;
|
|
17
|
-
/**
|
|
18
|
-
* Get request context by trace ID
|
|
19
|
-
*/
|
|
20
|
-
static getContext(traceId: string): RequestContext | undefined;
|
|
21
|
-
/**
|
|
22
|
-
* Remove request context (cleanup)
|
|
23
|
-
*/
|
|
24
|
-
static removeContext(traceId: string): boolean;
|
|
25
|
-
/**
|
|
26
|
-
* Get all active contexts
|
|
27
|
-
*/
|
|
28
|
-
static getAllContexts(): RequestContext[];
|
|
29
|
-
/**
|
|
30
|
-
* Clear all contexts (useful for testing)
|
|
31
|
-
*/
|
|
32
|
-
static clearAll(): void;
|
|
33
|
-
/**
|
|
34
|
-
* Get context statistics
|
|
35
|
-
*/
|
|
36
|
-
static getStats(): {
|
|
37
|
-
activeContexts: number;
|
|
38
|
-
averageDuration: number;
|
|
39
|
-
completedRequests: number;
|
|
40
|
-
};
|
|
41
|
-
/**
|
|
42
|
-
* Cleanup old completed contexts (older than specified time)
|
|
43
|
-
*/
|
|
44
|
-
static cleanup(maxAgeMs?: number): number;
|
|
45
|
-
}
|
|
46
|
-
//#endregion
|
|
47
6
|
//#region src/core/trace.middleware.d.ts
|
|
7
|
+
|
|
48
8
|
declare global {
|
|
49
9
|
namespace Express {
|
|
50
10
|
interface Request {
|
|
@@ -59,5 +19,5 @@ declare class TraceMiddleware implements NestMiddleware {
|
|
|
59
19
|
use(req: Request, res: Response, next: NextFunction): void;
|
|
60
20
|
}
|
|
61
21
|
//#endregion
|
|
62
|
-
export { KafkaTraceInterceptor, LOGIXIA_LOGGER_CONFIG, LOGIXIA_LOGGER_PREFIX, type LogixiaAsyncOptions, LogixiaLoggerModule, LogixiaLoggerService, type LogixiaOptionsFactory,
|
|
22
|
+
export { KafkaTraceInterceptor, LOGIXIA_LOGGER_CONFIG, LOGIXIA_LOGGER_PREFIX, type LogixiaAsyncOptions, LogixiaLoggerModule, LogixiaLoggerService, type LogixiaOptionsFactory, type LogixiaServiceWith, type LogixiaServiceWithLevels, TraceMiddleware, WebSocketTraceInterceptor };
|
|
63
23
|
//# sourceMappingURL=nest.d.mts.map
|
package/dist/nest.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"nest.d.mts","names":[],"sources":["../src/core/
|
|
1
|
+
{"version":3,"file":"nest.d.mts","names":[],"sources":["../src/core/trace.middleware.ts"],"sourcesContent":[],"mappings":";;;;;;;QA6DyC,MAAA,CAAA;EAxBD,UAAA,OAAA,CAAA;IAAc,UAAA,OAAA,CAAA;;;;;cAAzC,eAAA,YAA2B;;;uBAGY;WAqBzC,cAAc,gBAAgB"}
|
package/dist/nest.d.ts
CHANGED
|
@@ -1,50 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { a as LogixiaOptionsFactory, c as LogixiaLoggerService, i as LogixiaLoggerModule, n as LOGIXIA_LOGGER_PREFIX, o as WebSocketTraceInterceptor, r as LogixiaAsyncOptions, s as KafkaTraceInterceptor, t as LOGIXIA_LOGGER_CONFIG } from "./logitron-logger.module-
|
|
1
|
+
import { T as TraceIdConfig } from "./index-DknhKCCg.js";
|
|
2
|
+
import { a as LogixiaOptionsFactory, c as LogixiaLoggerService, i as LogixiaLoggerModule, l as LogixiaServiceWith, n as LOGIXIA_LOGGER_PREFIX, o as WebSocketTraceInterceptor, r as LogixiaAsyncOptions, s as KafkaTraceInterceptor, t as LOGIXIA_LOGGER_CONFIG, u as LogixiaServiceWithLevels } from "./logitron-logger.module-BkPXi0He.js";
|
|
3
3
|
import { NestMiddleware } from "@nestjs/common";
|
|
4
4
|
import { NextFunction, Request, Response } from "express";
|
|
5
5
|
|
|
6
|
-
//#region src/core/request-context.d.ts
|
|
7
|
-
declare class RequestContextManager {
|
|
8
|
-
private static contexts;
|
|
9
|
-
/**
|
|
10
|
-
* Create a new request context
|
|
11
|
-
*/
|
|
12
|
-
static createContext(request: HttpRequest, traceId?: string): RequestContext;
|
|
13
|
-
/**
|
|
14
|
-
* Update request context with response data
|
|
15
|
-
*/
|
|
16
|
-
static updateContext(traceId: string, response?: HttpResponse, error?: Error): RequestContext | undefined;
|
|
17
|
-
/**
|
|
18
|
-
* Get request context by trace ID
|
|
19
|
-
*/
|
|
20
|
-
static getContext(traceId: string): RequestContext | undefined;
|
|
21
|
-
/**
|
|
22
|
-
* Remove request context (cleanup)
|
|
23
|
-
*/
|
|
24
|
-
static removeContext(traceId: string): boolean;
|
|
25
|
-
/**
|
|
26
|
-
* Get all active contexts
|
|
27
|
-
*/
|
|
28
|
-
static getAllContexts(): RequestContext[];
|
|
29
|
-
/**
|
|
30
|
-
* Clear all contexts (useful for testing)
|
|
31
|
-
*/
|
|
32
|
-
static clearAll(): void;
|
|
33
|
-
/**
|
|
34
|
-
* Get context statistics
|
|
35
|
-
*/
|
|
36
|
-
static getStats(): {
|
|
37
|
-
activeContexts: number;
|
|
38
|
-
averageDuration: number;
|
|
39
|
-
completedRequests: number;
|
|
40
|
-
};
|
|
41
|
-
/**
|
|
42
|
-
* Cleanup old completed contexts (older than specified time)
|
|
43
|
-
*/
|
|
44
|
-
static cleanup(maxAgeMs?: number): number;
|
|
45
|
-
}
|
|
46
|
-
//#endregion
|
|
47
6
|
//#region src/core/trace.middleware.d.ts
|
|
7
|
+
|
|
48
8
|
declare global {
|
|
49
9
|
namespace Express {
|
|
50
10
|
interface Request {
|
|
@@ -59,5 +19,5 @@ declare class TraceMiddleware implements NestMiddleware {
|
|
|
59
19
|
use(req: Request, res: Response, next: NextFunction): void;
|
|
60
20
|
}
|
|
61
21
|
//#endregion
|
|
62
|
-
export { KafkaTraceInterceptor, LOGIXIA_LOGGER_CONFIG, LOGIXIA_LOGGER_PREFIX, type LogixiaAsyncOptions, LogixiaLoggerModule, LogixiaLoggerService, type LogixiaOptionsFactory,
|
|
22
|
+
export { KafkaTraceInterceptor, LOGIXIA_LOGGER_CONFIG, LOGIXIA_LOGGER_PREFIX, type LogixiaAsyncOptions, LogixiaLoggerModule, LogixiaLoggerService, type LogixiaOptionsFactory, type LogixiaServiceWith, type LogixiaServiceWithLevels, TraceMiddleware, WebSocketTraceInterceptor };
|
|
63
23
|
//# sourceMappingURL=nest.d.ts.map
|
package/dist/nest.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"nest.d.ts","names":[],"sources":["../src/core/
|
|
1
|
+
{"version":3,"file":"nest.d.ts","names":[],"sources":["../src/core/trace.middleware.ts"],"sourcesContent":[],"mappings":";;;;;;;QA6DyC,MAAA,CAAA;EAxBD,UAAA,OAAA,CAAA;IAAc,UAAA,OAAA,CAAA;;;;;cAAzC,eAAA,YAA2B;;;uBAGY;WAqBzC,cAAc,gBAAgB"}
|
package/dist/nest.js
CHANGED
|
@@ -1,94 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
require('./
|
|
1
|
+
require('./transport.manager-DPjB-dFH.js');
|
|
2
|
+
const require_logitron_logger_module = require('./logitron-logger.module-CMDM61Iz.js');
|
|
3
3
|
|
|
4
|
-
//#region src/core/request-context.ts
|
|
5
|
-
var RequestContextManager = class {
|
|
6
|
-
static #_ = this.contexts = /* @__PURE__ */ new Map();
|
|
7
|
-
/**
|
|
8
|
-
* Create a new request context
|
|
9
|
-
*/
|
|
10
|
-
static createContext(request, traceId) {
|
|
11
|
-
const ctx = require_logitron_logger_module.TraceContext.instance;
|
|
12
|
-
const contextTraceId = traceId || ctx.getCurrentTraceId() || ctx.generate();
|
|
13
|
-
const context = {
|
|
14
|
-
traceId: contextTraceId,
|
|
15
|
-
startTime: Date.now(),
|
|
16
|
-
request,
|
|
17
|
-
...request.userAgent && { userAgent: request.userAgent },
|
|
18
|
-
...request.ip && { ip: request.ip }
|
|
19
|
-
};
|
|
20
|
-
this.contexts.set(contextTraceId, context);
|
|
21
|
-
require_logitron_logger_module.TraceContext.instance.setTraceId(contextTraceId, {
|
|
22
|
-
method: request.method,
|
|
23
|
-
url: request.url
|
|
24
|
-
});
|
|
25
|
-
return context;
|
|
26
|
-
}
|
|
27
|
-
/**
|
|
28
|
-
* Update request context with response data
|
|
29
|
-
*/
|
|
30
|
-
static updateContext(traceId, response, error) {
|
|
31
|
-
const context = this.contexts.get(traceId);
|
|
32
|
-
if (!context) return;
|
|
33
|
-
const endTime = Date.now();
|
|
34
|
-
context.endTime = endTime;
|
|
35
|
-
context.duration = endTime - context.startTime;
|
|
36
|
-
if (response) context.response = response;
|
|
37
|
-
if (error) context.error = error;
|
|
38
|
-
return context;
|
|
39
|
-
}
|
|
40
|
-
/**
|
|
41
|
-
* Get request context by trace ID
|
|
42
|
-
*/
|
|
43
|
-
static getContext(traceId) {
|
|
44
|
-
return this.contexts.get(traceId);
|
|
45
|
-
}
|
|
46
|
-
/**
|
|
47
|
-
* Remove request context (cleanup)
|
|
48
|
-
*/
|
|
49
|
-
static removeContext(traceId) {
|
|
50
|
-
return this.contexts.delete(traceId);
|
|
51
|
-
}
|
|
52
|
-
/**
|
|
53
|
-
* Get all active contexts
|
|
54
|
-
*/
|
|
55
|
-
static getAllContexts() {
|
|
56
|
-
return Array.from(this.contexts.values());
|
|
57
|
-
}
|
|
58
|
-
/**
|
|
59
|
-
* Clear all contexts (useful for testing)
|
|
60
|
-
*/
|
|
61
|
-
static clearAll() {
|
|
62
|
-
this.contexts.clear();
|
|
63
|
-
}
|
|
64
|
-
/**
|
|
65
|
-
* Get context statistics
|
|
66
|
-
*/
|
|
67
|
-
static getStats() {
|
|
68
|
-
const contexts = Array.from(this.contexts.values());
|
|
69
|
-
const completedContexts = contexts.filter((ctx) => ctx.endTime);
|
|
70
|
-
const averageDuration = completedContexts.length > 0 ? completedContexts.reduce((sum, ctx) => sum + (ctx.duration || 0), 0) / completedContexts.length : 0;
|
|
71
|
-
return {
|
|
72
|
-
activeContexts: contexts.length,
|
|
73
|
-
averageDuration,
|
|
74
|
-
completedRequests: completedContexts.length
|
|
75
|
-
};
|
|
76
|
-
}
|
|
77
|
-
/**
|
|
78
|
-
* Cleanup old completed contexts (older than specified time)
|
|
79
|
-
*/
|
|
80
|
-
static cleanup(maxAgeMs = 3e5) {
|
|
81
|
-
const now = Date.now();
|
|
82
|
-
let cleaned = 0;
|
|
83
|
-
for (const [traceId, context] of this.contexts.entries()) if (context.endTime && now - context.endTime > maxAgeMs) {
|
|
84
|
-
this.contexts.delete(traceId);
|
|
85
|
-
cleaned++;
|
|
86
|
-
}
|
|
87
|
-
return cleaned;
|
|
88
|
-
}
|
|
89
|
-
};
|
|
90
|
-
|
|
91
|
-
//#endregion
|
|
92
4
|
Object.defineProperty(exports, 'KafkaTraceInterceptor', {
|
|
93
5
|
enumerable: true,
|
|
94
6
|
get: function () {
|
|
@@ -109,7 +21,6 @@ Object.defineProperty(exports, 'LogixiaLoggerService', {
|
|
|
109
21
|
return require_logitron_logger_module.LogixiaLoggerService;
|
|
110
22
|
}
|
|
111
23
|
});
|
|
112
|
-
exports.RequestContextManager = RequestContextManager;
|
|
113
24
|
Object.defineProperty(exports, 'TraceMiddleware', {
|
|
114
25
|
enumerable: true,
|
|
115
26
|
get: function () {
|
|
@@ -121,5 +32,4 @@ Object.defineProperty(exports, 'WebSocketTraceInterceptor', {
|
|
|
121
32
|
get: function () {
|
|
122
33
|
return require_logitron_logger_module.WebSocketTraceInterceptor;
|
|
123
34
|
}
|
|
124
|
-
});
|
|
125
|
-
//# sourceMappingURL=nest.js.map
|
|
35
|
+
});
|
package/dist/nest.mjs
CHANGED
|
@@ -1,93 +1,4 @@
|
|
|
1
|
-
import
|
|
2
|
-
import "./
|
|
1
|
+
import "./transport.manager-D3U03fJg.mjs";
|
|
2
|
+
import { a as TraceMiddleware, c as KafkaTraceInterceptor, i as WebSocketTraceInterceptor, l as LogixiaLoggerService, n as LOGIXIA_LOGGER_PREFIX, r as LogixiaLoggerModule, t as LOGIXIA_LOGGER_CONFIG } from "./logitron-logger.module-uyg1-Khn.mjs";
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
var RequestContextManager = class {
|
|
6
|
-
static #_ = this.contexts = /* @__PURE__ */ new Map();
|
|
7
|
-
/**
|
|
8
|
-
* Create a new request context
|
|
9
|
-
*/
|
|
10
|
-
static createContext(request, traceId) {
|
|
11
|
-
const ctx = TraceContext.instance;
|
|
12
|
-
const contextTraceId = traceId || ctx.getCurrentTraceId() || ctx.generate();
|
|
13
|
-
const context = {
|
|
14
|
-
traceId: contextTraceId,
|
|
15
|
-
startTime: Date.now(),
|
|
16
|
-
request,
|
|
17
|
-
...request.userAgent && { userAgent: request.userAgent },
|
|
18
|
-
...request.ip && { ip: request.ip }
|
|
19
|
-
};
|
|
20
|
-
this.contexts.set(contextTraceId, context);
|
|
21
|
-
TraceContext.instance.setTraceId(contextTraceId, {
|
|
22
|
-
method: request.method,
|
|
23
|
-
url: request.url
|
|
24
|
-
});
|
|
25
|
-
return context;
|
|
26
|
-
}
|
|
27
|
-
/**
|
|
28
|
-
* Update request context with response data
|
|
29
|
-
*/
|
|
30
|
-
static updateContext(traceId, response, error) {
|
|
31
|
-
const context = this.contexts.get(traceId);
|
|
32
|
-
if (!context) return;
|
|
33
|
-
const endTime = Date.now();
|
|
34
|
-
context.endTime = endTime;
|
|
35
|
-
context.duration = endTime - context.startTime;
|
|
36
|
-
if (response) context.response = response;
|
|
37
|
-
if (error) context.error = error;
|
|
38
|
-
return context;
|
|
39
|
-
}
|
|
40
|
-
/**
|
|
41
|
-
* Get request context by trace ID
|
|
42
|
-
*/
|
|
43
|
-
static getContext(traceId) {
|
|
44
|
-
return this.contexts.get(traceId);
|
|
45
|
-
}
|
|
46
|
-
/**
|
|
47
|
-
* Remove request context (cleanup)
|
|
48
|
-
*/
|
|
49
|
-
static removeContext(traceId) {
|
|
50
|
-
return this.contexts.delete(traceId);
|
|
51
|
-
}
|
|
52
|
-
/**
|
|
53
|
-
* Get all active contexts
|
|
54
|
-
*/
|
|
55
|
-
static getAllContexts() {
|
|
56
|
-
return Array.from(this.contexts.values());
|
|
57
|
-
}
|
|
58
|
-
/**
|
|
59
|
-
* Clear all contexts (useful for testing)
|
|
60
|
-
*/
|
|
61
|
-
static clearAll() {
|
|
62
|
-
this.contexts.clear();
|
|
63
|
-
}
|
|
64
|
-
/**
|
|
65
|
-
* Get context statistics
|
|
66
|
-
*/
|
|
67
|
-
static getStats() {
|
|
68
|
-
const contexts = Array.from(this.contexts.values());
|
|
69
|
-
const completedContexts = contexts.filter((ctx) => ctx.endTime);
|
|
70
|
-
const averageDuration = completedContexts.length > 0 ? completedContexts.reduce((sum, ctx) => sum + (ctx.duration || 0), 0) / completedContexts.length : 0;
|
|
71
|
-
return {
|
|
72
|
-
activeContexts: contexts.length,
|
|
73
|
-
averageDuration,
|
|
74
|
-
completedRequests: completedContexts.length
|
|
75
|
-
};
|
|
76
|
-
}
|
|
77
|
-
/**
|
|
78
|
-
* Cleanup old completed contexts (older than specified time)
|
|
79
|
-
*/
|
|
80
|
-
static cleanup(maxAgeMs = 3e5) {
|
|
81
|
-
const now = Date.now();
|
|
82
|
-
let cleaned = 0;
|
|
83
|
-
for (const [traceId, context] of this.contexts.entries()) if (context.endTime && now - context.endTime > maxAgeMs) {
|
|
84
|
-
this.contexts.delete(traceId);
|
|
85
|
-
cleaned++;
|
|
86
|
-
}
|
|
87
|
-
return cleaned;
|
|
88
|
-
}
|
|
89
|
-
};
|
|
90
|
-
|
|
91
|
-
//#endregion
|
|
92
|
-
export { KafkaTraceInterceptor, LOGIXIA_LOGGER_CONFIG, LOGIXIA_LOGGER_PREFIX, LogixiaLoggerModule, LogixiaLoggerService, RequestContextManager, TraceMiddleware, WebSocketTraceInterceptor };
|
|
93
|
-
//# sourceMappingURL=nest.mjs.map
|
|
4
|
+
export { KafkaTraceInterceptor, LOGIXIA_LOGGER_CONFIG, LOGIXIA_LOGGER_PREFIX, LogixiaLoggerModule, LogixiaLoggerService, TraceMiddleware, WebSocketTraceInterceptor };
|
package/dist/search.d.mts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import "./search-
|
|
1
|
+
import "./search-DN676Dnz.mjs";
|
package/dist/search.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
require('./search-
|
|
1
|
+
require('./search-DoZF3RZj.js');
|
package/dist/search.mjs
CHANGED
package/dist/testing.d.mts
CHANGED
package/dist/testing.d.ts
CHANGED
|
@@ -1,10 +1,14 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { createRequire } from "node:module";
|
|
2
2
|
import { EventEmitter } from "node:events";
|
|
3
3
|
import * as readline from "node:readline";
|
|
4
4
|
import * as fs from "node:fs";
|
|
5
5
|
import * as path from "node:path";
|
|
6
6
|
import { promisify } from "node:util";
|
|
7
7
|
|
|
8
|
+
//#region rolldown:runtime
|
|
9
|
+
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
10
|
+
|
|
11
|
+
//#endregion
|
|
8
12
|
//#region src/utils/internal-log.ts
|
|
9
13
|
/**
|
|
10
14
|
* Internal logging helpers for use within the logixia library itself.
|
|
@@ -77,6 +81,10 @@ var ConsoleTransport = class ConsoleTransport {
|
|
|
77
81
|
["brightwhite", "\x1B[97m"],
|
|
78
82
|
["reset", "\x1B[0m"]
|
|
79
83
|
]);
|
|
84
|
+
static #_2 = this.CONTROL_CHARS_RE = /[\x00-\x08\x0B-\x1F\x7F-\x9F]/g;
|
|
85
|
+
static sanitize(value) {
|
|
86
|
+
return value.replace(ConsoleTransport.CONTROL_CHARS_RE, "");
|
|
87
|
+
}
|
|
80
88
|
constructor(config = {}) {
|
|
81
89
|
this.config = config;
|
|
82
90
|
this.name = "console";
|
|
@@ -106,14 +114,14 @@ var ConsoleTransport = class ConsoleTransport {
|
|
|
106
114
|
const coloredLevel = this.colorize(level, this.getLevelColor(entry.level));
|
|
107
115
|
parts.push(coloredLevel);
|
|
108
116
|
if (entry.context) {
|
|
109
|
-
const context = `[${entry.context}]`;
|
|
117
|
+
const context = `[${ConsoleTransport.sanitize(entry.context)}]`;
|
|
110
118
|
parts.push(this.colorize(context, "cyan"));
|
|
111
119
|
}
|
|
112
120
|
if (entry.traceId) {
|
|
113
|
-
const traceId = `(${entry.traceId})`;
|
|
121
|
+
const traceId = `(${ConsoleTransport.sanitize(entry.traceId)})`;
|
|
114
122
|
parts.push(this.colorize(traceId, "magenta"));
|
|
115
123
|
}
|
|
116
|
-
parts.push(entry.message);
|
|
124
|
+
parts.push(ConsoleTransport.sanitize(entry.message));
|
|
117
125
|
if (entry.data && Object.keys(entry.data).length > 0) {
|
|
118
126
|
const data = JSON.stringify(entry.data);
|
|
119
127
|
parts.push(this.colorize(data, "blue"));
|
|
@@ -252,7 +260,7 @@ var DatabaseTransport = class {
|
|
|
252
260
|
}
|
|
253
261
|
async connectMongoDB() {
|
|
254
262
|
try {
|
|
255
|
-
const { MongoClient } = await import("
|
|
263
|
+
const { MongoClient } = await import("mongodb").catch(() => {
|
|
256
264
|
throw new Error("MongoDB driver not installed. Run: npm install mongodb");
|
|
257
265
|
});
|
|
258
266
|
this.connection = new MongoClient(this.config.connectionString || `mongodb://${this.config.host}:${this.config.port}/${this.config.database}`);
|
|
@@ -264,7 +272,7 @@ var DatabaseTransport = class {
|
|
|
264
272
|
}
|
|
265
273
|
async connectPostgreSQL() {
|
|
266
274
|
try {
|
|
267
|
-
const { Client } = await import("
|
|
275
|
+
const { Client } = await import("pg").catch(() => {
|
|
268
276
|
throw new Error("PostgreSQL driver not installed. Run: npm install pg @types/pg");
|
|
269
277
|
});
|
|
270
278
|
const config = {
|
|
@@ -285,7 +293,7 @@ var DatabaseTransport = class {
|
|
|
285
293
|
}
|
|
286
294
|
async connectMySQL() {
|
|
287
295
|
try {
|
|
288
|
-
const mysql = await import("
|
|
296
|
+
const mysql = await import("mysql2/promise").catch(() => {
|
|
289
297
|
throw new Error("MySQL driver not installed. Run: npm install mysql2");
|
|
290
298
|
});
|
|
291
299
|
const config = {
|
|
@@ -304,10 +312,12 @@ var DatabaseTransport = class {
|
|
|
304
312
|
}
|
|
305
313
|
async connectSQLite() {
|
|
306
314
|
try {
|
|
307
|
-
const
|
|
315
|
+
const sqlite3ModuleName = "sqlite3";
|
|
316
|
+
const sqliteModuleName = "sqlite";
|
|
317
|
+
const sqlite3 = await import(sqlite3ModuleName).catch(() => {
|
|
308
318
|
throw new Error("SQLite driver not installed. Run: npm install sqlite3 sqlite");
|
|
309
319
|
});
|
|
310
|
-
const { open } = await import(
|
|
320
|
+
const { open } = await import(sqliteModuleName).catch(() => {
|
|
311
321
|
throw new Error("SQLite driver not installed. Run: npm install sqlite3 sqlite");
|
|
312
322
|
});
|
|
313
323
|
this.connection = await open({
|
|
@@ -1989,5 +1999,5 @@ var TransportManager = class extends EventEmitter {
|
|
|
1989
1999
|
};
|
|
1990
2000
|
|
|
1991
2001
|
//#endregion
|
|
1992
|
-
export { FileTransport as a, DatabaseTransport as c, internalLog as d, internalWarn as f, GoogleAnalyticsTransport as i, ConsoleTransport as l, SegmentTransport as n, DataDogTransport as o, MixpanelTransport as r, AnalyticsTransport as s, TransportManager as t, internalError as u };
|
|
1993
|
-
//# sourceMappingURL=transport.manager-
|
|
2002
|
+
export { FileTransport as a, DatabaseTransport as c, internalLog as d, internalWarn as f, GoogleAnalyticsTransport as i, ConsoleTransport as l, SegmentTransport as n, DataDogTransport as o, __require as p, MixpanelTransport as r, AnalyticsTransport as s, TransportManager as t, internalError as u };
|
|
2003
|
+
//# sourceMappingURL=transport.manager-D3U03fJg.mjs.map
|