@bymax-one/nest-logger 1.1.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -64,6 +64,7 @@ function applyDefaults(options) {
64
64
  isGlobal: options.isGlobal ?? true,
65
65
  shouldUseAsNestLogger: options.shouldUseAsNestLogger ?? true,
66
66
  redactPaths: Object.freeze([...options.redactPaths ?? []]),
67
+ redactStrategy: options.redactStrategy ?? "names",
67
68
  redactCensor: options.redactCensor ?? "[REDACTED]",
68
69
  shouldDisableDefaultRedact: options.shouldDisableDefaultRedact ?? false,
69
70
  destinations: Object.freeze([...options.destinations ?? []]),
@@ -89,7 +90,7 @@ var PINO_LEVEL_NUMBERS = Object.freeze({
89
90
  debug: 20,
90
91
  trace: 10
91
92
  });
92
- Object.freeze(
93
+ var PINO_LEVEL_NAMES = Object.freeze(
93
94
  Object.fromEntries(
94
95
  Object.entries(PINO_LEVEL_NUMBERS).map(([name, num]) => [num, name])
95
96
  // keys of PINO_LEVEL_NUMBERS are always LogLevel
@@ -126,16 +127,105 @@ function validateOptions(options) {
126
127
  if (options.maxEntrySizeBytes !== void 0 && options.maxEntrySizeBytes <= 0) {
127
128
  throw new Error("[BymaxLoggerModule] options.maxEntrySizeBytes must be > 0");
128
129
  }
130
+ if (options.redactStrategy !== void 0 && options.redactStrategy !== "names" && options.redactStrategy !== "paths") {
131
+ throw new Error(
132
+ `[BymaxLoggerModule] options.redactStrategy must be 'names' or 'paths'. Got: ${String(
133
+ options.redactStrategy
134
+ )}`
135
+ );
136
+ }
129
137
  }
130
138
 
131
139
  // src/server/constants/injection-tokens.constants.ts
132
140
  var LOGGER_OPTIONS_TOKEN = /* @__PURE__ */ Symbol("BYMAX_LOGGER_OPTIONS");
133
141
  var LOGGER_PINO_INSTANCE_TOKEN = /* @__PURE__ */ Symbol("BYMAX_LOGGER_PINO_INSTANCE");
134
142
  var LOGGER_DESTINATIONS_TOKEN = /* @__PURE__ */ Symbol("BYMAX_LOGGER_DESTINATIONS");
143
+ var LOGGER_REDACTOR_TOKEN = /* @__PURE__ */ Symbol("BYMAX_LOGGER_REDACTOR");
135
144
  var LOG_CONTEXT_TOKEN = /* @__PURE__ */ Symbol("BYMAX_LOGGER_LOG_CONTEXT");
145
+
146
+ // src/shared/constants/reserved-log-keys.constants.ts
147
+ var RESERVED_LOG_KEYS = Object.freeze({
148
+ LOGGER_BOOTSTRAP_OK: "LOGGER_BOOTSTRAP_OK",
149
+ LOGGER_BOOTSTRAP_WARNING: "LOGGER_BOOTSTRAP_WARNING",
150
+ LOGGER_SHUTDOWN_OK: "LOGGER_SHUTDOWN_OK",
151
+ HTTP_REQUEST_START: "HTTP_REQUEST_START",
152
+ HTTP_REQUEST_SUCCESS: "HTTP_REQUEST_SUCCESS",
153
+ HTTP_REQUEST_REDIRECT: "HTTP_REQUEST_REDIRECT",
154
+ HTTP_REQUEST_CLIENT_ERROR: "HTTP_REQUEST_CLIENT_ERROR",
155
+ HTTP_REQUEST_SERVER_ERROR: "HTTP_REQUEST_SERVER_ERROR",
156
+ HTTP_REQUEST_COMPLETED: "HTTP_REQUEST_COMPLETED",
157
+ HTTP_REQUEST_ABORTED: "HTTP_REQUEST_ABORTED",
158
+ HTTP_EXCEPTION_HANDLED: "HTTP_EXCEPTION_HANDLED",
159
+ HTTP_EXCEPTION_UNHANDLED: "HTTP_EXCEPTION_UNHANDLED",
160
+ METHOD_EXECUTION: "METHOD_EXECUTION",
161
+ METHOD_SLOW_EXECUTION: "METHOD_SLOW_EXECUTION",
162
+ LOGGER_DESTINATION_INIT_FAILED: "LOGGER_DESTINATION_INIT_FAILED",
163
+ LOGGER_DESTINATION_WRITE_FAILED: "LOGGER_DESTINATION_WRITE_FAILED",
164
+ LOGGER_ENTRY_TRUNCATED: "LOGGER_ENTRY_TRUNCATED",
165
+ LOGGER_REDACTION_FAILED: "LOGGER_REDACTION_FAILED"
166
+ });
167
+ var RESERVED_LOG_KEYS_NOT_EMITTED = Object.freeze({
168
+ /**
169
+ * Superseded before it was ever used. The request lifecycle terminates in one
170
+ * of `HTTP_REQUEST_SUCCESS` / `_REDIRECT` / `_CLIENT_ERROR` / `_SERVER_ERROR`,
171
+ * each carrying the same `duration` a generic "completed" entry would. Emitting
172
+ * it as well would double the terminal access-log volume to say nothing new.
173
+ * It stays claimed so an application cannot repurpose a name that reads like a
174
+ * library event.
175
+ */
176
+ HTTP_REQUEST_COMPLETED: "reserved: superseded by the four status-specific terminal keys"
177
+ });
178
+
179
+ // src/server/constants/prototype-polluting-keys.constants.ts
180
+ var PROTOTYPE_POLLUTING_KEYS = /* @__PURE__ */ new Set([
181
+ "__proto__",
182
+ "constructor",
183
+ "prototype"
184
+ ]);
185
+
186
+ // src/server/services/pino-logger.service.ts
187
+ var OWNED_PAYLOAD_KEYS = ["logKey", "userId", "context"];
188
+ function withoutOwnedKeys(metadata) {
189
+ if (metadata === void 0) {
190
+ return {};
191
+ }
192
+ try {
193
+ const safe = {};
194
+ for (const key of Object.keys(metadata)) {
195
+ if (!OWNED_PAYLOAD_KEYS.includes(key) && !PROTOTYPE_POLLUTING_KEYS.has(key)) {
196
+ Reflect.set(safe, key, Reflect.get(metadata, key));
197
+ }
198
+ }
199
+ return safe;
200
+ } catch {
201
+ return {
202
+ _redactionFailed: true,
203
+ _logKey: RESERVED_LOG_KEYS.LOGGER_REDACTION_FAILED
204
+ };
205
+ }
206
+ }
207
+ function safeErrorMessage(error) {
208
+ try {
209
+ return String(error.message);
210
+ } catch {
211
+ return "Unreadable error message";
212
+ }
213
+ }
214
+ function assignIfDefined(payload, key, value) {
215
+ if (value !== void 0) {
216
+ Reflect.defineProperty(payload, key, { value, enumerable: true });
217
+ }
218
+ }
136
219
  exports.PinoLoggerService = class PinoLoggerService {
137
- constructor(pino2) {
220
+ /**
221
+ * @param pino - The wrapped Pino instance.
222
+ * @param redact - The DEFAULT-coverage redactor, applied to `child()` bindings.
223
+ * Defaults to the identity so a hand-built instance (benchmarks, unit tests)
224
+ * still works; the module always injects the configured one.
225
+ */
226
+ constructor(pino2, redact = (value) => value) {
138
227
  this.pino = pino2;
228
+ this.redact = redact;
139
229
  }
140
230
  // ─── NestJS LoggerService variadic interface ──────────────────────────────
141
231
  /**
@@ -158,18 +248,16 @@ exports.PinoLoggerService = class PinoLoggerService {
158
248
  */
159
249
  error(message, ...optionalParams) {
160
250
  if (message instanceof Error) {
161
- this.pino.error(
162
- { context: this.resolveContext(optionalParams), err: this.serializeError(message) },
163
- message.message
164
- );
251
+ const payload2 = { err: this.serializeError(message) };
252
+ assignIfDefined(payload2, "context", this.resolveContext(optionalParams));
253
+ this.pino.error(payload2, safeErrorMessage(message));
165
254
  return;
166
255
  }
167
256
  const stack = typeof optionalParams[0] === "string" ? optionalParams[0] : void 0;
168
257
  const context = typeof optionalParams[1] === "string" ? optionalParams[1] : this.context;
169
- const payload = { context };
170
- if (stack !== void 0) {
171
- payload["stack"] = stack;
172
- }
258
+ const payload = {};
259
+ assignIfDefined(payload, "context", context);
260
+ assignIfDefined(payload, "stack", stack);
173
261
  this.pino.error(payload, typeof message === "string" ? message : String(message));
174
262
  }
175
263
  /**
@@ -244,10 +332,14 @@ exports.PinoLoggerService = class PinoLoggerService {
244
332
  * @param metadata - Optional extra structured fields.
245
333
  */
246
334
  errorStructured(logKey, error, userId, metadata) {
247
- this.pino.error(
248
- { ...metadata, logKey, userId, context: this.context, err: this.serializeError(error) },
249
- error.message
250
- );
335
+ const payload = {
336
+ ...withoutOwnedKeys(metadata),
337
+ logKey,
338
+ err: this.serializeError(error)
339
+ };
340
+ assignIfDefined(payload, "userId", userId);
341
+ assignIfDefined(payload, "context", this.context);
342
+ this.pino.error(payload, safeErrorMessage(error));
251
343
  }
252
344
  // ─── Helpers / escape hatches ─────────────────────────────────────────────
253
345
  /**
@@ -280,7 +372,8 @@ exports.PinoLoggerService = class PinoLoggerService {
280
372
  * @returns A new `PinoLoggerService` wrapping the Pino child.
281
373
  */
282
374
  child(bindings) {
283
- const childService = new exports.PinoLoggerService(this.pino.child(bindings));
375
+ const safeBindings = this.redact(bindings, true);
376
+ const childService = new exports.PinoLoggerService(this.pino.child(safeBindings), this.redact);
284
377
  if (this.context !== void 0) {
285
378
  childService.setContext(this.context);
286
379
  }
@@ -305,7 +398,11 @@ exports.PinoLoggerService = class PinoLoggerService {
305
398
  * dashboards for every exception logged through `HttpExceptionFilter`.
306
399
  */
307
400
  serializeError(error) {
308
- return { type: error.name, message: error.message, stack: error.stack };
401
+ try {
402
+ return { type: error.name, message: error.message, stack: error.stack };
403
+ } catch {
404
+ return { type: "SanitizeFailed", message: "Failed to read the thrown value" };
405
+ }
309
406
  }
310
407
  /** Resolve the context: last string param wins, else the instance context. */
311
408
  resolveContext(optionalParams) {
@@ -314,12 +411,9 @@ exports.PinoLoggerService = class PinoLoggerService {
314
411
  }
315
412
  /** Emit a structured payload at info or warn level. */
316
413
  emitStructured(level, logKey, message, userId, metadata) {
317
- const payload = {
318
- ...metadata,
319
- logKey,
320
- userId,
321
- context: this.context
322
- };
414
+ const payload = { ...withoutOwnedKeys(metadata), logKey };
415
+ assignIfDefined(payload, "userId", userId);
416
+ assignIfDefined(payload, "context", this.context);
323
417
  if (level === "info") {
324
418
  this.pino.info(payload, message);
325
419
  } else {
@@ -328,7 +422,8 @@ exports.PinoLoggerService = class PinoLoggerService {
328
422
  }
329
423
  /** Emit a NestJS-style variadic log, dispatching by level without computed indexing. */
330
424
  emitNestStyle(level, message, optionalParams) {
331
- const payload = { context: this.resolveContext(optionalParams) };
425
+ const payload = {};
426
+ assignIfDefined(payload, "context", this.resolveContext(optionalParams));
332
427
  const msg = typeof message === "string" ? message : String(message);
333
428
  switch (level) {
334
429
  case "info":
@@ -351,7 +446,8 @@ exports.PinoLoggerService = class PinoLoggerService {
351
446
  };
352
447
  exports.PinoLoggerService = __decorateClass([
353
448
  common.Injectable(),
354
- __decorateParam(0, common.Inject(LOGGER_PINO_INSTANCE_TOKEN))
449
+ __decorateParam(0, common.Inject(LOGGER_PINO_INSTANCE_TOKEN)),
450
+ __decorateParam(1, common.Inject(LOGGER_REDACTOR_TOKEN))
355
451
  ], exports.PinoLoggerService);
356
452
 
357
453
  // src/server/decorators/inject-logger.provider.ts
@@ -401,26 +497,6 @@ exports.DefaultStdoutDestination = __decorateClass([
401
497
  common.Injectable()
402
498
  ], exports.DefaultStdoutDestination);
403
499
 
404
- // src/shared/constants/reserved-log-keys.constants.ts
405
- var RESERVED_LOG_KEYS = Object.freeze({
406
- LOGGER_BOOTSTRAP_OK: "LOGGER_BOOTSTRAP_OK",
407
- LOGGER_BOOTSTRAP_WARNING: "LOGGER_BOOTSTRAP_WARNING",
408
- LOGGER_SHUTDOWN_OK: "LOGGER_SHUTDOWN_OK",
409
- HTTP_REQUEST_START: "HTTP_REQUEST_START",
410
- HTTP_REQUEST_SUCCESS: "HTTP_REQUEST_SUCCESS",
411
- HTTP_REQUEST_REDIRECT: "HTTP_REQUEST_REDIRECT",
412
- HTTP_REQUEST_CLIENT_ERROR: "HTTP_REQUEST_CLIENT_ERROR",
413
- HTTP_REQUEST_SERVER_ERROR: "HTTP_REQUEST_SERVER_ERROR",
414
- HTTP_REQUEST_COMPLETED: "HTTP_REQUEST_COMPLETED",
415
- HTTP_EXCEPTION_HANDLED: "HTTP_EXCEPTION_HANDLED",
416
- HTTP_EXCEPTION_UNHANDLED: "HTTP_EXCEPTION_UNHANDLED",
417
- METHOD_EXECUTION: "METHOD_EXECUTION",
418
- METHOD_SLOW_EXECUTION: "METHOD_SLOW_EXECUTION",
419
- LOGGER_DESTINATION_INIT_FAILED: "LOGGER_DESTINATION_INIT_FAILED",
420
- LOGGER_DESTINATION_WRITE_FAILED: "LOGGER_DESTINATION_WRITE_FAILED",
421
- LOGGER_ENTRY_TRUNCATED: "LOGGER_ENTRY_TRUNCATED"
422
- });
423
-
424
500
  // src/server/utils/normalize-url.util.ts
425
501
  var UUID_REGEX = /\/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}(?![0-9a-f])/gi;
426
502
  var ULID_REGEX = /\/[0-9A-HJKMNP-TV-Z]{26}(?![0-9A-HJKMNP-TV-Z])/g;
@@ -561,11 +637,39 @@ exports.HttpExceptionFilter = __decorateClass([
561
637
  common.Catch(),
562
638
  __decorateParam(0, common.Inject(exports.PinoLoggerService))
563
639
  ], exports.HttpExceptionFilter);
564
- var HTTP_SUCCESS_MIN = 200;
640
+
641
+ // src/server/utils/http-log-state.util.ts
565
642
  var HTTP_REDIRECT_MIN = 300;
566
643
  var HTTP_CLIENT_ERROR_MIN = 400;
567
644
  var HTTP_SERVER_ERROR_MIN = 500;
568
645
  var UNKNOWN_USER_AGENT = "unknown";
646
+ var RECORDER_ACTIVE = /* @__PURE__ */ Symbol("bymax-one/nest-logger:recorder");
647
+ var RECORDED_ERROR = /* @__PURE__ */ Symbol("bymax-one/nest-logger:error");
648
+ function markRecorderActive(req) {
649
+ Reflect.set(req, RECORDER_ACTIVE, true);
650
+ }
651
+ function isRecorderActive(req) {
652
+ return Reflect.get(req, RECORDER_ACTIVE) === true;
653
+ }
654
+ function recordError(req, error) {
655
+ Reflect.set(req, RECORDED_ERROR, { error });
656
+ }
657
+ function readRecordedError(req) {
658
+ return Reflect.get(req, RECORDED_ERROR);
659
+ }
660
+ function toError(thrown) {
661
+ return thrown instanceof Error ? thrown : new Error(String(thrown));
662
+ }
663
+ function readUserId(req) {
664
+ return req.user?.sub ?? req.user?.id;
665
+ }
666
+ function readUserAgent(req) {
667
+ const raw = req.headers["user-agent"];
668
+ return typeof raw === "string" ? raw : UNKNOWN_USER_AGENT;
669
+ }
670
+
671
+ // src/server/interceptors/http-logging.interceptor.ts
672
+ var HTTP_SUCCESS_MIN = 200;
569
673
  exports.HttpLoggingInterceptor = class HttpLoggingInterceptor {
570
674
  /**
571
675
  * @param logger - The structured logger the lifecycle entries are written to.
@@ -599,13 +703,15 @@ exports.HttpLoggingInterceptor = class HttpLoggingInterceptor {
599
703
  const http = context.switchToHttp();
600
704
  const req = http.getRequest();
601
705
  const res = http.getResponse();
706
+ if (isRecorderActive(req)) {
707
+ return this.recordOnly(req, next);
708
+ }
602
709
  const { method, url, ip } = req;
603
710
  if (this.isExcluded(stripQueryString(url))) {
604
711
  return next.handle();
605
712
  }
606
- const rawUserAgent = req.headers["user-agent"];
607
- const userAgent = typeof rawUserAgent === "string" ? rawUserAgent : UNKNOWN_USER_AGENT;
608
- const userId = req.user?.sub ?? req.user?.id;
713
+ const userAgent = readUserAgent(req);
714
+ const userId = readUserId(req);
609
715
  const normalizedUrl = normalizeUrl(url);
610
716
  const start = Date.now();
611
717
  this.logger.info(RESERVED_LOG_KEYS.HTTP_REQUEST_START, `${method} ${normalizedUrl}`, userId, {
@@ -628,6 +734,28 @@ exports.HttpLoggingInterceptor = class HttpLoggingInterceptor {
628
734
  })
629
735
  );
630
736
  }
737
+ /**
738
+ * Hand the lifecycle to the access-log middleware, recording only the thrown
739
+ * error for its terminal entry.
740
+ *
741
+ * The interceptor cannot be the recorder: it never runs for a request a guard
742
+ * rejected or one that matched no route. It also cannot judge DELIVERY — at the
743
+ * moment it completes, the response has not been flushed yet, which is why an
744
+ * aborted request used to be logged as the 200 the handler intended. What it
745
+ * uniquely has is the thrown value, so that is all it contributes.
746
+ *
747
+ * @param req - The request whose lifecycle the middleware owns.
748
+ * @param next - The downstream call handler.
749
+ * @returns The response stream, unmodified and with exceptions re-thrown.
750
+ */
751
+ recordOnly(req, next) {
752
+ return next.handle().pipe(
753
+ rxjs.catchError((err) => {
754
+ recordError(req, toError(err));
755
+ return rxjs.throwError(() => err);
756
+ })
757
+ );
758
+ }
631
759
  /**
632
760
  * Log a non-throwing completion: SUCCESS for 2xx, REDIRECT for 3xx, nothing
633
761
  * for any other status (those are surfaced via the error path instead).
@@ -686,12 +814,12 @@ exports.HttpLoggingInterceptor = class HttpLoggingInterceptor {
686
814
  }
687
815
  return;
688
816
  }
689
- this.logger.errorStructured(
690
- RESERVED_LOG_KEYS.HTTP_REQUEST_SERVER_ERROR,
691
- err instanceof Error ? err : new Error(String(err)),
692
- userId,
693
- { method, url, statusCode: common.HttpStatus.INTERNAL_SERVER_ERROR, duration }
694
- );
817
+ this.logger.errorStructured(RESERVED_LOG_KEYS.HTTP_REQUEST_SERVER_ERROR, toError(err), userId, {
818
+ method,
819
+ url,
820
+ statusCode: common.HttpStatus.INTERNAL_SERVER_ERROR,
821
+ duration
822
+ });
695
823
  }
696
824
  };
697
825
  exports.HttpLoggingInterceptor = __decorateClass([
@@ -726,48 +854,6 @@ var {
726
854
  // disabled" without a dead nullish branch.
727
855
  global: extras.isGlobal !== false
728
856
  })).build();
729
- function detectOtelTraceApi() {
730
- try {
731
- const requireFromCwd = module$1.createRequire(path.join(process.cwd(), "noop.cjs"));
732
- const mod = requireFromCwd("@opentelemetry/api");
733
- return mod.trace;
734
- } catch {
735
- return void 0;
736
- }
737
- }
738
- function isValidTraceId(traceId) {
739
- return /^[0-9a-f]{32}$/.test(traceId) && !/^0+$/.test(traceId);
740
- }
741
- function isValidSpanId(spanId) {
742
- return /^[0-9a-f]{16}$/.test(spanId) && !/^0+$/.test(spanId);
743
- }
744
-
745
- // src/server/mixins/trace-context.mixin.ts
746
- function createTraceContextMixin(logContext, opts) {
747
- const traceApi = opts.shouldAutoInjectTraceContext ? detectOtelTraceApi() : void 0;
748
- return function mixin(_mergeObject, _level, _logger) {
749
- const merged = {};
750
- const store = logContext.getStore();
751
- if (store) {
752
- Object.assign(merged, store);
753
- }
754
- if (traceApi) {
755
- const span = traceApi.getActiveSpan();
756
- if (span) {
757
- const ctx = span.spanContext();
758
- if (isValidTraceId(ctx.traceId) && isValidSpanId(ctx.spanId)) {
759
- Reflect.set(merged, opts.traceIdField, ctx.traceId);
760
- Reflect.set(merged, opts.spanIdField, ctx.spanId);
761
- if (typeof ctx.traceFlags === "number") {
762
- const flagsByte = ctx.traceFlags & 255;
763
- Reflect.set(merged, opts.traceFlagsField, flagsByte.toString(16).padStart(2, "0"));
764
- }
765
- }
766
- }
767
- }
768
- return merged;
769
- };
770
- }
771
857
 
772
858
  // src/server/constants/default-redact-paths.constants.ts
773
859
  var REDACT_MAX_DEPTH = 4;
@@ -810,7 +896,20 @@ var REDACT_COMMON_FIELDS = [
810
896
  "signingSecret",
811
897
  "privateKey",
812
898
  // Conservative PII (1) — consumer can disable if logging email is justified
813
- "email"
899
+ "email",
900
+ // Credential-bearing HTTP header names (5). These also appear in
901
+ // {@link REDACT_ABSOLUTE_PATHS}, pinned to the `req.headers` / `res.headers`
902
+ // shapes — which covered ONLY those two shapes. A headers bag logged under any
903
+ // other key (`logger.info(k, m, u, { headers: req.headers })`, one of the most
904
+ // common things written while debugging an integration) wrote the bearer token
905
+ // in clear. Listed here as bare names, they are caught wherever they appear.
906
+ // Node lower-cases inbound header names, so the lower-case spelling is the one
907
+ // that can actually reach a log.
908
+ "authorization",
909
+ "cookie",
910
+ "set-cookie",
911
+ "x-api-key",
912
+ "x-auth-token"
814
913
  ];
815
914
  var REDACT_ABSOLUTE_PATHS = [
816
915
  "req.headers.authorization",
@@ -824,6 +923,48 @@ var DEFAULT_REDACT_PATHS = [
824
923
  ...REDACT_COMMON_FIELDS.flatMap((field) => depth(field)),
825
924
  ...REDACT_ABSOLUTE_PATHS
826
925
  ];
926
+ function detectOtelTraceApi() {
927
+ try {
928
+ const requireFromCwd = module$1.createRequire(path.join(process.cwd(), "noop.cjs"));
929
+ const mod = requireFromCwd("@opentelemetry/api");
930
+ return mod.trace;
931
+ } catch {
932
+ return void 0;
933
+ }
934
+ }
935
+ function isValidTraceId(traceId) {
936
+ return /^[0-9a-f]{32}$/.test(traceId) && !/^0+$/.test(traceId);
937
+ }
938
+ function isValidSpanId(spanId) {
939
+ return /^[0-9a-f]{16}$/.test(spanId) && !/^0+$/.test(spanId);
940
+ }
941
+
942
+ // src/server/mixins/trace-context.mixin.ts
943
+ function createTraceContextMixin(logContext, opts) {
944
+ const traceApi = opts.shouldAutoInjectTraceContext ? detectOtelTraceApi() : void 0;
945
+ return function mixin(_mergeObject, _level, _logger) {
946
+ const merged = {};
947
+ const store = logContext.getStore();
948
+ if (store) {
949
+ Object.assign(merged, store);
950
+ }
951
+ if (traceApi) {
952
+ const span = traceApi.getActiveSpan();
953
+ if (span) {
954
+ const ctx = span.spanContext();
955
+ if (isValidTraceId(ctx.traceId) && isValidSpanId(ctx.spanId)) {
956
+ Reflect.set(merged, opts.traceIdField, ctx.traceId);
957
+ Reflect.set(merged, opts.spanIdField, ctx.spanId);
958
+ if (typeof ctx.traceFlags === "number") {
959
+ const flagsByte = ctx.traceFlags & 255;
960
+ Reflect.set(merged, opts.traceFlagsField, flagsByte.toString(16).padStart(2, "0"));
961
+ }
962
+ }
963
+ }
964
+ }
965
+ return merged;
966
+ };
967
+ }
827
968
 
828
969
  // src/server/utils/compile-redact-paths.util.ts
829
970
  function compileRedactPaths(extraPaths, shouldSkipDefaults) {
@@ -872,6 +1013,120 @@ function destinationToStream(destination) {
872
1013
  });
873
1014
  }
874
1015
 
1016
+ // src/server/utils/redact-by-name.util.ts
1017
+ var REDACT_MAX_TRAVERSAL_DEPTH = 100;
1018
+ var REDACT_DEPTH_EXCEEDED = "[REDACTION_DEPTH_EXCEEDED]";
1019
+ var REDACT_CIRCULAR = "[Circular]";
1020
+ function resolveToJson(value) {
1021
+ let getter;
1022
+ let candidate;
1023
+ let current = value;
1024
+ while (current !== null) {
1025
+ const descriptor = Object.getOwnPropertyDescriptor(current, "toJSON");
1026
+ if (descriptor !== void 0) {
1027
+ getter = descriptor.get;
1028
+ candidate = getter === void 0 ? descriptor.value : getter.call(value);
1029
+ break;
1030
+ }
1031
+ current = Object.getPrototypeOf(current);
1032
+ }
1033
+ return {
1034
+ method: typeof candidate === "function" ? candidate : void 0,
1035
+ fromAccessor: getter !== void 0
1036
+ };
1037
+ }
1038
+ function cloneError(error) {
1039
+ const clone = Object.create(
1040
+ Object.getPrototypeOf(error),
1041
+ Object.getOwnPropertyDescriptors(error)
1042
+ );
1043
+ const { stack } = error;
1044
+ if (typeof stack === "string") {
1045
+ Reflect.defineProperty(clone, "stack", { value: stack, enumerable: false });
1046
+ }
1047
+ return clone;
1048
+ }
1049
+ var BUFFER_TO_JSON = Buffer.prototype.toJSON;
1050
+ var WRITE_FAILED = new Error();
1051
+ function defineOwn(target, key, value) {
1052
+ if (!Reflect.defineProperty(target, key, { value, enumerable: true })) {
1053
+ throw WRITE_FAILED;
1054
+ }
1055
+ }
1056
+ function walkArray(value, sensitive, censor, depth2, ancestors) {
1057
+ const length = value.length;
1058
+ const copy = [];
1059
+ for (let index = 0; index < length; index++) {
1060
+ Reflect.set(
1061
+ copy,
1062
+ index,
1063
+ walk(Reflect.get(value, index), sensitive, censor, depth2 + 1, ancestors)
1064
+ );
1065
+ }
1066
+ return copy;
1067
+ }
1068
+ function walk(value, sensitive, censor, depth2, ancestors, honorToJson = true) {
1069
+ if (value === null) {
1070
+ return value;
1071
+ }
1072
+ if (typeof value !== "object" && typeof value !== "function") {
1073
+ return value;
1074
+ }
1075
+ if (depth2 > REDACT_MAX_TRAVERSAL_DEPTH) {
1076
+ return REDACT_DEPTH_EXCEEDED;
1077
+ }
1078
+ if (ancestors.has(value)) {
1079
+ return REDACT_CIRCULAR;
1080
+ }
1081
+ const resolvedToJson = resolveToJson(value);
1082
+ if (!resolvedToJson.fromAccessor && resolvedToJson.method === BUFFER_TO_JSON) {
1083
+ return value;
1084
+ }
1085
+ ancestors.add(value);
1086
+ try {
1087
+ const toJson = honorToJson ? resolvedToJson.method : void 0;
1088
+ if (toJson !== void 0) {
1089
+ if (Object.keys(value).some((key) => sensitive.has(key.toLowerCase()))) {
1090
+ return censor;
1091
+ }
1092
+ return walk(toJson.call(value), sensitive, censor, depth2 + 1, ancestors);
1093
+ }
1094
+ if (typeof value === "function") {
1095
+ return value;
1096
+ }
1097
+ if (Array.isArray(value)) {
1098
+ return walkArray(value, sensitive, censor, depth2, ancestors);
1099
+ }
1100
+ const source = value;
1101
+ const keys = Object.keys(source);
1102
+ const copy = value instanceof Error ? cloneError(value) : {};
1103
+ for (const key of keys) {
1104
+ const current = Reflect.get(source, key);
1105
+ defineOwn(
1106
+ copy,
1107
+ key,
1108
+ sensitive.has(key.toLowerCase()) ? censor : walk(current, sensitive, censor, depth2 + 1, ancestors)
1109
+ );
1110
+ }
1111
+ return copy;
1112
+ } finally {
1113
+ ancestors.delete(value);
1114
+ }
1115
+ }
1116
+ function createNameRedactor(fieldNames, censor) {
1117
+ const sensitive = new Set(fieldNames.map((name) => name.toLowerCase()));
1118
+ return (value, isRecordRoot = false) => {
1119
+ try {
1120
+ return walk(value, sensitive, censor, 0, /* @__PURE__ */ new Set(), !isRecordRoot);
1121
+ } catch {
1122
+ return {
1123
+ _redactionFailed: true,
1124
+ _logKey: RESERVED_LOG_KEYS.LOGGER_REDACTION_FAILED
1125
+ };
1126
+ }
1127
+ };
1128
+ }
1129
+
875
1130
  // src/server/utils/truncate-large-entries.ts
876
1131
  var PREVIEW_LENGTH = 200;
877
1132
  function createSizeBoundedSerializer(baseSerializer, maxBytes) {
@@ -900,25 +1155,56 @@ function createSizeBoundedSerializer(baseSerializer, maxBytes) {
900
1155
  }
901
1156
 
902
1157
  // src/server/pino-factory.ts
1158
+ var PATH_SEGMENT = /\[\s*['"]([^'"]+)['"]\s*\]|([^.[\]]+)/g;
1159
+ var INDEX_SEGMENT = /^\d+$/;
1160
+ function leafNameOf(path) {
1161
+ let leaf;
1162
+ for (const match of path.matchAll(PATH_SEGMENT)) {
1163
+ const quoted = match[1];
1164
+ const name = quoted ?? (match[2] !== void 0 && INDEX_SEGMENT.test(match[2]) ? void 0 : match[2]);
1165
+ if (name !== void 0 && name !== "*") {
1166
+ leaf = name;
1167
+ }
1168
+ }
1169
+ return leaf;
1170
+ }
1171
+ var PASS_THROUGH = (value) => value;
1172
+ function resolveNameRedactor(options) {
1173
+ if (options.redactStrategy !== "names") {
1174
+ return PASS_THROUGH;
1175
+ }
1176
+ const names = [
1177
+ ...options.shouldDisableDefaultRedact ? [] : REDACT_COMMON_FIELDS,
1178
+ ...options.redactPaths.flatMap((path) => leafNameOf(path) ?? [])
1179
+ ];
1180
+ if (names.length === 0) {
1181
+ return PASS_THROUGH;
1182
+ }
1183
+ return createNameRedactor(names, options.redactCensor);
1184
+ }
1185
+ function resolveRedactOption(options) {
1186
+ const paths = options.redactStrategy === "paths" ? compileRedactPaths(options.redactPaths, options.shouldDisableDefaultRedact) : [...new Set(options.redactPaths)];
1187
+ if (paths.length === 0) {
1188
+ return void 0;
1189
+ }
1190
+ return { paths, censor: options.redactCensor };
1191
+ }
903
1192
  function buildPinoInstance(options, logContext, destinations) {
904
1193
  const maxBytes = options.maxEntrySizeBytes;
1194
+ const redact = resolveNameRedactor(options);
1195
+ const bound = (serializer) => createSizeBoundedSerializer((input) => redact(serializer(input)), maxBytes);
905
1196
  const serializers = {
906
- err: createSizeBoundedSerializer(pino__default.default.stdSerializers.err, maxBytes),
1197
+ err: bound(pino__default.default.stdSerializers.err),
907
1198
  ...Object.fromEntries(
908
1199
  Object.entries(options.serializers).map(
909
- ([key, serializer]) => [
910
- key,
911
- createSizeBoundedSerializer(serializer, maxBytes)
912
- ]
1200
+ ([key, serializer]) => [key, bound(serializer)]
913
1201
  )
914
1202
  )
915
1203
  };
1204
+ const redactOption = resolveRedactOption(options);
916
1205
  const pinoOptions = {
917
1206
  level: options.level,
918
- redact: {
919
- paths: compileRedactPaths(options.redactPaths, options.shouldDisableDefaultRedact),
920
- censor: options.redactCensor
921
- },
1207
+ ...redactOption === void 0 ? {} : { redact: redactOption },
922
1208
  base: { service: options.service },
923
1209
  // Pino requires the timestamp fn to emit the `,"time":"..."` fragment.
924
1210
  timestamp: () => `,"time":"${options.timestamp()}"`,
@@ -926,10 +1212,42 @@ function buildPinoInstance(options, logContext, destinations) {
926
1212
  // Emit the level as a string label instead of the numeric code — easier
927
1213
  // for log aggregators. Trace context is injected via `mixin`, never via
928
1214
  // `formatters.log` (which cannot see ambient ALS / OTel state).
929
- level: (label) => ({ level: label })
1215
+ level: (label) => ({ level: label }),
1216
+ // `base` bindings never reach `formatters.log` — Pino pre-serializes them
1217
+ // into the instance's `chindings`, the same reason `child()` has to redact
1218
+ // its own. That matters because `service` is CONSUMER-supplied and
1219
+ // `applyDefaults` keeps whatever it was given: a `{ name, version, apiKey }`
1220
+ // went out in clear, where the path expansion had covered it via `*.*.apiKey`.
1221
+ // Redacting here rather than trimming to the two declared fields keeps a
1222
+ // consumer's extra metadata instead of silently dropping it. Runs ONCE, at
1223
+ // logger construction — no per-entry cost. `true`: bindings are a record
1224
+ // root, iterated rather than serialized.
1225
+ bindings: (bindings) => redact(bindings, true),
1226
+ // The name-walk redactor runs here, on the merged record (mixin output +
1227
+ // the caller's object), which is exactly the surface a caller controls.
1228
+ // `base` and child bindings are NOT visible at this hook — they are
1229
+ // library-owned (`service`, the `@InjectLogger` context) and carry nothing
1230
+ // sensitive, which `pino-factory.spec.ts` pins.
1231
+ log: (record) => redact(record, true)
930
1232
  },
931
1233
  serializers,
932
- mixin: createTraceContextMixin(logContext, options.otel)
1234
+ mixin: createTraceContextMixin(logContext, options.otel),
1235
+ // `formatters.log` is NOT the first code to touch the caller's object: Pino
1236
+ // merges the mixin result with it first, and the default strategy's
1237
+ // `Object.assign` invokes every own getter. A throwing getter therefore
1238
+ // crashed the log call before the redactor could return its fail-closed
1239
+ // envelope. Owning the merge moves that boundary inside the guarantee.
1240
+ mixinMergeStrategy: (mergeObject, mixinObject) => {
1241
+ try {
1242
+ return Object.assign({}, mixinObject, mergeObject);
1243
+ } catch {
1244
+ return {
1245
+ ...mixinObject,
1246
+ _redactionFailed: true,
1247
+ _logKey: RESERVED_LOG_KEYS.LOGGER_REDACTION_FAILED
1248
+ };
1249
+ }
1250
+ }
933
1251
  };
934
1252
  const streams = destinations.map((destination) => ({
935
1253
  level: destination.minLevel ?? options.level,
@@ -945,9 +1263,10 @@ var DestinationRegistry = class {
945
1263
  * @param logger - Structured logger used to report init failures. Injected by
946
1264
  * token explicitly for the same bundling reason.
947
1265
  */
948
- constructor(registered, logger) {
1266
+ constructor(registered, logger, options) {
949
1267
  this.registered = registered;
950
1268
  this.logger = logger;
1269
+ this.options = options;
951
1270
  /**
952
1271
  * Destinations that initialized successfully, in registration order.
953
1272
  *
@@ -979,6 +1298,35 @@ var DestinationRegistry = class {
979
1298
  );
980
1299
  }
981
1300
  }
1301
+ this.announceBootstrap();
1302
+ }
1303
+ /**
1304
+ * Emit the one-shot bootstrap entries, AFTER every destination has been
1305
+ * initialized.
1306
+ *
1307
+ * Ordering is the whole point of doing this here rather than from an eagerly
1308
+ * instantiated provider factory: a provider factory runs while Nest is still
1309
+ * building the graph, before `onModuleInit`, so a sink that only accepts
1310
+ * writes once its own `onInit()` has run would drop these entries — including
1311
+ * `LOGGER_BOOTSTRAP_WARNING`, which exists precisely so a security review can
1312
+ * see that PII redaction was turned off. A signal that a custom destination
1313
+ * can silently swallow is not an audit trail. Emitting from the registry that
1314
+ * owns destination initialization makes the ordering structural instead of a
1315
+ * cross-provider hook-order assumption.
1316
+ */
1317
+ announceBootstrap() {
1318
+ this.logger.info(RESERVED_LOG_KEYS.LOGGER_BOOTSTRAP_OK, "BymaxLoggerModule initialized");
1319
+ if (this.options.shouldDisableDefaultRedact) {
1320
+ this.logger.warnStructured(
1321
+ RESERVED_LOG_KEYS.LOGGER_BOOTSTRAP_WARNING,
1322
+ "Default PII redaction is DISABLED \u2014 sensitive fields will be logged verbatim unless every one of them is listed in options.redactPaths",
1323
+ void 0,
1324
+ {
1325
+ shouldDisableDefaultRedact: true,
1326
+ redactPathCount: this.options.redactPaths.length
1327
+ }
1328
+ );
1329
+ }
982
1330
  }
983
1331
  /**
984
1332
  * Flush and close active destinations in REVERSE registration order, so a
@@ -987,6 +1335,15 @@ var DestinationRegistry = class {
987
1335
  * point in the shutdown sequence.
988
1336
  */
989
1337
  async onApplicationShutdown() {
1338
+ this.logger.info(
1339
+ RESERVED_LOG_KEYS.LOGGER_SHUTDOWN_OK,
1340
+ "BymaxLoggerModule shutting down",
1341
+ void 0,
1342
+ { destinations: this.active.length }
1343
+ );
1344
+ await new Promise((resolve) => {
1345
+ setImmediate(resolve);
1346
+ });
990
1347
  for (const destination of [...this.active].reverse()) {
991
1348
  try {
992
1349
  await destination.onShutdown?.();
@@ -1011,9 +1368,10 @@ var DestinationRegistry = class {
1011
1368
  DestinationRegistry = __decorateClass([
1012
1369
  common.Injectable(),
1013
1370
  __decorateParam(0, common.Inject(LOGGER_DESTINATIONS_TOKEN)),
1014
- __decorateParam(1, common.Inject(exports.PinoLoggerService))
1371
+ __decorateParam(1, common.Inject(exports.PinoLoggerService)),
1372
+ __decorateParam(2, common.Inject(LOGGER_OPTIONS_TOKEN))
1015
1373
  ], DestinationRegistry);
1016
- var FORBIDDEN_CONTEXT_KEYS = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
1374
+ var FORBIDDEN_CONTEXT_KEYS = PROTOTYPE_POLLUTING_KEYS;
1017
1375
  exports.LogContextService = class LogContextService {
1018
1376
  constructor() {
1019
1377
  this.als = new async_hooks.AsyncLocalStorage();
@@ -1099,24 +1457,21 @@ exports.LogContextService = __decorateClass([
1099
1457
  ], exports.LogContextService);
1100
1458
 
1101
1459
  // src/server/logger.module.ts
1102
- var LOGGER_BOOTSTRAP_TOKEN = /* @__PURE__ */ Symbol("BYMAX_LOGGER_BOOTSTRAP");
1103
1460
  function resolveDestinations(options) {
1104
1461
  return options.destinations.length > 0 ? options.destinations : [new exports.DefaultStdoutDestination()];
1105
1462
  }
1106
- function bootstrapProvider() {
1107
- return {
1108
- provide: LOGGER_BOOTSTRAP_TOKEN,
1109
- useFactory: (logger) => {
1110
- logger.info(RESERVED_LOG_KEYS.LOGGER_BOOTSTRAP_OK, "BymaxLoggerModule initialized");
1111
- return true;
1112
- },
1113
- inject: [exports.PinoLoggerService]
1114
- };
1115
- }
1116
1463
  function buildCommonProviders() {
1117
1464
  return [
1118
1465
  exports.LogContextService,
1119
1466
  { provide: LOG_CONTEXT_TOKEN, useExisting: exports.LogContextService },
1467
+ {
1468
+ // The DEFAULT-coverage redactor, shared by the Pino factory's hooks and by
1469
+ // `PinoLoggerService.child()`. The latter needs it as a provider because
1470
+ // Pino pre-serializes child bindings before `formatters.log` can see them.
1471
+ provide: LOGGER_REDACTOR_TOKEN,
1472
+ useFactory: (options) => resolveNameRedactor(options),
1473
+ inject: [LOGGER_OPTIONS_TOKEN]
1474
+ },
1120
1475
  {
1121
1476
  provide: LOGGER_PINO_INSTANCE_TOKEN,
1122
1477
  useFactory: (options, logContext, destinations) => buildPinoInstance(options, logContext, destinations),
@@ -1132,8 +1487,7 @@ function buildCommonProviders() {
1132
1487
  // exported — consumers never inject it directly.
1133
1488
  DestinationRegistry,
1134
1489
  // One child-logger provider per context discovered from @InjectLogger(context).
1135
- ...collectContextLoggerProviders(),
1136
- bootstrapProvider()
1490
+ ...collectContextLoggerProviders()
1137
1491
  ];
1138
1492
  }
1139
1493
  function asyncHttpInterceptorProvider() {
@@ -1153,6 +1507,7 @@ function augmentLoggerModule(base, providers) {
1153
1507
  LOGGER_OPTIONS_TOKEN,
1154
1508
  LOGGER_PINO_INSTANCE_TOKEN,
1155
1509
  LOGGER_DESTINATIONS_TOKEN,
1510
+ LOGGER_REDACTOR_TOKEN,
1156
1511
  LOG_CONTEXT_TOKEN,
1157
1512
  exports.LogContextService,
1158
1513
  exports.PinoLoggerService,
@@ -1343,6 +1698,119 @@ var PrettyDevDestination = class {
1343
1698
  });
1344
1699
  }
1345
1700
  };
1701
+ var HttpAccessLogMiddleware = class {
1702
+ /**
1703
+ * @param logger - The structured logger the access entries are written to.
1704
+ * Injected by token explicitly: the package is bundled without
1705
+ * `emitDecoratorMetadata`, so implicit class-type injection would not resolve.
1706
+ * @param options - Resolved module options (read for `http.excludePaths`).
1707
+ */
1708
+ constructor(logger, options) {
1709
+ this.logger = logger;
1710
+ this.isEnabled = options.http.isEnabled;
1711
+ this.excludePaths = options.http.excludePaths;
1712
+ }
1713
+ /**
1714
+ * Emit START, arm the terminal entry on `'close'`, and continue the chain.
1715
+ *
1716
+ * @param req - The incoming request (Express satisfies the contract).
1717
+ * @param res - The outgoing response (Express satisfies the contract).
1718
+ * @param next - The next handler in the chain.
1719
+ */
1720
+ use(req, res, next) {
1721
+ if (!this.isEnabled) {
1722
+ next();
1723
+ return;
1724
+ }
1725
+ const target = req.originalUrl ?? req.url;
1726
+ const path = stripQueryString(target);
1727
+ if (this.excludePaths.some((pattern) => pattern.test(path))) {
1728
+ next();
1729
+ return;
1730
+ }
1731
+ markRecorderActive(req);
1732
+ const method = req.method;
1733
+ const url = normalizeUrl(target);
1734
+ const start = Date.now();
1735
+ this.logger.info(RESERVED_LOG_KEYS.HTTP_REQUEST_START, `${method} ${url}`, readUserId(req), {
1736
+ method,
1737
+ url,
1738
+ // Query string stripped: it may carry secrets (reset tokens, OAuth codes)
1739
+ // that no key-name redaction can scrub out of a string VALUE.
1740
+ fullUrl: path,
1741
+ // Conventional for an access log and personal data under GDPR/LGPD. Its
1742
+ // fidelity is the app's to establish: behind a proxy it is only the real
1743
+ // client when the app configures `trust proxy`, and a value the app has not
1744
+ // established is attacker-chosen. Suppress with `redactPaths: ['ip']`.
1745
+ ip: req.ip,
1746
+ userAgent: readUserAgent(req)
1747
+ });
1748
+ res.on(
1749
+ "close",
1750
+ async_hooks.AsyncResource.bind(() => {
1751
+ this.logTerminal(req, res, method, url, Date.now() - start);
1752
+ })
1753
+ );
1754
+ next();
1755
+ }
1756
+ /**
1757
+ * Emit the terminal entry for a closed request.
1758
+ *
1759
+ * `userId` is read HERE rather than at START because authentication runs in a
1760
+ * guard, downstream of this middleware — at START there is no principal yet.
1761
+ *
1762
+ * @param req - The request, carrying any error the interceptor recorded.
1763
+ * @param res - The closed response.
1764
+ * @param method - The HTTP method.
1765
+ * @param url - The normalized request URL.
1766
+ * @param duration - Elapsed milliseconds.
1767
+ */
1768
+ logTerminal(req, res, method, url, duration) {
1769
+ const statusCode = res.statusCode;
1770
+ const userId = readUserId(req);
1771
+ const meta = { method, url, statusCode, duration };
1772
+ if (!res.writableFinished) {
1773
+ this.logger.warnStructured(
1774
+ RESERVED_LOG_KEYS.HTTP_REQUEST_ABORTED,
1775
+ `${method} ${url} \u2192 ${statusCode} not delivered (${duration}ms)`,
1776
+ userId,
1777
+ meta
1778
+ );
1779
+ return;
1780
+ }
1781
+ if (statusCode >= HTTP_SERVER_ERROR_MIN) {
1782
+ const recorded = readRecordedError(req);
1783
+ this.logger.errorStructured(
1784
+ RESERVED_LOG_KEYS.HTTP_REQUEST_SERVER_ERROR,
1785
+ recorded?.error ?? new Error(`${method} ${url} \u2192 ${statusCode}`),
1786
+ userId,
1787
+ meta
1788
+ );
1789
+ return;
1790
+ }
1791
+ if (statusCode >= HTTP_CLIENT_ERROR_MIN) {
1792
+ const recorded = readRecordedError(req);
1793
+ this.logger.warnStructured(
1794
+ RESERVED_LOG_KEYS.HTTP_REQUEST_CLIENT_ERROR,
1795
+ `${method} ${url} \u2192 ${statusCode}`,
1796
+ userId,
1797
+ recorded === void 0 ? meta : { ...meta, errorMessage: recorded.error.message }
1798
+ );
1799
+ return;
1800
+ }
1801
+ this.logger.info(
1802
+ statusCode >= HTTP_REDIRECT_MIN ? RESERVED_LOG_KEYS.HTTP_REQUEST_REDIRECT : RESERVED_LOG_KEYS.HTTP_REQUEST_SUCCESS,
1803
+ `${method} ${url} \u2192 ${statusCode} (${duration}ms)`,
1804
+ userId,
1805
+ meta
1806
+ );
1807
+ }
1808
+ };
1809
+ HttpAccessLogMiddleware = __decorateClass([
1810
+ common.Injectable(),
1811
+ __decorateParam(0, common.Inject(exports.PinoLoggerService)),
1812
+ __decorateParam(1, common.Inject(LOGGER_OPTIONS_TOKEN))
1813
+ ], HttpAccessLogMiddleware);
1346
1814
  var REQUEST_ID_HEADER = "x-request-id";
1347
1815
  var MAX_CORRELATION_ID_LENGTH = 256;
1348
1816
  var CORRELATION_ID_CHARSET = /^[A-Za-z0-9._:/+=-]+$/;
@@ -1393,9 +1861,9 @@ exports.RequestIdMiddleware = __decorateClass([
1393
1861
  ], exports.RequestIdMiddleware);
1394
1862
 
1395
1863
  // src/server/middlewares/apply-request-id-middleware.ts
1396
- var ALL_ROUTES = "*";
1864
+ var ALL_ROUTES = "/";
1397
1865
  function applyRequestIdMiddleware(consumer, routes = ALL_ROUTES) {
1398
- consumer.apply(exports.RequestIdMiddleware).forRoutes(routes);
1866
+ consumer.apply(exports.RequestIdMiddleware, HttpAccessLogMiddleware).forRoutes(routes);
1399
1867
  }
1400
1868
  var INJECT_LOGGER_CONTEXT_METADATA_KEY = "bymax_logger:context";
1401
1869
  function InjectLogger(context) {
@@ -1468,6 +1936,9 @@ exports.LOG_CONTEXT_TOKEN = LOG_CONTEXT_TOKEN;
1468
1936
  exports.LOG_KEYS_CONVENTION_REGEX = LOG_KEYS_CONVENTION_REGEX;
1469
1937
  exports.LogContext = LogContext;
1470
1938
  exports.LogPerformance = LogPerformance;
1939
+ exports.PINO_LEVEL_NAMES = PINO_LEVEL_NAMES;
1940
+ exports.PINO_LEVEL_NUMBERS = PINO_LEVEL_NUMBERS;
1471
1941
  exports.PrettyDevDestination = PrettyDevDestination;
1472
1942
  exports.RESERVED_LOG_KEYS = RESERVED_LOG_KEYS;
1943
+ exports.RESERVED_LOG_KEYS_NOT_EMITTED = RESERVED_LOG_KEYS_NOT_EMITTED;
1473
1944
  exports.applyRequestIdMiddleware = applyRequestIdMiddleware;