@bymax-one/nest-logger 1.4.1 → 1.4.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +173 -5
- package/README.md +183 -81
- package/dist/server/index.cjs +159 -6
- package/dist/server/index.d.cts +75 -22
- package/dist/server/index.d.ts +75 -22
- package/dist/server/index.mjs +157 -7
- package/dist/shared/index.d.cts +2 -1
- package/dist/shared/index.d.ts +2 -1
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -11,6 +11,163 @@ heading here.
|
|
|
11
11
|
|
|
12
12
|
## [Unreleased]
|
|
13
13
|
|
|
14
|
+
## [1.4.3] - 2026-10-31
|
|
15
|
+
|
|
16
|
+
### Added
|
|
17
|
+
|
|
18
|
+
- `LOGGER_REDACTOR_TOKEN`, `REDACT_COMMON_FIELDS` and `isValidTraceId` are exported from the package
|
|
19
|
+
root. The token is the injection point of `PinoLoggerService`'s redactor, so a consumer composing
|
|
20
|
+
its own providers can now name it. `REDACT_COMMON_FIELDS` is the name list the
|
|
21
|
+
default redactor matches, and `DEFAULT_REDACT_PATHS` is built from it, so extending the defaults no
|
|
22
|
+
longer means copying the names. `isValidTraceId` is the check the trace mixin already applies.
|
|
23
|
+
`sanitizeError` stays internal: its output shape is not a contract this release commits to.
|
|
24
|
+
|
|
25
|
+
### Deprecated
|
|
26
|
+
|
|
27
|
+
- `@LogContext(name)` is marked `@deprecated`. It records a label as class metadata and nothing in
|
|
28
|
+
the package reads it, so the label has never been applied. `@InjectLogger(MyClass.name)` is the
|
|
29
|
+
working equivalent. `shouldUseAsNestLogger` was already deprecated and is unchanged.
|
|
30
|
+
|
|
31
|
+
### Fixed
|
|
32
|
+
|
|
33
|
+
- **A custom `timestamp` can no longer break the log line or add fields to it.** Pino inserts the
|
|
34
|
+
value into the JSON line verbatim, and the library wrapped it in quotes without encoding it, so a
|
|
35
|
+
quote, a backslash or a newline in the returned string produced invalid JSON for every entry, and a
|
|
36
|
+
crafted value such as `","injected":"x` added a field. The value is now encoded as a JSON string,
|
|
37
|
+
and `time` carries exactly what the function returned.
|
|
38
|
+
|
|
39
|
+
### Breaking
|
|
40
|
+
|
|
41
|
+
- **`http.excludePaths` now excludes `/health/live` and `/health/ready` by default**, the probes of
|
|
42
|
+
`@bymax-one/nest-core`, so the defaults are `/health`, `/health/live`, `/health/ready` and
|
|
43
|
+
`/metrics`. A probe hit every few seconds drowned the record (8272 of 8274 entries on one
|
|
44
|
+
deployment). Each default is an exact, anchored path, so a route such as `/health/other` is still
|
|
45
|
+
logged.
|
|
46
|
+
- **Options are validated more strictly at bootstrap**, each rejection naming the option and, where
|
|
47
|
+
there is a value to show, what was received. Added checks: `maxEntrySizeBytes` must be a finite number (a `NaN` or `Infinity`
|
|
48
|
+
made the size gate never trip); `isGlobal`, `shouldDisableDefaultRedact` and the `http` and `otel`
|
|
49
|
+
switches must be booleans (the string `'false'` is truthy); `redactCensor` a string; `timestamp` a
|
|
50
|
+
function; `redactPaths` an array of non-empty strings; `serializers` an object of functions;
|
|
51
|
+
`destinations` an array whose entries have a `write` method, a non-empty `name` and function hooks;
|
|
52
|
+
`http` and `otel` objects; `http.excludePaths` an array of `RegExp` (a pattern from another realm,
|
|
53
|
+
such as a `vm` context, is accepted); `http.tenantIdHeader` and the
|
|
54
|
+
three `otel.*Field` names non-empty strings; `otel.fieldFormat` `'camelCase'` or `'snake_case'`
|
|
55
|
+
(an unknown value silently behaved as `camelCase`).
|
|
56
|
+
- **`PrettyDevDestination` refuses to initialize when `NODE_ENV` is `production`.** The 0.1.0 entry
|
|
57
|
+
said it was auto-disabled in production, and nothing did that: registered there it rendered ANSI
|
|
58
|
+
colour through a main-thread transform into the log stream. It now fails at `onInit()` with a
|
|
59
|
+
message naming the cause; the registry reports `LOGGER_DESTINATION_INIT_FAILED` on stderr, later
|
|
60
|
+
writes to it are dropped, and when it is the only destination entries go to stdout as raw NDJSON.
|
|
61
|
+
Only the exact value `production` refuses.
|
|
62
|
+
|
|
63
|
+
#### Apply to a consumer
|
|
64
|
+
|
|
65
|
+
- A deployment whose own `/health/live` or `/health/ready` route should stay in the log now sets
|
|
66
|
+
`http.excludePaths` itself. A value replaces the defaults, and `[/^\/health$/, /^\/metrics$/]`
|
|
67
|
+
restores the previous list.
|
|
68
|
+
- An application that passed a value of the wrong kind, such as `http: { isEnabled: 'false' }` or a
|
|
69
|
+
destination without a `name`, now fails at bootstrap with a message naming the option, where it
|
|
70
|
+
previously booted with that value ignored or misread. Correct the value.
|
|
71
|
+
- A deployment that registers `PrettyDevDestination` with `NODE_ENV=production` now gets raw JSON on
|
|
72
|
+
stdout and one stderr line instead of coloured output. Register it only outside production, for
|
|
73
|
+
example `...(process.env.NODE_ENV === 'production' ? [] : [new PrettyDevDestination()])`, and keep
|
|
74
|
+
`DefaultStdoutDestination` in the list.
|
|
75
|
+
|
|
76
|
+
### Documentation
|
|
77
|
+
|
|
78
|
+
- The error catalog listed codes that nothing in the library emits (for example
|
|
79
|
+
`LOGGER_INVALID_OPTIONS` and `LOGGER_OTEL_API_UNAVAILABLE`), and described them as thrown. A thrown
|
|
80
|
+
error carries a message, not a code, so the catalog now separates the message each thrown error
|
|
81
|
+
starts with from the log keys the library writes. It also gains the errors it omitted and the real
|
|
82
|
+
surface of a missing `@opentelemetry/api`, a `LOGGER_BOOTSTRAP_WARNING` with
|
|
83
|
+
`reason: 'OTEL_API_UNAVAILABLE'`.
|
|
84
|
+
`readme-error-catalog.spec.ts` scans every throw site in `src` and fails when a row and the code
|
|
85
|
+
disagree in either direction.
|
|
86
|
+
- The README documents the injection tokens and the exported helpers, the `useClass` and
|
|
87
|
+
`useExisting` forms of `forRootAsync`, the rules the request-id middleware applies to an inbound
|
|
88
|
+
`x-request-id` and tenant header (a value that fails them is replaced, not cleaned), and that a
|
|
89
|
+
Fastify adapter is not supported.
|
|
90
|
+
- `forRootAsync` does not register the exception filter, which `forRoot` does, and the README now
|
|
91
|
+
says so under the async example, in the options table and in the `http` option JSDoc. Measured with
|
|
92
|
+
the same failing controller on both paths: with `http.isEnabled`, `forRootAsync` emits the access
|
|
93
|
+
log (`HTTP_REQUEST_START`, `_CLIENT_ERROR`, `_SERVER_ERROR`) and the real error reaches its terminal
|
|
94
|
+
entry, but not `HTTP_EXCEPTION_HANDLED` or `HTTP_EXCEPTION_UNHANDLED`; the 500 response is
|
|
95
|
+
identical. Registering `{ provide: APP_FILTER, useClass: HttpExceptionFilter }` yields them. The
|
|
96
|
+
difference is deliberate, and a spec pins the behaviour and the remedy.
|
|
97
|
+
- `ILogDestination` JSDoc: `write` no longer says a failing destination "may be temporarily
|
|
98
|
+
skipped". Nothing skips a destination that initialized: every failed entry is dropped for it and
|
|
99
|
+
reported, and it keeps receiving entries. Only one whose `onInit()` failed receives none.
|
|
100
|
+
`minLevel` says it can only narrow what the module `level` lets through.
|
|
101
|
+
- The README prose and tables are corrected against the code; that correction touches no source file.
|
|
102
|
+
- The options table gave `level` a default of `'info'`. Outside `NODE_ENV=production` the default
|
|
103
|
+
is `'debug'`. It now lists the options it omitted: `isGlobal`, `serializers`, `timestamp`, the
|
|
104
|
+
deprecated `shouldUseAsNestLogger`, and `otel.traceIdField`, `otel.spanIdField` and
|
|
105
|
+
`otel.traceFlagsField`.
|
|
106
|
+
- `DefaultStdoutDestination` was called "always active". It is the default sink only while
|
|
107
|
+
`destinations` is empty, as the Destinations section already said. A destination whose
|
|
108
|
+
`onInit()` rejects was described as staying in the write fan-out. It is removed from the fan-out
|
|
109
|
+
and from shutdown.
|
|
110
|
+
- The architecture diagram showed `info(logKey, msg, context, metadata)`; the third parameter is
|
|
111
|
+
`userId`. It named a `composedMixin()` that does not exist (the function is
|
|
112
|
+
`createTraceContextMixin`) and put `userId` in the scope `RequestIdMiddleware` opens, which holds
|
|
113
|
+
`requestId` and `tenantId`.
|
|
114
|
+
- The tech stack badges now read pnpm 11 and tsup 9. The URL normalization lists name ULID and
|
|
115
|
+
nanoid segments as well as UUID and numeric ones. The `LogContextService` table lists `get()`.
|
|
116
|
+
The last two HTTP log keys sit inside their table.
|
|
117
|
+
- The Pino throughput figures are attributed to Pino's own benchmarks, the `Scope.REQUEST` cost
|
|
118
|
+
to NestJS's estimate, and the EPIPE guard note names its one exception, `pino-pretty`'s own
|
|
119
|
+
stream.
|
|
120
|
+
- The resource identity example passed `process.env.POD_UID` to `service.instanceId`, which does
|
|
121
|
+
not compile under `exactOptionalPropertyTypes` because the value can be `undefined`. It now reads
|
|
122
|
+
`process.env.POD_UID!`.
|
|
123
|
+
|
|
124
|
+
### Tests
|
|
125
|
+
|
|
126
|
+
- `readme-options.spec.ts` parses the three option tables in the README and checks every default
|
|
127
|
+
against the defaults the module applies, and checks that the tables list exactly the options the
|
|
128
|
+
module resolves, so a default that drifts, or an option added without a row, fails the suite.
|
|
129
|
+
|
|
130
|
+
## [1.4.2] - 2026-10-30
|
|
131
|
+
|
|
132
|
+
No breaking changes. Dependency and build-tooling maintenance only. No source file under `src/` changes and the
|
|
133
|
+
runtime JavaScript in `dist/` is byte-identical to `1.4.1`.
|
|
134
|
+
|
|
135
|
+
### Security
|
|
136
|
+
|
|
137
|
+
- Raise the pnpm override floors for transitive devDependencies that resolved to versions
|
|
138
|
+
with new advisories: `body-parser` `^2.4.0` (GHSA-27r3-jxmh-p828, DoS on trailing bytes after a
|
|
139
|
+
compressed body), `multer` `^2.5.0` (GHSA-q7qp-rjg7-q26m, DoS from a pending async
|
|
140
|
+
`fileFilter`), `qs` `^6.16.1` (GHSA-6pq8-jhm2-2vcw, `qs.stringify` DoS) and `zod` `^4.6.6`
|
|
141
|
+
(GHSA-mrhx-c7xc-m3w5, memory exhaustion on oversized collections). Dev-only: the published
|
|
142
|
+
package has zero runtime dependencies.
|
|
143
|
+
- Ignore GHSA-gcqx-w48m-w2h4 (`deepmerge` <= 4.3.1, prototype poisoning in `mergeObject`) in
|
|
144
|
+
`osv-scanner.toml` until 2027-01-27. No patched release exists, and `deepmerge` is reached
|
|
145
|
+
only through `jest-config`, a devDependency. Remove the entry when a fixed `deepmerge` ships
|
|
146
|
+
or jest drops it.
|
|
147
|
+
|
|
148
|
+
### Changed
|
|
149
|
+
|
|
150
|
+
- Build with `tsup` 9 (devDependency, was 8.5). The published `.mjs` and `.cjs` bundles are
|
|
151
|
+
byte-identical; the `.d.ts` and `.d.cts` files re-emit type exports as a separate
|
|
152
|
+
`export type { … }` statement instead of inline `type` modifiers, which declares the same
|
|
153
|
+
public surface. `attw` reports no problems and the bundle-size budgets hold.
|
|
154
|
+
- Resolve `@opentelemetry/api` to 1.10.0 in the lockfile (was 1.9.1), so the test suite runs
|
|
155
|
+
against the current API release. The `^1.9.0` range in `package.json`, devDependency and peer
|
|
156
|
+
alike, is unchanged.
|
|
157
|
+
- Bump `github/codeql-action/upload-sarif` to 4.39.1 in the Scorecard workflow. CI only; nothing
|
|
158
|
+
ships.
|
|
159
|
+
|
|
160
|
+
### Documentation
|
|
161
|
+
|
|
162
|
+
- The runtime bundles are unchanged, and the type declarations were regenerated by `tsup` 9.
|
|
163
|
+
- The 1.0.1 and 1.0.8 release notes are corrected: 1.0.8 now records the id-safe charset
|
|
164
|
+
validation of inbound `x-request-id` and tenant ids that it already shipped.
|
|
165
|
+
|
|
166
|
+
#### Apply to a consumer
|
|
167
|
+
|
|
168
|
+
No action required. There is no new public API, no peer range changed, and the runtime JavaScript
|
|
169
|
+
is byte-identical to `1.4.1`; only the grouping of type exports in the declaration files differs.
|
|
170
|
+
|
|
14
171
|
## [1.4.1] - 2026-10-23
|
|
15
172
|
|
|
16
173
|
No breaking changes.
|
|
@@ -1699,8 +1856,9 @@ identical to `1.0.8`, and nothing changed but the version number.
|
|
|
1699
1856
|
|
|
1700
1857
|
## [1.0.8] - 2026-08-10
|
|
1701
1858
|
|
|
1702
|
-
Remediation of a local audit's redaction, attribution and correlation-id findings.
|
|
1703
|
-
|
|
1859
|
+
Remediation of a local audit's redaction, attribution and correlation-id findings. The public
|
|
1860
|
+
API is unchanged; the fixes are in the default redact set, the acting-user resolution, the
|
|
1861
|
+
correlation-id validation and the docs.
|
|
1704
1862
|
|
|
1705
1863
|
### Fixed
|
|
1706
1864
|
|
|
@@ -1712,6 +1870,14 @@ changed; the fixes are in the default redact set, the acting-user resolution and
|
|
|
1712
1870
|
exception filter now resolve the acting user as `sub ?? id`, so a JWT principal (every
|
|
1713
1871
|
`@bymax-one/nest-auth` token) is attributed to its subject rather than an ORM `id` when a
|
|
1714
1872
|
principal carries both.
|
|
1873
|
+
- **Inbound correlation and tenant ids are confined to an id-safe charset.** The inbound
|
|
1874
|
+
`x-request-id` and tenant-id header values are now accepted only when they are drawn from an
|
|
1875
|
+
id-safe character set and fit the length bound; anything else (control bytes, whitespace,
|
|
1876
|
+
markup characters) is rejected. A rejected request id is replaced by a generated one (when
|
|
1877
|
+
`shouldGenerateRequestId` is on) and a rejected tenant id is omitted. The request id is echoed
|
|
1878
|
+
on the `x-request-id` response header and both ids are stored in the log context, so this keeps
|
|
1879
|
+
a client from planting a control byte or markup fragment in the logs and the header of every
|
|
1880
|
+
request it makes.
|
|
1715
1881
|
|
|
1716
1882
|
### Documentation
|
|
1717
1883
|
|
|
@@ -1956,11 +2122,11 @@ published `dist/` is identical — no runtime behaviour changes for consumers.
|
|
|
1956
2122
|
Dev-only: the published package has zero runtime dependencies.
|
|
1957
2123
|
- Force `qs` to `^6.15.3` (via `pnpm.overrides`) to clear GHSA-q8mj-m7cp-5q26
|
|
1958
2124
|
(`qs.stringify` DoS). `typed-rest-client`, pulled in by Stryker, pins `qs` at
|
|
1959
|
-
the affected `6.15.1` exactly, so no dependency refresh could resolve it
|
|
2125
|
+
the affected `6.15.1` exactly, so no dependency refresh could resolve it.
|
|
1960
2126
|
- Pin every third-party and GitHub-owned action to a full commit SHA, with the
|
|
1961
2127
|
release tag kept as a trailing comment so Dependabot can still bump them. The
|
|
1962
2128
|
org's own `bymaxone/.github` reusable workflows and composite action stay on
|
|
1963
|
-
the `@v1` moving tag by design, so shared-pipeline fixes keep propagating
|
|
2129
|
+
the `@v1` moving tag by design, so shared-pipeline fixes keep propagating.
|
|
1964
2130
|
|
|
1965
2131
|
### Changed
|
|
1966
2132
|
|
|
@@ -2026,7 +2192,9 @@ published `dist/` is identical — no runtime behaviour changes for consumers.
|
|
|
2026
2192
|
- Professional CI suite: `ci.yml`, `bench.yml`, `codeql.yml`, `scorecard.yml`,
|
|
2027
2193
|
`release.yml`, Dependabot, and issue templates
|
|
2028
2194
|
|
|
2029
|
-
[Unreleased]: https://github.com/bymaxone/nest-logger/compare/v1.4.
|
|
2195
|
+
[Unreleased]: https://github.com/bymaxone/nest-logger/compare/v1.4.3...HEAD
|
|
2196
|
+
[1.4.3]: https://github.com/bymaxone/nest-logger/compare/v1.4.2...v1.4.3
|
|
2197
|
+
[1.4.2]: https://github.com/bymaxone/nest-logger/compare/v1.4.1...v1.4.2
|
|
2030
2198
|
[1.4.1]: https://github.com/bymaxone/nest-logger/compare/v1.4.0...v1.4.1
|
|
2031
2199
|
[1.4.0]: https://github.com/bymaxone/nest-logger/compare/v1.3.1...v1.4.0
|
|
2032
2200
|
[1.3.1]: https://github.com/bymaxone/nest-logger/compare/v1.3.0...v1.3.1
|