logixia 2.0.6 → 2.0.7

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 (128) hide show
  1. package/dist/{async-context-2mbUKhcl.mjs → async-context-COuvmwsS.mjs} +2 -2
  2. package/dist/{async-context-2mbUKhcl.mjs.map → async-context-COuvmwsS.mjs.map} +1 -1
  3. package/dist/{async-context-DUFMDYAr.js → async-context-Dv0bmPC-.js} +3 -3
  4. package/dist/{async-context-DUFMDYAr.js.map → async-context-Dv0bmPC-.js.map} +1 -1
  5. package/dist/{azure-monitor.transport-C1RWAumT.mjs → azure-monitor.transport-Coz5Gesu.mjs} +5 -5
  6. package/dist/{azure-monitor.transport-C1RWAumT.mjs.map → azure-monitor.transport-Coz5Gesu.mjs.map} +1 -1
  7. package/dist/{azure-monitor.transport-Bu4S2I2q.js → azure-monitor.transport-D6ryi8rA.js} +5 -5
  8. package/dist/{azure-monitor.transport-Bu4S2I2q.js.map → azure-monitor.transport-D6ryi8rA.js.map} +1 -1
  9. package/dist/azure.js +1 -1
  10. package/dist/azure.mjs +1 -1
  11. package/dist/{batch-buffer-C7Am4Mw-.js → batch-buffer-CFzKnuNZ.js} +3 -3
  12. package/dist/{batch-buffer-C7Am4Mw-.js.map → batch-buffer-CFzKnuNZ.js.map} +1 -1
  13. package/dist/{batch-buffer-BvXLDPlV.mjs → batch-buffer-CQUWDMYq.mjs} +3 -3
  14. package/dist/{batch-buffer-BvXLDPlV.mjs.map → batch-buffer-CQUWDMYq.mjs.map} +1 -1
  15. package/dist/browser.js +25 -1
  16. package/dist/browser.js.map +1 -1
  17. package/dist/browser.mjs +25 -1
  18. package/dist/browser.mjs.map +1 -1
  19. package/dist/{builder-DhNhvOkt.mjs → builder-C_TgxEOW.mjs} +7 -7
  20. package/dist/builder-C_TgxEOW.mjs.map +1 -0
  21. package/dist/{builder-yFvJrz7o.js → builder-CzmM_4Ub.js} +13 -13
  22. package/dist/builder-CzmM_4Ub.js.map +1 -0
  23. package/dist/cloudwatch.js +1 -1
  24. package/dist/cloudwatch.mjs +1 -1
  25. package/dist/{cloudwatch.transport-DZqF2xZO.mjs → cloudwatch.transport-Cr1aeTGj.mjs} +6 -6
  26. package/dist/{cloudwatch.transport-DZqF2xZO.mjs.map → cloudwatch.transport-Cr1aeTGj.mjs.map} +1 -1
  27. package/dist/{cloudwatch.transport-Ch1Uae-0.js → cloudwatch.transport-D4G5xYfG.js} +6 -6
  28. package/dist/{cloudwatch.transport-Ch1Uae-0.js.map → cloudwatch.transport-D4G5xYfG.js.map} +1 -1
  29. package/dist/correlation.d.mts +6 -0
  30. package/dist/correlation.d.mts.map +1 -1
  31. package/dist/correlation.d.ts +6 -0
  32. package/dist/correlation.d.ts.map +1 -1
  33. package/dist/correlation.js +4 -2
  34. package/dist/correlation.js.map +1 -1
  35. package/dist/correlation.mjs +4 -2
  36. package/dist/correlation.mjs.map +1 -1
  37. package/dist/{entry-fields-BSLkzw18.js → entry-fields-CVwoQplO.js} +3 -3
  38. package/dist/{entry-fields-BSLkzw18.js.map → entry-fields-CVwoQplO.js.map} +1 -1
  39. package/dist/{entry-fields-J1OBi24o.mjs → entry-fields-DNTKQxoU.mjs} +2 -2
  40. package/dist/{entry-fields-J1OBi24o.mjs.map → entry-fields-DNTKQxoU.mjs.map} +1 -1
  41. package/dist/gcp.js +1 -1
  42. package/dist/gcp.mjs +1 -1
  43. package/dist/{gcp.transport-Dy2Lf8FI.js → gcp.transport-CVuRpchl.js} +6 -6
  44. package/dist/{gcp.transport-Dy2Lf8FI.js.map → gcp.transport-CVuRpchl.js.map} +1 -1
  45. package/dist/{gcp.transport-DVCmnA3b.mjs → gcp.transport-LLK2bw2-.mjs} +6 -6
  46. package/dist/{gcp.transport-DVCmnA3b.mjs.map → gcp.transport-LLK2bw2-.mjs.map} +1 -1
  47. package/dist/{index-BSTtFcQ6.d.mts → index-BAkPHp5D.d.mts} +9 -1
  48. package/dist/index-BAkPHp5D.d.mts.map +1 -0
  49. package/dist/{index-CFDGkI8n.d.ts → index-e7LowmAu.d.ts} +9 -1
  50. package/dist/index-e7LowmAu.d.ts.map +1 -0
  51. package/dist/index.d.mts +3 -3
  52. package/dist/index.d.ts +3 -3
  53. package/dist/index.js +16 -16
  54. package/dist/index.js.map +1 -1
  55. package/dist/index.mjs +7 -7
  56. package/dist/internal-log-Cy5nF1ZL.mjs +63 -0
  57. package/dist/internal-log-Cy5nF1ZL.mjs.map +1 -0
  58. package/dist/internal-log-DwqTjhpb.js +80 -0
  59. package/dist/internal-log-DwqTjhpb.js.map +1 -0
  60. package/dist/{logitron-logger-D_MYYrQt.d.ts → logitron-logger-Qh3y9-WH.d.ts} +2 -2
  61. package/dist/{logitron-logger-D_MYYrQt.d.ts.map → logitron-logger-Qh3y9-WH.d.ts.map} +1 -1
  62. package/dist/{logitron-logger-D22Yb61K.d.mts → logitron-logger-sYuk8fOb.d.mts} +2 -2
  63. package/dist/{logitron-logger-D22Yb61K.d.mts.map → logitron-logger-sYuk8fOb.d.mts.map} +1 -1
  64. package/dist/middleware.d.mts +1 -1
  65. package/dist/middleware.d.ts +1 -1
  66. package/dist/middleware.js +8 -8
  67. package/dist/middleware.js.map +1 -1
  68. package/dist/middleware.mjs +3 -3
  69. package/dist/nest.d.mts +12 -3
  70. package/dist/nest.d.mts.map +1 -1
  71. package/dist/nest.d.ts +12 -3
  72. package/dist/nest.d.ts.map +1 -1
  73. package/dist/nest.js +128 -20
  74. package/dist/nest.js.map +1 -1
  75. package/dist/nest.mjs +128 -20
  76. package/dist/nest.mjs.map +1 -1
  77. package/dist/{otel-DyeH6DVR.js → otel-ChnVYRLA.js} +5 -5
  78. package/dist/{otel-DyeH6DVR.js.map → otel-ChnVYRLA.js.map} +1 -1
  79. package/dist/{otel-Dt5riXuE.mjs → otel-DOuwGPCd.mjs} +5 -5
  80. package/dist/{otel-Dt5riXuE.mjs.map → otel-DOuwGPCd.mjs.map} +1 -1
  81. package/dist/{safe-stringify-B5p5ktFe.mjs → safe-stringify--7gbe95n.mjs} +2 -2
  82. package/dist/{safe-stringify-B5p5ktFe.mjs.map → safe-stringify--7gbe95n.mjs.map} +1 -1
  83. package/dist/{safe-stringify-J3sh-7YM.js → safe-stringify-CN7icp8S.js} +5 -5
  84. package/dist/{safe-stringify-J3sh-7YM.js.map → safe-stringify-CN7icp8S.js.map} +1 -1
  85. package/dist/{search-DA3ft3X5.d.mts → search-D-8HJADE.d.mts} +2 -2
  86. package/dist/{search-DA3ft3X5.d.mts.map → search-D-8HJADE.d.mts.map} +1 -1
  87. package/dist/{search-DEl3Pe47.d.ts → search-DPwTKPve.d.ts} +2 -2
  88. package/dist/{search-DEl3Pe47.d.ts.map → search-DPwTKPve.d.ts.map} +1 -1
  89. package/dist/search.d.mts +1 -1
  90. package/dist/search.d.ts +1 -1
  91. package/dist/{secret-config-CmK2wVkr.js → secret-config-BvFl2dC8.js} +7 -8
  92. package/dist/{secret-config-CmK2wVkr.js.map → secret-config-BvFl2dC8.js.map} +1 -1
  93. package/dist/{secret-config-Dhb6pqTU.mjs → secret-config-ByGq7kJd.mjs} +2 -3
  94. package/dist/{secret-config-Dhb6pqTU.mjs.map → secret-config-ByGq7kJd.mjs.map} +1 -1
  95. package/dist/sensitive-names-CHMowujD.js +276 -0
  96. package/dist/sensitive-names-CHMowujD.js.map +1 -0
  97. package/dist/sensitive-names-o__1PUUR.mjs +217 -0
  98. package/dist/sensitive-names-o__1PUUR.mjs.map +1 -0
  99. package/dist/{slack.transport-BTEwsREY.mjs → slack.transport-CSj1j0_X.mjs} +6 -6
  100. package/dist/{slack.transport-BTEwsREY.mjs.map → slack.transport-CSj1j0_X.mjs.map} +1 -1
  101. package/dist/{slack.transport-UbYvOdKx.js → slack.transport-zLQ9MGxS.js} +6 -6
  102. package/dist/{slack.transport-UbYvOdKx.js.map → slack.transport-zLQ9MGxS.js.map} +1 -1
  103. package/dist/testing.d.mts +1 -1
  104. package/dist/testing.d.ts +1 -1
  105. package/dist/transports.d.mts +1 -1
  106. package/dist/transports.d.ts +1 -1
  107. package/dist/transports.js +6 -6
  108. package/dist/transports.mjs +6 -6
  109. package/dist/worker-entry.js +25 -1
  110. package/dist/worker.js +1 -1
  111. package/dist/worker.mjs +1 -1
  112. package/dist/{worker.transport-BmmOKb1-.mjs → worker.transport-D78xhNhB.mjs} +3 -3
  113. package/dist/{worker.transport-BmmOKb1-.mjs.map → worker.transport-D78xhNhB.mjs.map} +1 -1
  114. package/dist/{worker.transport-DxxbqQCG.js → worker.transport-DQDv1nAJ.js} +3 -3
  115. package/dist/{worker.transport-DxxbqQCG.js.map → worker.transport-DQDv1nAJ.js.map} +1 -1
  116. package/package.json +1 -1
  117. package/dist/builder-DhNhvOkt.mjs.map +0 -1
  118. package/dist/builder-yFvJrz7o.js.map +0 -1
  119. package/dist/index-BSTtFcQ6.d.mts.map +0 -1
  120. package/dist/index-CFDGkI8n.d.ts.map +0 -1
  121. package/dist/internal-log-Bg4V1cPg.mjs +0 -170
  122. package/dist/internal-log-Bg4V1cPg.mjs.map +0 -1
  123. package/dist/internal-log-By4Govmu.js +0 -223
  124. package/dist/internal-log-By4Govmu.js.map +0 -1
  125. package/dist/own-property-BWkibepN.js +0 -40
  126. package/dist/own-property-BWkibepN.js.map +0 -1
  127. package/dist/own-property-CjFw9qwZ.mjs +0 -29
  128. package/dist/own-property-CjFw9qwZ.mjs.map +0 -1
@@ -1,4 +1,4 @@
1
- import { C as LogixiaLoggerInstance, L as LogixiaPlugin, b as LoggerConfig, p as ILoggerDefault, w as NamespaceLevels, x as LoggerWithLevels, y as LogLevelString } from "./index-BSTtFcQ6.mjs";
1
+ import { C as LogixiaLoggerInstance, L as LogixiaPlugin, b as LoggerConfig, p as ILoggerDefault, w as NamespaceLevels, x as LoggerWithLevels, y as LogLevelString } from "./index-BAkPHp5D.mjs";
2
2
  /**
3
3
  * The logixia logger. Create instances with {@link createLogger} so that custom
4
4
  * levels from `levelOptions.levels` also become methods.
@@ -275,4 +275,4 @@ declare class LogixiaLogger<TConfig extends LoggerConfig<Record<string, number>>
275
275
  */
276
276
  declare function createLogger<T extends LoggerConfig<Record<string, number>>>(config: T, context?: string): LoggerWithLevels<T>;
277
277
  export { createLogger as n, LogixiaLogger as t };
278
- //# sourceMappingURL=logitron-logger-D22Yb61K.d.mts.map
278
+ //# sourceMappingURL=logitron-logger-sYuk8fOb.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"logitron-logger-D22Yb61K.d.mts","names":[],"sources":["../src/core/logitron-logger.ts"],"mappings":";;;;;;;;;;;;;;cAyLa,cACX,gBAAgB,aAAa,0BAA0B,yBAC5C;GAEV;UAEO;UACA;UACA;UACA;UACA;UACA;;mBAGS;;UAIT;;UAEA;;UAEA;;mBAES;;UAET;;UAEA;;UAEA;;;;;UAKA;;UAEA;;UAEA;;UAEA;;mBAES;;mBAEA;;mBAEA;;UAET;EAEI,YAAA,QAAQ,SAAS,kBAAkB,SAAS,cAAc;UA4G9D;UAiBA;;;;;UAsBA;;;;;;EA2HF,MAAM,yBAAyB,OAAO,OAAO,0BAA0B;;EAYvE,KAAK,iBAAiB,OAAO,0BAA0B;;EAKvD,KAAK,iBAAiB,OAAO,0BAA0B;;EAKvD,MAAM,iBAAiB,OAAO,0BAA0B;;EAKxD,MAAM,iBAAiB,OAAO,0BAA0B;;EAKxD,QAAQ,iBAAiB,OAAO,0BAA0B;;;;;;EAS1D,SAAS,eAAe,iBAAiB,OAAO,0BAA0B;;EAOhF,KAAK;;;;;;;;;;;;;EAgBC,QAAQ,gBAAgB;EAmBxB,UAAU,GAAG,eAAe,UAAU,QAAQ,KAAK,QAAQ;;;;;;;;;;;;EAyBjE,SAAS,OAAO;;;;;;EAuBhB,YAAY;UAIJ;;;;;UAQA;;;;;;;;;;;;;;;;;;;EAkCR,mBAAmB,QAAQ;;EAS3B,qBAAqB,QAAQ;;EAO7B,sBAAsB;UAId;;EAMR,WAAW;;EAKX;;EAOA,YAAY;;EASZ,aAAa;;EASb,eAAe;;EASf,iBAAiB;;EAmBjB;;EAQA;;EAMA;;EAMA,mBAAmB,qBAAqB;;EAMxC,mBAAmB;EAMnB;;EAMA;;;;;;;;;;;;;EAkBA,MAAM,iBAAiB,OAAO,0BAA0B;;;;;;;;;;;;EA0BxD,IAAI,QAAQ;;;;;EASZ,MAAM;;EAQA,SAAS;;EAKT,eAAe;IAAU;IAAkB,SAAS;;;;;;;;;;;;;;;;EAqBpD,SAAS;UAsBD;;;;;UA8GN;;;;;;;;;;;UAgBA;UAwCA;UAgDA;;;;;;;;UAcA;;;UAuBM;;;;;;;;;;;;;;;;;;iBA+BA,aAAa,UAAU,aAAa,yBAClD,QAAQ,GACR,mBACC,iBAAiB"}
1
+ {"version":3,"file":"logitron-logger-sYuk8fOb.d.mts","names":[],"sources":["../src/core/logitron-logger.ts"],"mappings":";;;;;;;;;;;;;;cAyLa,cACX,gBAAgB,aAAa,0BAA0B,yBAC5C;GAEV;UAEO;UACA;UACA;UACA;UACA;UACA;;mBAGS;;UAIT;;UAEA;;UAEA;;mBAES;;UAET;;UAEA;;UAEA;;;;;UAKA;;UAEA;;UAEA;;UAEA;;mBAES;;mBAEA;;mBAEA;;UAET;EAEI,YAAA,QAAQ,SAAS,kBAAkB,SAAS,cAAc;UA4G9D;UAiBA;;;;;UAsBA;;;;;;EA2HF,MAAM,yBAAyB,OAAO,OAAO,0BAA0B;;EAYvE,KAAK,iBAAiB,OAAO,0BAA0B;;EAKvD,KAAK,iBAAiB,OAAO,0BAA0B;;EAKvD,MAAM,iBAAiB,OAAO,0BAA0B;;EAKxD,MAAM,iBAAiB,OAAO,0BAA0B;;EAKxD,QAAQ,iBAAiB,OAAO,0BAA0B;;;;;;EAS1D,SAAS,eAAe,iBAAiB,OAAO,0BAA0B;;EAOhF,KAAK;;;;;;;;;;;;;EAgBC,QAAQ,gBAAgB;EAmBxB,UAAU,GAAG,eAAe,UAAU,QAAQ,KAAK,QAAQ;;;;;;;;;;;;EAyBjE,SAAS,OAAO;;;;;;EAuBhB,YAAY;UAIJ;;;;;UAQA;;;;;;;;;;;;;;;;;;;EAkCR,mBAAmB,QAAQ;;EAS3B,qBAAqB,QAAQ;;EAO7B,sBAAsB;UAId;;EAMR,WAAW;;EAKX;;EAOA,YAAY;;EASZ,aAAa;;EASb,eAAe;;EASf,iBAAiB;;EAmBjB;;EAQA;;EAMA;;EAMA,mBAAmB,qBAAqB;;EAMxC,mBAAmB;EAMnB;;EAMA;;;;;;;;;;;;;EAkBA,MAAM,iBAAiB,OAAO,0BAA0B;;;;;;;;;;;;EA0BxD,IAAI,QAAQ;;;;;EASZ,MAAM;;EAQA,SAAS;;EAKT,eAAe;IAAU;IAAkB,SAAS;;;;;;;;;;;;;;;;EAqBpD,SAAS;UAsBD;;;;;UA8GN;;;;;;;;;;;UAgBA;UAwCA;UAgDA;;;;;;;;UAcA;;;UAuBM;;;;;;;;;;;;;;;;;;iBA+BA,aAAa,UAAU,aAAa,yBAClD,QAAQ,GACR,mBACC,iBAAiB"}
@@ -1,5 +1,5 @@
1
1
  import { n as HttpResponseShape, t as HttpRequestShape } from "./http-shapes-BnBkJcid.mjs";
2
- import { u as IBaseLogger } from "./index-BSTtFcQ6.mjs";
2
+ import { u as IBaseLogger } from "./index-BAkPHp5D.mjs";
3
3
  interface HttpLoggerOptions {
4
4
  /**
5
5
  * Skip logging for a request. Called before any I/O.
@@ -1,5 +1,5 @@
1
1
  import { n as HttpResponseShape, t as HttpRequestShape } from "./http-shapes-BnBkJcid.js";
2
- import { u as IBaseLogger } from "./index-CFDGkI8n.js";
2
+ import { u as IBaseLogger } from "./index-e7LowmAu.js";
3
3
  interface HttpLoggerOptions {
4
4
  /**
5
5
  * Skip logging for a request. Called before any I/O.
@@ -1,13 +1,13 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_own_property = require("./own-property-BWkibepN.js");
2
+ const require_sensitive_names = require("./sensitive-names-CHMowujD.js");
3
3
  const require_request_trace = require("./request-trace-ByujsUZk.js");
4
- const require_internal_log = require("./internal-log-By4Govmu.js");
5
- const require_safe_stringify = require("./safe-stringify-J3sh-7YM.js");
4
+ const require_internal_log = require("./internal-log-DwqTjhpb.js");
5
+ const require_safe_stringify = require("./safe-stringify-CN7icp8S.js");
6
6
  // src/middleware/http-logger.ts
7
7
  function sanitizeHeaders(headers, redactSet) {
8
8
  if (!headers) return {};
9
9
  const out = {};
10
- for (const [k, v] of Object.entries(headers)) require_own_property.assignOwn(out, k, redactSet.has(k.toLowerCase()) ? "[REDACTED]" : v);
10
+ for (const [k, v] of Object.entries(headers)) require_sensitive_names.assignOwn(out, k, redactSet.has(k.toLowerCase()) ? "[REDACTED]" : v);
11
11
  return out;
12
12
  }
13
13
  /** Fire-and-forget a logger call; a failing log must never become an unhandled rejection. */
@@ -16,8 +16,8 @@ function fire(result) {
16
16
  }
17
17
  function resolveNameSets(options) {
18
18
  return {
19
- headers: require_internal_log.buildNameSet(require_internal_log.DEFAULT_REDACT_HEADERS, options.redactHeaders),
20
- queryParams: require_internal_log.buildNameSet(require_internal_log.DEFAULT_REDACT_QUERY_PARAMS, options.redactQueryParams)
19
+ headers: require_sensitive_names.buildNameSet(require_sensitive_names.DEFAULT_REDACT_HEADERS, options.redactHeaders),
20
+ queryParams: require_sensitive_names.buildNameSet(require_sensitive_names.DEFAULT_REDACT_QUERY_PARAMS, options.redactQueryParams)
21
21
  };
22
22
  }
23
23
  function buildBaseFields(req, traceId, options, { headers: redactSet, queryParams: paramSet }) {
@@ -25,7 +25,7 @@ function buildBaseFields(req, traceId, options, { headers: redactSet, queryParam
25
25
  const fields = {
26
26
  traceId,
27
27
  method: ((_req$method = req.method) === null || _req$method === void 0 ? void 0 : _req$method.toUpperCase()) ?? "UNKNOWN",
28
- url: require_internal_log.redactUrlQuery(req.url ?? "/", paramSet),
28
+ url: require_sensitive_names.redactUrlQuery(req.url ?? "/", paramSet),
29
29
  ip: req.ip ?? ((_req$socket = req.socket) === null || _req$socket === void 0 ? void 0 : _req$socket.remoteAddress) ?? "unknown",
30
30
  headers: sanitizeHeaders(req.headers, redactSet)
31
31
  };
@@ -193,7 +193,7 @@ function pruneValue(value, budget, depth, ancestors) {
193
193
  break;
194
194
  }
195
195
  budget.left -= k.length;
196
- require_own_property.assignOwn(record, k, pruneValue(v, budget, depth + 1, ancestors));
196
+ require_sensitive_names.assignOwn(record, k, pruneValue(v, budget, depth + 1, ancestors));
197
197
  }
198
198
  return record;
199
199
  } catch {
@@ -1 +1 @@
1
- {"version":3,"file":"middleware.js","names":["internalError","buildNameSet","DEFAULT_REDACT_HEADERS","DEFAULT_REDACT_QUERY_PARAMS","sanitizeUrl","resolveTraceHeaders","resolveRequestTraceId","stringifyForLog"],"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\nimport type { IBaseLogger } from '../types';\nimport type { HttpRequestShape, HttpResponseShape } from '../types/http-shapes';\nimport { internalError } from '../utils/internal-log';\nimport { assignOwn } from '../utils/own-property';\nimport { resolveRequestTraceId, resolveTraceHeaders } from '../utils/request-trace';\nimport { stringifyForLog } from '../utils/safe-stringify';\nimport {\n buildNameSet,\n DEFAULT_REDACT_HEADERS,\n DEFAULT_REDACT_QUERY_PARAMS,\n redactUrlQuery as sanitizeUrl,\n} from '../utils/sensitive-names';\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 * Header name, or list of names tried in order, to read the trace ID from.\n * Default: the library-wide list (`DEFAULT_TRACE_HEADERS`: traceparent,\n * x-trace-id, x-request-id, x-correlation-id, trace-id).\n * If none is present, `request.id` is used when it is not a framework counter,\n * otherwise a UUID is generated and shared with the logixia context helpers.\n */\n traceIdHeader?: string | readonly string[];\n /**\n * Additional headers to redact from logged output. Merged with the defaults\n * (authorization, cookie, set-cookie, x-api-key, proxy-authorization,\n * x-auth-token, x-access-token, x-csrf-token, x-amz-security-token).\n */\n redactHeaders?: string[];\n /**\n * Additional query-string parameter names whose values are redacted from the\n * logged URL. Merged with the defaults (token, access_token, refresh_token,\n * code, password, secret, api_key, apikey, key, signature, sig, auth).\n */\n redactQueryParams?: 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 type IncomingRequest = HttpRequestShape;\nexport type OutgoingResponse = HttpResponseShape;\n\n// ── Helpers ───────────────────────────────────────────────────────────────────\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 assignOwn(out, k, redactSet.has(k.toLowerCase()) ? '[REDACTED]' : v);\n }\n return out;\n}\n\n/** Fire-and-forget a logger call; a failing log must never become an unhandled rejection. */\nfunction fire(result: unknown): void {\n if (result && typeof (result as Promise<unknown>).catch === 'function') {\n (result as Promise<unknown>).catch((error: unknown) =>\n internalError('http-logger: log call failed', error)\n );\n }\n}\n\ninterface NameSets {\n headers: Set<string>;\n queryParams: Set<string>;\n}\n\nfunction resolveNameSets(options: HttpLoggerOptions): NameSets {\n return {\n headers: buildNameSet(DEFAULT_REDACT_HEADERS, options.redactHeaders),\n queryParams: buildNameSet(DEFAULT_REDACT_QUERY_PARAMS, options.redactQueryParams),\n };\n}\n\nfunction buildBaseFields(\n req: IncomingRequest,\n traceId: string,\n options: HttpLoggerOptions,\n { headers: redactSet, queryParams: paramSet }: NameSets\n): Record<string, unknown> {\n const fields: Record<string, unknown> = {\n traceId,\n method: req.method?.toUpperCase() ?? 'UNKNOWN',\n url: sanitizeUrl(req.url ?? '/', paramSet),\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,\n requestLevel = 'debug',\n responseLevel = 'info',\n errorLevel = 'error',\n slowRequestThresholdMs = 1000,\n } = options;\n const nameSets = resolveNameSets(options);\n const traceHeaders = resolveTraceHeaders(traceIdHeader);\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 = resolveRequestTraceId(req, traceHeaders);\n const startMs = Date.now();\n const baseFields = buildBaseFields(req, traceId, options, nameSets);\n\n // Log request start\n if (requestLevel !== 'silent') {\n fire(\n logger.logLevel(requestLevel, 'request started', {\n ...baseFields,\n ...(logBody && req.body ? { body: truncateBody(req.body, bodyMaxBytes) } : {}),\n })\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 //\n // BOTH 'finish' and 'close' fire on a normal response, so guard against\n // logging the completion twice (which would duplicate the completed entry and\n // the slow-request warning).\n let completed = false;\n const onFinish = (): void => {\n if (completed) return;\n completed = true;\n\n const duration = Date.now() - startMs;\n const status = res.statusCode ?? 0;\n const level = status >= 500 ? errorLevel : responseLevel;\n\n fire(\n logger.logLevel(level, 'request completed', {\n ...baseFields,\n statusCode: status,\n duration,\n })\n );\n\n if (duration > slowRequestThresholdMs) {\n fire(\n logger.warn('slow request detected', {\n ...baseFields,\n statusCode: status,\n duration,\n threshold: slowRequestThresholdMs,\n })\n );\n }\n };\n\n res.once?.('finish', onFinish);\n // Fallback: also covers a client that disconnects before 'finish' fires. The\n // `completed` guard ensures a normal finish+close pair logs only once.\n res.once?.('close', onFinish);\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,\n requestLevel = 'debug',\n responseLevel = 'info',\n errorLevel = 'error',\n slowRequestThresholdMs = 1000,\n } = options;\n const nameSets = resolveNameSets(options);\n const traceHeaders = resolveTraceHeaders(traceIdHeader);\n\n function logixiaFastifyPlugin(fastify: FastifyInstance, _opts: unknown, done: () => void): void {\n fastify.addHook('onRequest', (request: unknown, _reply: unknown, hookDone: () => void) => {\n const req = request as IncomingRequest & { _logixiaStart?: number };\n if (skip?.(req)) {\n hookDone();\n return;\n }\n\n const traceId = resolveRequestTraceId(req, traceHeaders);\n req._logixiaStart = Date.now();\n\n if (requestLevel !== 'silent') {\n fire(\n logger.logLevel(\n requestLevel,\n 'request started',\n buildBaseFields(req, traceId, options, nameSets)\n )\n );\n }\n hookDone();\n });\n\n fastify.addHook('onResponse', (request: unknown, reply: unknown, hookDone: () => void) => {\n const req = request as IncomingRequest & { _logixiaStart?: number };\n if (req._logixiaStart === undefined) {\n hookDone();\n return;\n }\n\n const rep = reply as { statusCode?: number };\n const duration = Date.now() - req._logixiaStart;\n const status = rep.statusCode ?? 0;\n const traceId = resolveRequestTraceId(req, traceHeaders);\n const level = status >= 500 ? errorLevel : responseLevel;\n const baseFields = buildBaseFields(req, traceId, options, nameSets);\n\n fire(\n logger.logLevel(level, 'request completed', {\n ...baseFields,\n statusCode: status,\n duration,\n })\n );\n\n if (duration > slowRequestThresholdMs) {\n fire(\n logger.warn('slow request detected', {\n traceId,\n url: baseFields.url,\n method: req.method,\n duration,\n threshold: slowRequestThresholdMs,\n })\n );\n }\n\n hookDone();\n });\n\n done();\n }\n\n return Object.assign(logixiaFastifyPlugin, {\n [Symbol.for('skip-override')]: true,\n [Symbol.for('fastify.display-name')]: 'logixia',\n });\n}\n\n// ── Internal helpers ──────────────────────────────────────────────────────────\n\n/**\n * Bound the captured body without turning it into a string, so the logger's\n * path-based redaction still sees the original keys. Oversized structures are\n * pruned (extra keys/items dropped, long strings cut) rather than serialized.\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 = stringifyForLog(body);\n if (str.length <= maxBytes) return body;\n return pruneValue(body, { left: maxBytes }, 0, new Set());\n }\n return body;\n}\n\nconst TRUNCATED = '…[truncated]';\nconst MAX_PRUNE_DEPTH = 8;\n\nfunction pruneValue(\n value: unknown,\n budget: { left: number },\n depth: number,\n ancestors: Set<object>\n): unknown {\n if (typeof value === 'string') {\n const cut = value.slice(0, Math.max(0, budget.left));\n budget.left -= cut.length;\n return cut.length < value.length ? cut + TRUNCATED : cut;\n }\n if (value === null || typeof value !== 'object') {\n budget.left -= 8;\n return value;\n }\n if (value instanceof Date) {\n budget.left -= 24;\n return Number.isNaN(value.getTime()) ? 'Invalid Date' : value.toISOString();\n }\n if (value instanceof ArrayBuffer || ArrayBuffer.isView(value)) {\n budget.left -= 16;\n return `[Buffer ${value.byteLength} bytes]`;\n }\n if (value instanceof Error) return value;\n if (ancestors.has(value) || depth >= MAX_PRUNE_DEPTH) return TRUNCATED;\n ancestors.add(value);\n try {\n if (Array.isArray(value) || value instanceof Set || value instanceof Map) {\n const items: unknown[] = [];\n for (const item of value instanceof Map ? value.entries() : value) {\n if (budget.left <= 0) {\n items.push(TRUNCATED);\n break;\n }\n items.push(pruneValue(item, budget, depth + 1, ancestors));\n }\n return items;\n }\n const toJSON = (value as { toJSON?: unknown }).toJSON;\n if (typeof toJSON === 'function') {\n const json: unknown = toJSON.call(value);\n if (json !== value) return pruneValue(json, budget, depth + 1, ancestors);\n }\n const record: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(value)) {\n if (budget.left <= 0) {\n record['…'] = TRUNCATED;\n break;\n }\n budget.left -= k.length;\n assignOwn(record, k, pruneValue(v, budget, depth + 1, ancestors));\n }\n return record;\n } catch {\n return TRUNCATED;\n } finally {\n ancestors.delete(value);\n }\n}\n"],"mappings":";;;;;;AAoGA,SAAS,gBACP,SACA,WACyB;CACzB,IAAI,CAAC,SAAS,OAAO,CAAC;CACtB,MAAM,MAA+B,CAAC;CACtC,KAAK,MAAM,CAAC,GAAG,MAAM,OAAO,QAAQ,OAAO,GACzC,qBAAA,UAAU,KAAK,GAAG,UAAU,IAAI,EAAE,YAAY,CAAC,IAAI,eAAe,CAAC;CAErE,OAAO;AACT;;AAGA,SAAS,KAAK,QAAuB;CACnC,IAAI,UAAU,OAAQ,OAA4B,UAAU,YAC1D,OAA6B,OAAO,UAClCA,qBAAAA,cAAc,gCAAgC,KAAK,CACrD;AAEJ;AAOA,SAAS,gBAAgB,SAAsC;CAC7D,OAAO;EACL,SAASC,qBAAAA,aAAaC,qBAAAA,wBAAwB,QAAQ,aAAa;EACnE,aAAaD,qBAAAA,aAAaE,qBAAAA,6BAA6B,QAAQ,iBAAiB;CAClF;AACF;AAEA,SAAS,gBACP,KACA,SACA,SACA,EAAE,SAAS,WAAW,aAAa,YACV;;CACzB,MAAM,SAAkC;EACtC;EACA,UAAA,cAAQ,IAAI,YAAA,QAAA,gBAAA,KAAA,IAAA,KAAA,IAAA,YAAQ,YAAY,MAAK;EACrC,KAAKC,qBAAAA,eAAY,IAAI,OAAO,KAAK,QAAQ;EACzC,IAAI,IAAI,QAAA,cAAM,IAAI,YAAA,QAAA,gBAAA,KAAA,IAAA,KAAA,IAAA,YAAQ,kBAAiB;EAC3C,SAAS,gBAAgB,IAAI,SAAS,SAAS;CACjD;CAEA,IAAI,QAAQ,aACV,OAAO,OAAO,QAAQ,QAAQ,YAAY,GAAG,CAAC;CAGhD,OAAO;AACT;;;;AAOA,SAAgB,wBACd,QACA,UAA6B,CAAC,GAC2C;CACzE,MAAM,EACJ,MACA,SACA,cACA,eACA,eAAe,SACf,gBAAgB,QAChB,aAAa,SACb,yBAAyB,QACvB;CACJ,MAAM,WAAW,gBAAgB,OAAO;CACxC,MAAM,eAAeC,sBAAAA,oBAAoB,aAAa;CAEtD,OAAO,SAAS,sBACd,KACA,KACA,MACM;;EACN,IAAA,SAAA,QAAA,SAAA,KAAA,IAAA,KAAA,IAAI,KAAO,GAAG,GAAG;GACf,KAAK;GACL;EACF;EAEA,MAAM,UAAUC,sBAAAA,sBAAsB,KAAK,YAAY;EACvD,MAAM,UAAU,KAAK,IAAI;EACzB,MAAM,aAAa,gBAAgB,KAAK,SAAS,SAAS,QAAQ;EAGlE,IAAI,iBAAiB,UACnB,KACE,OAAO,SAAS,cAAc,mBAAmB;GAC/C,GAAG;GACH,GAAI,WAAW,IAAI,OAAO,EAAE,MAAM,aAAa,IAAI,MAAM,YAAY,EAAE,IAAI,CAAC;EAC9E,CAAC,CACH;EAUF,IAAI,YAAY;EAChB,MAAM,iBAAuB;GAC3B,IAAI,WAAW;GACf,YAAY;GAEZ,MAAM,WAAW,KAAK,IAAI,IAAI;GAC9B,MAAM,SAAS,IAAI,cAAc;GACjC,MAAM,QAAQ,UAAU,MAAM,aAAa;GAE3C,KACE,OAAO,SAAS,OAAO,qBAAqB;IAC1C,GAAG;IACH,YAAY;IACZ;GACF,CAAC,CACH;GAEA,IAAI,WAAW,wBACb,KACE,OAAO,KAAK,yBAAyB;IACnC,GAAG;IACH,YAAY;IACZ;IACA,WAAW;GACb,CAAC,CACH;EAEJ;EAEA,CAAA,YAAA,IAAI,UAAA,QAAA,cAAA,KAAA,KAAA,UAAA,KAAA,KAAO,UAAU,QAAQ;EAG7B,CAAA,aAAA,IAAI,UAAA,QAAA,eAAA,KAAA,KAAA,WAAA,KAAA,KAAO,SAAS,QAAQ;EAE5B,KAAK;CACP;AACF;;;;;;;;;AAgBA,SAAgB,oBAAoB,QAAqB,UAA6B,CAAC,GAAG;CACxF,MAAM,EACJ,MACA,eACA,eAAe,SACf,gBAAgB,QAChB,aAAa,SACb,yBAAyB,QACvB;CACJ,MAAM,WAAW,gBAAgB,OAAO;CACxC,MAAM,eAAeD,sBAAAA,oBAAoB,aAAa;CAEtD,SAAS,qBAAqB,SAA0B,OAAgB,MAAwB;EAC9F,QAAQ,QAAQ,cAAc,SAAkB,QAAiB,aAAyB;GACxF,MAAM,MAAM;GACZ,IAAA,SAAA,QAAA,SAAA,KAAA,IAAA,KAAA,IAAI,KAAO,GAAG,GAAG;IACf,SAAS;IACT;GACF;GAEA,MAAM,UAAUC,sBAAAA,sBAAsB,KAAK,YAAY;GACvD,IAAI,gBAAgB,KAAK,IAAI;GAE7B,IAAI,iBAAiB,UACnB,KACE,OAAO,SACL,cACA,mBACA,gBAAgB,KAAK,SAAS,SAAS,QAAQ,CACjD,CACF;GAEF,SAAS;EACX,CAAC;EAED,QAAQ,QAAQ,eAAe,SAAkB,OAAgB,aAAyB;GACxF,MAAM,MAAM;GACZ,IAAI,IAAI,kBAAkB,KAAA,GAAW;IACnC,SAAS;IACT;GACF;GAEA,MAAM,MAAM;GACZ,MAAM,WAAW,KAAK,IAAI,IAAI,IAAI;GAClC,MAAM,SAAS,IAAI,cAAc;GACjC,MAAM,UAAUA,sBAAAA,sBAAsB,KAAK,YAAY;GACvD,MAAM,QAAQ,UAAU,MAAM,aAAa;GAC3C,MAAM,aAAa,gBAAgB,KAAK,SAAS,SAAS,QAAQ;GAElE,KACE,OAAO,SAAS,OAAO,qBAAqB;IAC1C,GAAG;IACH,YAAY;IACZ;GACF,CAAC,CACH;GAEA,IAAI,WAAW,wBACb,KACE,OAAO,KAAK,yBAAyB;IACnC;IACA,KAAK,WAAW;IAChB,QAAQ,IAAI;IACZ;IACA,WAAW;GACb,CAAC,CACH;GAGF,SAAS;EACX,CAAC;EAED,KAAK;CACP;CAEA,OAAO,OAAO,OAAO,sBAAsB;GACxC,OAAO,IAAI,eAAe,IAAI;GAC9B,OAAO,IAAI,sBAAsB,IAAI;CACxC,CAAC;AACH;;;;;;AASA,SAAS,aAAa,MAAe,WAAW,MAAe;CAC7D,IAAI,OAAO,SAAS,UAClB,OAAO,KAAK,SAAS,WAAW,KAAK,MAAM,GAAG,QAAQ,IAAI,iBAAiB;CAE7E,IAAI,QAAQ,OAAO,SAAS,UAAU;EAEpC,IADYC,uBAAAA,gBAAgB,IACtB,CAAC,CAAC,UAAU,UAAU,OAAO;EACnC,OAAO,WAAW,MAAM,EAAE,MAAM,SAAS,GAAG,mBAAG,IAAI,IAAI,CAAC;CAC1D;CACA,OAAO;AACT;AAEA,MAAM,YAAY;AAClB,MAAM,kBAAkB;AAExB,SAAS,WACP,OACA,QACA,OACA,WACS;CACT,IAAI,OAAO,UAAU,UAAU;EAC7B,MAAM,MAAM,MAAM,MAAM,GAAG,KAAK,IAAI,GAAG,OAAO,IAAI,CAAC;EACnD,OAAO,QAAQ,IAAI;EACnB,OAAO,IAAI,SAAS,MAAM,SAAS,MAAM,YAAY;CACvD;CACA,IAAI,UAAU,QAAQ,OAAO,UAAU,UAAU;EAC/C,OAAO,QAAQ;EACf,OAAO;CACT;CACA,IAAI,iBAAiB,MAAM;EACzB,OAAO,QAAQ;EACf,OAAO,OAAO,MAAM,MAAM,QAAQ,CAAC,IAAI,iBAAiB,MAAM,YAAY;CAC5E;CACA,IAAI,iBAAiB,eAAe,YAAY,OAAO,KAAK,GAAG;EAC7D,OAAO,QAAQ;EACf,OAAO,WAAW,MAAM,WAAW;CACrC;CACA,IAAI,iBAAiB,OAAO,OAAO;CACnC,IAAI,UAAU,IAAI,KAAK,KAAK,SAAS,iBAAiB,OAAO;CAC7D,UAAU,IAAI,KAAK;CACnB,IAAI;EACF,IAAI,MAAM,QAAQ,KAAK,KAAK,iBAAiB,OAAO,iBAAiB,KAAK;GACxE,MAAM,QAAmB,CAAC;GAC1B,KAAK,MAAM,QAAQ,iBAAiB,MAAM,MAAM,QAAQ,IAAI,OAAO;IACjE,IAAI,OAAO,QAAQ,GAAG;KACpB,MAAM,KAAK,SAAS;KACpB;IACF;IACA,MAAM,KAAK,WAAW,MAAM,QAAQ,QAAQ,GAAG,SAAS,CAAC;GAC3D;GACA,OAAO;EACT;EACA,MAAM,SAAU,MAA+B;EAC/C,IAAI,OAAO,WAAW,YAAY;GAChC,MAAM,OAAgB,OAAO,KAAK,KAAK;GACvC,IAAI,SAAS,OAAO,OAAO,WAAW,MAAM,QAAQ,QAAQ,GAAG,SAAS;EAC1E;EACA,MAAM,SAAkC,CAAC;EACzC,KAAK,MAAM,CAAC,GAAG,MAAM,OAAO,QAAQ,KAAK,GAAG;GAC1C,IAAI,OAAO,QAAQ,GAAG;IACpB,OAAO,OAAO;IACd;GACF;GACA,OAAO,QAAQ,EAAE;GACjB,qBAAA,UAAU,QAAQ,GAAG,WAAW,GAAG,QAAQ,QAAQ,GAAG,SAAS,CAAC;EAClE;EACA,OAAO;CACT,QAAQ;EACN,OAAO;CACT,UAAU;EACR,UAAU,OAAO,KAAK;CACxB;AACF"}
1
+ {"version":3,"file":"middleware.js","names":["internalError","buildNameSet","DEFAULT_REDACT_HEADERS","DEFAULT_REDACT_QUERY_PARAMS","sanitizeUrl","resolveTraceHeaders","resolveRequestTraceId","stringifyForLog"],"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\nimport type { IBaseLogger } from '../types';\nimport type { HttpRequestShape, HttpResponseShape } from '../types/http-shapes';\nimport { internalError } from '../utils/internal-log';\nimport { assignOwn } from '../utils/own-property';\nimport { resolveRequestTraceId, resolveTraceHeaders } from '../utils/request-trace';\nimport { stringifyForLog } from '../utils/safe-stringify';\nimport {\n buildNameSet,\n DEFAULT_REDACT_HEADERS,\n DEFAULT_REDACT_QUERY_PARAMS,\n redactUrlQuery as sanitizeUrl,\n} from '../utils/sensitive-names';\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 * Header name, or list of names tried in order, to read the trace ID from.\n * Default: the library-wide list (`DEFAULT_TRACE_HEADERS`: traceparent,\n * x-trace-id, x-request-id, x-correlation-id, trace-id).\n * If none is present, `request.id` is used when it is not a framework counter,\n * otherwise a UUID is generated and shared with the logixia context helpers.\n */\n traceIdHeader?: string | readonly string[];\n /**\n * Additional headers to redact from logged output. Merged with the defaults\n * (authorization, cookie, set-cookie, x-api-key, proxy-authorization,\n * x-auth-token, x-access-token, x-csrf-token, x-amz-security-token).\n */\n redactHeaders?: string[];\n /**\n * Additional query-string parameter names whose values are redacted from the\n * logged URL. Merged with the defaults (token, access_token, refresh_token,\n * code, password, secret, api_key, apikey, key, signature, sig, auth).\n */\n redactQueryParams?: 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 type IncomingRequest = HttpRequestShape;\nexport type OutgoingResponse = HttpResponseShape;\n\n// ── Helpers ───────────────────────────────────────────────────────────────────\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 assignOwn(out, k, redactSet.has(k.toLowerCase()) ? '[REDACTED]' : v);\n }\n return out;\n}\n\n/** Fire-and-forget a logger call; a failing log must never become an unhandled rejection. */\nfunction fire(result: unknown): void {\n if (result && typeof (result as Promise<unknown>).catch === 'function') {\n (result as Promise<unknown>).catch((error: unknown) =>\n internalError('http-logger: log call failed', error)\n );\n }\n}\n\ninterface NameSets {\n headers: Set<string>;\n queryParams: Set<string>;\n}\n\nfunction resolveNameSets(options: HttpLoggerOptions): NameSets {\n return {\n headers: buildNameSet(DEFAULT_REDACT_HEADERS, options.redactHeaders),\n queryParams: buildNameSet(DEFAULT_REDACT_QUERY_PARAMS, options.redactQueryParams),\n };\n}\n\nfunction buildBaseFields(\n req: IncomingRequest,\n traceId: string,\n options: HttpLoggerOptions,\n { headers: redactSet, queryParams: paramSet }: NameSets\n): Record<string, unknown> {\n const fields: Record<string, unknown> = {\n traceId,\n method: req.method?.toUpperCase() ?? 'UNKNOWN',\n url: sanitizeUrl(req.url ?? '/', paramSet),\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,\n requestLevel = 'debug',\n responseLevel = 'info',\n errorLevel = 'error',\n slowRequestThresholdMs = 1000,\n } = options;\n const nameSets = resolveNameSets(options);\n const traceHeaders = resolveTraceHeaders(traceIdHeader);\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 = resolveRequestTraceId(req, traceHeaders);\n const startMs = Date.now();\n const baseFields = buildBaseFields(req, traceId, options, nameSets);\n\n // Log request start\n if (requestLevel !== 'silent') {\n fire(\n logger.logLevel(requestLevel, 'request started', {\n ...baseFields,\n ...(logBody && req.body ? { body: truncateBody(req.body, bodyMaxBytes) } : {}),\n })\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 //\n // BOTH 'finish' and 'close' fire on a normal response, so guard against\n // logging the completion twice (which would duplicate the completed entry and\n // the slow-request warning).\n let completed = false;\n const onFinish = (): void => {\n if (completed) return;\n completed = true;\n\n const duration = Date.now() - startMs;\n const status = res.statusCode ?? 0;\n const level = status >= 500 ? errorLevel : responseLevel;\n\n fire(\n logger.logLevel(level, 'request completed', {\n ...baseFields,\n statusCode: status,\n duration,\n })\n );\n\n if (duration > slowRequestThresholdMs) {\n fire(\n logger.warn('slow request detected', {\n ...baseFields,\n statusCode: status,\n duration,\n threshold: slowRequestThresholdMs,\n })\n );\n }\n };\n\n res.once?.('finish', onFinish);\n // Fallback: also covers a client that disconnects before 'finish' fires. The\n // `completed` guard ensures a normal finish+close pair logs only once.\n res.once?.('close', onFinish);\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,\n requestLevel = 'debug',\n responseLevel = 'info',\n errorLevel = 'error',\n slowRequestThresholdMs = 1000,\n } = options;\n const nameSets = resolveNameSets(options);\n const traceHeaders = resolveTraceHeaders(traceIdHeader);\n\n function logixiaFastifyPlugin(fastify: FastifyInstance, _opts: unknown, done: () => void): void {\n fastify.addHook('onRequest', (request: unknown, _reply: unknown, hookDone: () => void) => {\n const req = request as IncomingRequest & { _logixiaStart?: number };\n if (skip?.(req)) {\n hookDone();\n return;\n }\n\n const traceId = resolveRequestTraceId(req, traceHeaders);\n req._logixiaStart = Date.now();\n\n if (requestLevel !== 'silent') {\n fire(\n logger.logLevel(\n requestLevel,\n 'request started',\n buildBaseFields(req, traceId, options, nameSets)\n )\n );\n }\n hookDone();\n });\n\n fastify.addHook('onResponse', (request: unknown, reply: unknown, hookDone: () => void) => {\n const req = request as IncomingRequest & { _logixiaStart?: number };\n if (req._logixiaStart === undefined) {\n hookDone();\n return;\n }\n\n const rep = reply as { statusCode?: number };\n const duration = Date.now() - req._logixiaStart;\n const status = rep.statusCode ?? 0;\n const traceId = resolveRequestTraceId(req, traceHeaders);\n const level = status >= 500 ? errorLevel : responseLevel;\n const baseFields = buildBaseFields(req, traceId, options, nameSets);\n\n fire(\n logger.logLevel(level, 'request completed', {\n ...baseFields,\n statusCode: status,\n duration,\n })\n );\n\n if (duration > slowRequestThresholdMs) {\n fire(\n logger.warn('slow request detected', {\n traceId,\n url: baseFields.url,\n method: req.method,\n duration,\n threshold: slowRequestThresholdMs,\n })\n );\n }\n\n hookDone();\n });\n\n done();\n }\n\n return Object.assign(logixiaFastifyPlugin, {\n [Symbol.for('skip-override')]: true,\n [Symbol.for('fastify.display-name')]: 'logixia',\n });\n}\n\n// ── Internal helpers ──────────────────────────────────────────────────────────\n\n/**\n * Bound the captured body without turning it into a string, so the logger's\n * path-based redaction still sees the original keys. Oversized structures are\n * pruned (extra keys/items dropped, long strings cut) rather than serialized.\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 = stringifyForLog(body);\n if (str.length <= maxBytes) return body;\n return pruneValue(body, { left: maxBytes }, 0, new Set());\n }\n return body;\n}\n\nconst TRUNCATED = '…[truncated]';\nconst MAX_PRUNE_DEPTH = 8;\n\nfunction pruneValue(\n value: unknown,\n budget: { left: number },\n depth: number,\n ancestors: Set<object>\n): unknown {\n if (typeof value === 'string') {\n const cut = value.slice(0, Math.max(0, budget.left));\n budget.left -= cut.length;\n return cut.length < value.length ? cut + TRUNCATED : cut;\n }\n if (value === null || typeof value !== 'object') {\n budget.left -= 8;\n return value;\n }\n if (value instanceof Date) {\n budget.left -= 24;\n return Number.isNaN(value.getTime()) ? 'Invalid Date' : value.toISOString();\n }\n if (value instanceof ArrayBuffer || ArrayBuffer.isView(value)) {\n budget.left -= 16;\n return `[Buffer ${value.byteLength} bytes]`;\n }\n if (value instanceof Error) return value;\n if (ancestors.has(value) || depth >= MAX_PRUNE_DEPTH) return TRUNCATED;\n ancestors.add(value);\n try {\n if (Array.isArray(value) || value instanceof Set || value instanceof Map) {\n const items: unknown[] = [];\n for (const item of value instanceof Map ? value.entries() : value) {\n if (budget.left <= 0) {\n items.push(TRUNCATED);\n break;\n }\n items.push(pruneValue(item, budget, depth + 1, ancestors));\n }\n return items;\n }\n const toJSON = (value as { toJSON?: unknown }).toJSON;\n if (typeof toJSON === 'function') {\n const json: unknown = toJSON.call(value);\n if (json !== value) return pruneValue(json, budget, depth + 1, ancestors);\n }\n const record: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(value)) {\n if (budget.left <= 0) {\n record['…'] = TRUNCATED;\n break;\n }\n budget.left -= k.length;\n assignOwn(record, k, pruneValue(v, budget, depth + 1, ancestors));\n }\n return record;\n } catch {\n return TRUNCATED;\n } finally {\n ancestors.delete(value);\n }\n}\n"],"mappings":"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"}
@@ -1,7 +1,7 @@
1
- import { t as assignOwn } from "./own-property-CjFw9qwZ.mjs";
1
+ import { a as buildNameSet, l as assignOwn, n as DEFAULT_REDACT_QUERY_PARAMS, o as redactUrlQuery, t as DEFAULT_REDACT_HEADERS } from "./sensitive-names-o__1PUUR.mjs";
2
2
  import { n as resolveTraceHeaders, t as resolveRequestTraceId } from "./request-trace-BgNykH9M.mjs";
3
- import { a as DEFAULT_REDACT_QUERY_PARAMS, c as buildNameSet, i as DEFAULT_REDACT_HEADERS, l as redactUrlQuery, t as internalError } from "./internal-log-Bg4V1cPg.mjs";
4
- import { i as stringifyForLog } from "./safe-stringify-B5p5ktFe.mjs";
3
+ import { t as internalError } from "./internal-log-Cy5nF1ZL.mjs";
4
+ import { i as stringifyForLog } from "./safe-stringify--7gbe95n.mjs";
5
5
  // src/middleware/http-logger.ts
6
6
  function sanitizeHeaders(headers, redactSet) {
7
7
  if (!headers) return {};
package/dist/nest.d.mts CHANGED
@@ -1,5 +1,5 @@
1
- import { A as TraceIdConfig, b as LoggerConfig, y as LogLevelString } from "./index-BSTtFcQ6.mjs";
2
- import { t as LogixiaLogger } from "./logitron-logger-D22Yb61K.mjs";
1
+ import { A as TraceIdConfig, b as LoggerConfig, y as LogLevelString } from "./index-BAkPHp5D.mjs";
2
+ import { t as LogixiaLogger } from "./logitron-logger-sYuk8fOb.mjs";
3
3
  import { ArgumentsHost, CallHandler, ExceptionFilter, ExecutionContext, InjectionToken, LoggerService, MiddlewareConsumer, ModuleMetadata, NestInterceptor, NestMiddleware, NestModule, OptionalFactoryDependency, Type } from "@nestjs/common";
4
4
  import { Observable } from "rxjs";
5
5
  import { NextFunction, Request, Response } from "express";
@@ -455,6 +455,13 @@ interface LogixiaExceptionFilterOptions {
455
455
  * @default false
456
456
  */
457
457
  exposeCause?: boolean;
458
+ /**
459
+ * Extra query parameter names whose values are replaced with `[REDACTED]` in the
460
+ * logged `url`, the response `path`, and any copy of those values inside the error
461
+ * message, stack or details. Merged with the defaults (`token`, `code`, `password`,
462
+ * `api_key`, …) and `LoggerConfig.redact.queryParams`.
463
+ */
464
+ redactQueryParams?: readonly string[];
458
465
  }
459
466
  /** Injection token for {@link LogixiaExceptionFilterOptions}. */
460
467
  export declare const LOGIXIA_EXCEPTION_FILTER_OPTIONS = "LOGIXIA_EXCEPTION_FILTER_OPTIONS";
@@ -462,6 +469,7 @@ export declare class LogixiaExceptionFilter implements ExceptionFilter {
462
469
  private readonly _logger;
463
470
  private readonly _traceConfig;
464
471
  private readonly _options;
472
+ private readonly _redactParams;
465
473
  constructor(logger?: LogixiaLoggerService, loggerConfig?: Partial<LoggerConfig>, options?: LogixiaExceptionFilterOptions);
466
474
  catch(exception: unknown, host: ArgumentsHost): void;
467
475
  }
@@ -475,7 +483,8 @@ declare global {
475
483
  export declare class TraceMiddleware implements NestMiddleware {
476
484
  private readonly config?;
477
485
  private readonly ctx;
478
- constructor(config?: TraceIdConfig | undefined);
486
+ private readonly redactParams;
487
+ constructor(config?: TraceIdConfig | undefined, redactQueryParams?: readonly string[]);
479
488
  use(req: Request, res: Response, next: NextFunction): void;
480
489
  }
481
490
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"nest.d.mts","names":[],"sources":["../src/core/logitron-nestjs.service.ts","../src/core/kafka-trace.interceptor.ts","../src/core/websocket-trace.interceptor.ts","../src/core/logitron-logger.module.ts","../src/core/nestjs-extras.ts","../src/core/trace.middleware.ts","../src/nest.ts"],"mappings":"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"}
1
+ {"version":3,"file":"nest.d.mts","names":[],"sources":["../src/core/logitron-nestjs.service.ts","../src/core/kafka-trace.interceptor.ts","../src/core/websocket-trace.interceptor.ts","../src/core/logitron-logger.module.ts","../src/core/nestjs-extras.ts","../src/core/trace.middleware.ts","../src/nest.ts"],"mappings":"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"}
package/dist/nest.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { A as TraceIdConfig, b as LoggerConfig, y as LogLevelString } from "./index-CFDGkI8n.js";
2
- import { t as LogixiaLogger } from "./logitron-logger-D_MYYrQt.js";
1
+ import { A as TraceIdConfig, b as LoggerConfig, y as LogLevelString } from "./index-e7LowmAu.js";
2
+ import { t as LogixiaLogger } from "./logitron-logger-Qh3y9-WH.js";
3
3
  import { ArgumentsHost, CallHandler, ExceptionFilter, ExecutionContext, InjectionToken, LoggerService, MiddlewareConsumer, ModuleMetadata, NestInterceptor, NestMiddleware, NestModule, OptionalFactoryDependency, Type } from "@nestjs/common";
4
4
  import { Observable } from "rxjs";
5
5
  import { NextFunction, Request, Response } from "express";
@@ -455,6 +455,13 @@ interface LogixiaExceptionFilterOptions {
455
455
  * @default false
456
456
  */
457
457
  exposeCause?: boolean;
458
+ /**
459
+ * Extra query parameter names whose values are replaced with `[REDACTED]` in the
460
+ * logged `url`, the response `path`, and any copy of those values inside the error
461
+ * message, stack or details. Merged with the defaults (`token`, `code`, `password`,
462
+ * `api_key`, …) and `LoggerConfig.redact.queryParams`.
463
+ */
464
+ redactQueryParams?: readonly string[];
458
465
  }
459
466
  /** Injection token for {@link LogixiaExceptionFilterOptions}. */
460
467
  export declare const LOGIXIA_EXCEPTION_FILTER_OPTIONS = "LOGIXIA_EXCEPTION_FILTER_OPTIONS";
@@ -462,6 +469,7 @@ export declare class LogixiaExceptionFilter implements ExceptionFilter {
462
469
  private readonly _logger;
463
470
  private readonly _traceConfig;
464
471
  private readonly _options;
472
+ private readonly _redactParams;
465
473
  constructor(logger?: LogixiaLoggerService, loggerConfig?: Partial<LoggerConfig>, options?: LogixiaExceptionFilterOptions);
466
474
  catch(exception: unknown, host: ArgumentsHost): void;
467
475
  }
@@ -475,7 +483,8 @@ declare global {
475
483
  export declare class TraceMiddleware implements NestMiddleware {
476
484
  private readonly config?;
477
485
  private readonly ctx;
478
- constructor(config?: TraceIdConfig | undefined);
486
+ private readonly redactParams;
487
+ constructor(config?: TraceIdConfig | undefined, redactQueryParams?: readonly string[]);
479
488
  use(req: Request, res: Response, next: NextFunction): void;
480
489
  }
481
490
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"nest.d.ts","names":[],"sources":["../src/core/logitron-nestjs.service.ts","../src/core/kafka-trace.interceptor.ts","../src/core/websocket-trace.interceptor.ts","../src/core/logitron-logger.module.ts","../src/core/nestjs-extras.ts","../src/core/trace.middleware.ts","../src/nest.ts"],"mappings":";;;;;;;;;;KAiCK;;;;;;;;;KAWA,0BAA0B,gBAAgB,sCACnC,WAAW,WAAW,UAAU,gCAAgC,cACxE,iBACA,OAAO,4BACJ;;;;;;;;YAUK,yBAAyB,UAAU,aAAa,2BAC1D;EAA4B,cAAc;IACtC,UAAU,yBACR,uBAAuB,0BAA0B,KACjD,uBACF;;;;KAKD,yBAAyB,KAAK;EAAY;IAAiB,eAAe;;IAC3E,UAAU,yBACR,cAAc,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;YAmCpB,mBAAmB,mBAAmB,2BAChD,mCAEI,KAAK,mBAAmB,QAAQ,GAAG,yBAAyB,yBAAyB,MACnF,iBAAiB,OAAO,4BAA4B;qBAS/C,gCAAgC;GAE1C;UAEO;UACA;UACA;EAEI,YAAA,SAAS;UA+Cb;;;;;;;EAyBR,IAAI,kBAAkB;;;;;;EAYhB,KAAK,iBAAiB,OAAO,0BAA0B;;;;;;;EAY7D,MAAM,kBAAkB,OAAO,MAAM,0BAA0B;;;;;;EAO/D,MAAM,kBAAkB,gBAAgB;;;;;;EAoCxC,KAAK,iBAAiB,MAAM,0BAA0B;;;;;;EAOtD,KAAK,kBAAkB;;;;;;EAmBvB,MAAM,iBAAiB,MAAM,0BAA0B;;;;;;EAOvD,MAAM,kBAAkB;;;;;;;EAoBxB,QAAQ,iBAAiB,MAAM,0BAA0B;;;;;;EAOzD,QAAQ,kBAAkB;;;;EAoBpB,MAAM,iBAAiB,OAAO,0BAA0B;;;;EAO9D,SAAS,eAAe,iBAAiB,OAAO,0BAA0B;EAM1E,KAAK;EAIC,QAAQ,gBAAgB;EAIxB,UAAU,GAAG,eAAe,UAAU,QAAQ,KAAK,QAAQ;EAMjE,WAAW;EAMX;EAIA,SAAS,OAAO;EAIhB,YAAY;EAMZ,MAAM,iBAAiB,OAAO,0BAA0B;EASxD;;MAKI;EAIE,SAAS;SAIR,OAAO,UAAU,aAAa,yBACnC,SAAS,IACR,yBAAyB;EAI5B,aAAa;UAML;UAUA;;;;;;;;;;;UCjaO;;EAEf;;EAEA;;EAEA;;qBAIW,iCAAiC;mBA+BzB;;;;;kBA1BH,SAAS;;SAOlB;mBAMU;mBACA;;;;;;;;;EAWf,YAAA,SAAS,eACQ;EAcnB,UAAU,SAAS,kBAAkB,MAAM,cAAc;;qBChE9C,qCAAqC;mBAC/B;mBACA;EAEL,YAAA,SAAS;EAcrB,UAAU,SAAS,kBAAkB,MAAM,cAAc;;qBCL9C;qBACA;qBACA;iBAcI,4BAA4B,KAAK;EAChD,cAAc,KAAK;EACnB,WAAW,KAAK;EAChB,iBAAiB,oBAAoB,QAAQ,QAAQ,iBAAiB,QAAQ;EAC9E,SAAS,MAAM,iBAAiB;;iBAIjB;EACf,wBAAwB,QAAQ,QAAQ,iBAAiB,QAAQ;;;;;qBAOtD,+BAA+B;UAClC;iBACO;;;;;;SAWR,eAAe;;;;;;;;;;;;;SAcf,iBAAiB,SAAS;;SAY1B;;;;;;;;;;;;;;;;;;;SAsBA,mBAAmB;EAI1B,UAAU,UAAU;;;;SAkCb,QAAQ,SAAS,QAAQ;;;;;;;;;;;;;;MAsBG,aAAA,cAAA,QAAQ,kBAAa;;;;;MAmCtB,aAAA,aAAA,8BAAyB;;;;;MAMzB,aAAA,aAAA,8BAAyB;;;;;;;;;;SAkBpD,aAAa,SAAS;;;;;MAjMN,gBAAA,oBAAc,QAAQ,QAAQ,iBAAiB,QAAQ;;;;MAuTvC,aAAA,gBAAA,0BAAqB,QAAA,QAAA,aAAA;;;;;;;MA9GzB,aAAA,cAAA,QAAQ,kBAAa;;;;MASrB,aAAA,cAAA,QAAQ,kBAAa;;;;MAqCtB,aAAA,aAAA,8BAAyB;;;;MAMzB,aAAA,aAAA,8BAAyB;;;;;;;;;SAkBpD,WAAW;;;;MAOe,aAAA,YAAA,yBAAoB;;;;;iBAUtC;iBAaA;;;;;;;;;;;;;;;;;;qBCnRJ,eAAgB,qBAAmB;UAO/B;;;;;EAKf,QAAQ;;;;;;EAMR;;;;;EAKA;;;;;EAKA;;;;EAIA;;;;;;;;;;;;;;;;;wBAkBc,UAAU,UAAS,mBAAwB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;UAkJ1C;;;;;EAKf;;;;;EAKA;;;qBAIW;qBAGA,kCAAkC;mBAC5B;mBACA;mBACA;EAKf,YAAA,SAAS,sBAGT,eAAe,QAAQ,eAGvB,UAAU;EAaZ,MAAM,oBAAoB,MAAM;;QCnQ1B;YACI;cACE;MACR;;;;qBAOO,2BAA2B;mBAGG;mBAFxB;EAEwB,YAAA,SAAS;EAqBlD,IAAI,KAAK,SAAS,KAAK,UAAU,MAAM;;;;;;;wBCjDzB,oBAAoB,SAAS,QAAQ,gBAAgB"}
1
+ {"version":3,"file":"nest.d.ts","names":[],"sources":["../src/core/logitron-nestjs.service.ts","../src/core/kafka-trace.interceptor.ts","../src/core/websocket-trace.interceptor.ts","../src/core/logitron-logger.module.ts","../src/core/nestjs-extras.ts","../src/core/trace.middleware.ts","../src/nest.ts"],"mappings":"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"}
package/dist/nest.js CHANGED
@@ -1,8 +1,9 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_secret_config = require("./secret-config-CmK2wVkr.js");
3
- const require_builder = require("./builder-yFvJrz7o.js");
2
+ const require_secret_config = require("./secret-config-BvFl2dC8.js");
3
+ const require_builder = require("./builder-CzmM_4Ub.js");
4
+ const require_sensitive_names = require("./sensitive-names-CHMowujD.js");
4
5
  const require_request_trace = require("./request-trace-ByujsUZk.js");
5
- const require_internal_log = require("./internal-log-By4Govmu.js");
6
+ const require_internal_log = require("./internal-log-DwqTjhpb.js");
6
7
  const require_coerce_utils = require("./coerce.utils-C1C5sIX0.js");
7
8
  let _nestjs_common = require("@nestjs/common");
8
9
  let rxjs = require("rxjs");
@@ -303,10 +304,18 @@ function writeTraceHeader(res, header, traceId) {
303
304
  else if (typeof r.header === "function") r.header(header, traceId);
304
305
  } catch {}
305
306
  }
307
+ /** Injection token for extra query parameter names redacted in the trace context `url`. */
308
+ const LOGIXIA_TRACE_REDACT_QUERY_PARAMS = "LOGIXIA_TRACE_REDACT_QUERY_PARAMS";
309
+ /** The request URL as stored in the trace context: `originalUrl`, sensitive query values redacted. */
310
+ function traceUrl(req, names) {
311
+ const raw = req.originalUrl ?? req.url;
312
+ return raw === void 0 ? void 0 : require_sensitive_names.redactUrlQuery(raw, names);
313
+ }
306
314
  let TraceMiddleware = class TraceMiddleware {
307
- constructor(config) {
315
+ constructor(config, redactQueryParams) {
308
316
  this.config = config;
309
317
  this.ctx = require_request_trace.TraceContext.instance;
318
+ this.redactParams = require_sensitive_names.buildNameSet(require_sensitive_names.DEFAULT_REDACT_QUERY_PARAMS, redactQueryParams);
310
319
  const defaultExtractor = {
311
320
  header: require_request_trace.DEFAULT_TRACE_HEADERS,
312
321
  query: ["traceId", "trace_id"]
@@ -339,7 +348,7 @@ let TraceMiddleware = class TraceMiddleware {
339
348
  if (header) writeTraceHeader(res, header, traceId);
340
349
  this.ctx.run(traceId, () => next(), {
341
350
  method: req.method,
342
- url: req.url,
351
+ url: traceUrl(req, this.redactParams),
343
352
  userAgent: req.get("User-Agent"),
344
353
  ip: req.ip || ((_req$socket = req.socket) === null || _req$socket === void 0 ? void 0 : _req$socket.remoteAddress) || ((_req$connection = req.connection) === null || _req$connection === void 0 ? void 0 : _req$connection.remoteAddress)
345
354
  });
@@ -348,7 +357,9 @@ let TraceMiddleware = class TraceMiddleware {
348
357
  TraceMiddleware = __decorate([
349
358
  (0, _nestjs_common.Injectable)(),
350
359
  __decorateParam(0, (0, _nestjs_common.Optional)()),
351
- __decorateMetadata("design:paramtypes", [Object])
360
+ __decorateParam(1, (0, _nestjs_common.Optional)()),
361
+ __decorateParam(1, (0, _nestjs_common.Inject)(LOGIXIA_TRACE_REDACT_QUERY_PARAMS)),
362
+ __decorateMetadata("design:paramtypes", [Object, Array])
352
363
  ], TraceMiddleware);
353
364
  // src/core/websocket-trace.interceptor.ts
354
365
  let WebSocketTraceInterceptor = class WebSocketTraceInterceptor {
@@ -470,6 +481,7 @@ let LogixiaLoggerModule = class LogixiaLoggerModule {
470
481
  return _LogixiaLoggerModule._globalLogger;
471
482
  }
472
483
  configure(consumer) {
484
+ var _LogixiaLoggerModule$;
473
485
  const { forRoutes = DEFAULT_ROUTES, exclude } = this.config;
474
486
  let resolvedTraceConfig;
475
487
  if (typeof _LogixiaLoggerModule.loggerConfig.traceId === "object") resolvedTraceConfig = _LogixiaLoggerModule.loggerConfig.traceId;
@@ -478,7 +490,7 @@ let LogixiaLoggerModule = class LogixiaLoggerModule {
478
490
  contextKey: "traceId",
479
491
  generator: () => require_request_trace.TraceContext.instance.generate()
480
492
  };
481
- const middleware = new TraceMiddleware(resolvedTraceConfig);
493
+ const middleware = new TraceMiddleware(resolvedTraceConfig, (_LogixiaLoggerModule$ = _LogixiaLoggerModule.loggerConfig.redact) === null || _LogixiaLoggerModule$ === void 0 ? void 0 : _LogixiaLoggerModule$.queryParams);
482
494
  const middlewareConfig = (req, res, next) => middleware.use(req, res, next);
483
495
  if (exclude) consumer.apply(middlewareConfig).exclude(...exclude).forRoutes(...forRoutes);
484
496
  else consumer.apply(middlewareConfig).forRoutes(...forRoutes);
@@ -765,9 +777,86 @@ function LogMethod(options = {}) {
765
777
  }
766
778
  /** Injection token for {@link LogixiaExceptionFilterOptions}. */
767
779
  const LOGIXIA_EXCEPTION_FILTER_OPTIONS = "LOGIXIA_EXCEPTION_FILTER_OPTIONS";
780
+ const MAX_SCRUB_DEPTH = 8;
781
+ /** Copy `value` with every string passed through `clean`; the input is never modified. */
782
+ function cleanDeep(value, clean, depth = 0) {
783
+ if (typeof value === "string") return clean(value);
784
+ if (value === null || typeof value !== "object" || depth >= MAX_SCRUB_DEPTH) return value;
785
+ if (Array.isArray(value)) return value.map((item) => cleanDeep(item, clean, depth + 1));
786
+ const out = {};
787
+ for (const [key, item] of Object.entries(value)) out[key] = cleanDeep(item, clean, depth + 1);
788
+ return out;
789
+ }
790
+ function scrubErrorResponse(response, clean) {
791
+ const { error, debug } = response;
792
+ return {
793
+ ...response,
794
+ error: cleanDeep(error, clean),
795
+ ...debug !== void 0 ? { debug: cleanDeep(debug, clean) } : {}
796
+ };
797
+ }
798
+ const MAX_ERROR_DEPTH = 6;
799
+ /** Scrub string VALUES of an already serialized tree; keys stay so key-based redaction still applies. */
800
+ function scrubSerialized(value, clean, depth, seen) {
801
+ if (typeof value === "string") return clean(value);
802
+ if (value === null || typeof value !== "object") return typeof value === "function" || typeof value === "symbol" ? "[Unserializable]" : value;
803
+ if (seen.has(value)) return "[Circular]";
804
+ if (depth >= MAX_ERROR_DEPTH) return "[MaxDepth]";
805
+ seen.add(value);
806
+ try {
807
+ if (Array.isArray(value)) return value.map((item) => scrubSerialized(item, clean, depth + 1, seen));
808
+ const out = {};
809
+ for (const [key, item] of Object.entries(value)) require_sensitive_names.assignOwn(out, key, scrubSerialized(item, clean, depth + 1, seen));
810
+ return out;
811
+ } finally {
812
+ seen.delete(value);
813
+ }
814
+ }
815
+ /** Minimal copy used when the full sanitize step fails; never throws. */
816
+ function fallbackError(exception, clean) {
817
+ let name = "Error";
818
+ let message = "[Unserializable]";
819
+ try {
820
+ if (exception instanceof Error) {
821
+ name = exception.name;
822
+ message = clean(exception.message);
823
+ }
824
+ } catch {}
825
+ const copy = new Error(message);
826
+ copy.name = name;
827
+ require_sensitive_names.assignOwn(copy, "serialization", "[Unserializable]");
828
+ return copy;
829
+ }
830
+ /**
831
+ * A fresh Error safe to log. Built from `serializeError` (class instances walked by key,
832
+ * so the logger's key-based redaction still sees `authorization`, `x-api-key`, ...), with
833
+ * string values scrubbed. Keeps name, message, stack, cause and custom properties.
834
+ * The original is untouched and this never throws.
835
+ */
836
+ function sanitizedError(exception, clean) {
837
+ try {
838
+ if (!(exception instanceof Error)) return new Error(clean(String(exception)));
839
+ const scrubbed = scrubSerialized(require_builder.serializeError(exception), clean, 0, /* @__PURE__ */ new WeakSet());
840
+ const copy = new Error(String(scrubbed["message"] ?? ""));
841
+ for (const [key, value] of Object.entries(scrubbed)) {
842
+ if (key === "message") continue;
843
+ if (key === "stack" || key === "name") Object.defineProperty(copy, key, {
844
+ value,
845
+ writable: true,
846
+ configurable: true
847
+ });
848
+ else require_sensitive_names.assignOwn(copy, key, value);
849
+ }
850
+ return copy;
851
+ } catch {
852
+ return fallbackError(exception, clean);
853
+ }
854
+ }
768
855
  let LogixiaExceptionFilter = class LogixiaExceptionFilter {
769
856
  constructor(logger, loggerConfig, options) {
857
+ var _loggerConfig$redact;
770
858
  this._options = options ?? {};
859
+ this._redactParams = require_sensitive_names.buildNameSet(require_sensitive_names.DEFAULT_REDACT_QUERY_PARAMS, [...(loggerConfig === null || loggerConfig === void 0 || (_loggerConfig$redact = loggerConfig.redact) === null || _loggerConfig$redact === void 0 ? void 0 : _loggerConfig$redact.queryParams) ?? [], ...this._options.redactQueryParams ?? []]);
771
860
  this._logger = logger ?? LogixiaLoggerModule._globalLogger ?? void 0;
772
861
  this._traceConfig = typeof (loggerConfig === null || loggerConfig === void 0 ? void 0 : loggerConfig.traceId) === "object" ? loggerConfig.traceId : void 0;
773
862
  }
@@ -777,18 +866,39 @@ let LogixiaExceptionFilter = class LogixiaExceptionFilter {
777
866
  const request = ctx.getRequest();
778
867
  const response = ctx.getResponse();
779
868
  const traceId = require_request_trace.TraceContext.instance.getCurrentTraceId() ?? require_request_trace.sanitizeIncomingId((_request$headers = request.headers) === null || _request$headers === void 0 ? void 0 : _request$headers["x-trace-id"]) ?? require_request_trace.sanitizeIncomingId(request.id) ?? void 0;
780
- const { response: errorResponse, httpStatus } = require_builder.ErrorResponseBuilder.build({
781
- exception,
782
- traceId,
783
- path: request.url ?? "/",
784
- startTime: request.startTime,
785
- exposeDebug: this._options.exposeDebug === true,
786
- exposeCause: this._options.exposeCause === true
787
- });
869
+ const rawUrl = request.originalUrl ?? request.url ?? "";
870
+ const url = require_sensitive_names.redactUrlQuery(rawUrl, this._redactParams);
871
+ const secrets = require_sensitive_names.sensitiveQueryValues(rawUrl, this._redactParams);
872
+ const clean = (text) => require_sensitive_names.sanitizeText(text, this._redactParams, secrets);
873
+ const buildFor = (input) => {
874
+ const { response: built, httpStatus: status } = require_builder.ErrorResponseBuilder.build({
875
+ exception: input,
876
+ traceId,
877
+ path: url || "/",
878
+ startTime: request.startTime,
879
+ exposeDebug: this._options.exposeDebug === true,
880
+ exposeCause: this._options.exposeCause === true
881
+ });
882
+ return {
883
+ errorResponse: scrubErrorResponse(built, clean),
884
+ httpStatus: status
885
+ };
886
+ };
887
+ let result;
888
+ try {
889
+ result = buildFor(exception);
890
+ } catch {
891
+ result = buildFor(fallbackError(exception, clean));
892
+ }
893
+ const { errorResponse, httpStatus } = result;
894
+ let logixiaException = false;
895
+ try {
896
+ logixiaException = require_builder.isLogixiaException(exception);
897
+ } catch {}
788
898
  if (this._logger) {
789
899
  const requestMeta = {
790
900
  method: request.method ?? "",
791
- url: request.url ?? "",
901
+ url,
792
902
  status: httpStatus,
793
903
  ...errorResponse.meta.trace_id !== void 0 ? { trace_id: errorResponse.meta.trace_id } : {}
794
904
  };
@@ -796,10 +906,8 @@ let LogixiaExceptionFilter = class LogixiaExceptionFilter {
796
906
  require_internal_log.internalError(`ExceptionFilter failed to write log entry: ${String(err)}`);
797
907
  };
798
908
  let logPromise;
799
- if (httpStatus >= 500) {
800
- const err = exception instanceof Error ? exception : new Error(String(exception));
801
- logPromise = this._logger.error(err, requestMeta);
802
- } else if (require_builder.isLogixiaException(exception)) logPromise = this._logger.warn(`[${errorResponse.error.code}] ${errorResponse.error.message}`, requestMeta);
909
+ if (httpStatus >= 500) logPromise = this._logger.error(sanitizedError(exception, clean), requestMeta);
910
+ else if (logixiaException) logPromise = this._logger.warn(`[${errorResponse.error.code}] ${errorResponse.error.message}`, requestMeta);
803
911
  else logPromise = this._logger.warn(`[${httpStatus}] ${errorResponse.error.message}`, requestMeta);
804
912
  if (logPromise && typeof logPromise.catch === "function") logPromise.catch(onLogFailure);
805
913
  }