@bymax-one/nest-logger 1.0.6 → 1.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.
- package/CHANGELOG.md +48 -1
- package/README.md +7 -7
- package/dist/server/index.cjs +1 -0
- package/dist/server/index.mjs +1 -0
- package/package.json +3 -2
package/CHANGELOG.md
CHANGED
|
@@ -11,6 +11,52 @@ heading here.
|
|
|
11
11
|
|
|
12
12
|
## [Unreleased]
|
|
13
13
|
|
|
14
|
+
## [1.0.7] - 2026-08-07
|
|
15
|
+
|
|
16
|
+
**Documentation and tooling.** `dist/` differs from `1.0.6` only in the text of the comments
|
|
17
|
+
described below; no runtime code changed.
|
|
18
|
+
|
|
19
|
+
### Changed
|
|
20
|
+
|
|
21
|
+
- **Equivalent mutants are documented in the source instead of only in the report, and the
|
|
22
|
+
rule against that was retired on a measurement.** The plan forbade inline
|
|
23
|
+
`// Stryker disable` comments on the ground that they would push the server subpath past
|
|
24
|
+
its 13.5 kB brotli budget. Measured: seven directives took the bundle from **12.84 to
|
|
25
|
+
12.94 kB** — **+0.10 kB** against 0.66 kB of headroom, because brotli compresses their
|
|
26
|
+
repeated prefixes almost for free. The assumed cost was roughly ten times the real one, and
|
|
27
|
+
no budget changed.
|
|
28
|
+
|
|
29
|
+
With the ten survivors now carrying their reason inline, the measured score moves from
|
|
30
|
+
**97.42%** to **100%** — no test and no production logic changed; Stryker excludes an
|
|
31
|
+
ignored mutant from the denominator instead of counting it as one the suite failed to kill.
|
|
32
|
+
|
|
33
|
+
- **One suppression is recorded as what it is, not as an equivalent.** `otel-detector.ts:40`
|
|
34
|
+
is killed by the suite — applying the mutation by hand turns the suite red — but Stryker
|
|
35
|
+
fails to attribute the killing test to it under `perTest` coverage analysis. Its directive
|
|
36
|
+
says exactly that. Calling it equivalent to reach a rounder number would have been false.
|
|
37
|
+
|
|
38
|
+
- Two reasons were corrected after review. `decodeStrings: false` claimed equivalence "for
|
|
39
|
+
every input"; with `true`, Node encodes the string using the write's encoding and this
|
|
40
|
+
stream decodes with `toString('utf-8')`, so a `write(chunk, 'latin1')` would change
|
|
41
|
+
non-ASCII bytes. Nothing writes here but Pino, which emits UTF-8 NDJSON at the default
|
|
42
|
+
encoding, and the reason now says so and names where it stops being true. The
|
|
43
|
+
`{ strict: false }` reason argued from a missing provider; it now gives the actual
|
|
44
|
+
mechanism — `NestApplicationContext.get` branches on `!(options && options.strict)`, so the
|
|
45
|
+
mutant's `{}` leaves `strict` undefined, which is falsy, and takes the same non-strict
|
|
46
|
+
lookup.
|
|
47
|
+
|
|
48
|
+
### Added
|
|
49
|
+
|
|
50
|
+
- `check:mutants` gate (`scripts/check-mutation-directives.mjs`) — validates every
|
|
51
|
+
`// Stryker` comment against the parser's own regular expression, rejecting a reason written
|
|
52
|
+
after `--` instead of a colon, a reason wrapped onto a second comment line, a stray comma in
|
|
53
|
+
the mutator list, and a mutator name Stryker does not know, which matches nothing and so
|
|
54
|
+
silences nothing. Wired into CI and `prepublishOnly`.
|
|
55
|
+
|
|
56
|
+
### Fixed
|
|
57
|
+
|
|
58
|
+
- The `[Unreleased]` compare link still pointed at `v1.0.5` after `1.0.6` shipped.
|
|
59
|
+
|
|
14
60
|
## [1.0.6] - 2026-08-06
|
|
15
61
|
|
|
16
62
|
**Tests and documentation only.** `dist/` is byte-identical to `1.0.5`.
|
|
@@ -270,7 +316,8 @@ published `dist/` is identical — no runtime behaviour changes for consumers.
|
|
|
270
316
|
- Professional CI suite: `ci.yml`, `bench.yml`, `codeql.yml`, `scorecard.yml`,
|
|
271
317
|
`release.yml`, Dependabot, and issue templates
|
|
272
318
|
|
|
273
|
-
[Unreleased]: https://github.com/bymaxone/nest-logger/compare/v1.0.
|
|
319
|
+
[Unreleased]: https://github.com/bymaxone/nest-logger/compare/v1.0.7...HEAD
|
|
320
|
+
[1.0.7]: https://github.com/bymaxone/nest-logger/compare/v1.0.6...v1.0.7
|
|
274
321
|
[1.0.6]: https://github.com/bymaxone/nest-logger/compare/v1.0.5...v1.0.6
|
|
275
322
|
[1.0.5]: https://github.com/bymaxone/nest-logger/compare/v1.0.4...v1.0.5
|
|
276
323
|
[1.0.4]: https://github.com/bymaxone/nest-logger/compare/v1.0.3...v1.0.4
|
package/README.md
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
<a href="https://www.npmjs.com/package/@bymax-one/nest-logger"><img src="https://img.shields.io/npm/dm/@bymax-one/nest-logger?style=flat-square&colorA=000000&colorB=000000" alt="npm downloads" /></a>
|
|
15
15
|
<a href="https://github.com/bymaxone/nest-logger/actions/workflows/ci.yml"><img src="https://img.shields.io/github/actions/workflow/status/bymaxone/nest-logger/ci.yml?branch=main&style=flat-square&colorA=000000&label=CI" alt="CI status" /></a>
|
|
16
16
|
<a href="https://github.com/bymaxone/nest-logger/actions/workflows/ci.yml"><img src="https://img.shields.io/badge/coverage-100%25-brightgreen?style=flat-square&colorA=000000" alt="coverage" /></a>
|
|
17
|
-
<a href="https://github.com/bymaxone/nest-logger/blob/main/docs/mutation_testing_results.md"><img src="https://img.shields.io/badge/mutation-
|
|
17
|
+
<a href="https://github.com/bymaxone/nest-logger/blob/main/docs/mutation_testing_results.md"><img src="https://img.shields.io/badge/mutation-100%25-brightgreen?style=flat-square&colorA=000000" alt="mutation score" /></a>
|
|
18
18
|
<a href="https://scorecard.dev/viewer/?uri=github.com/bymaxone/nest-logger"><img src="https://api.scorecard.dev/projects/github.com/bymaxone/nest-logger/badge?style=flat-square" alt="OpenSSF Scorecard" /></a>
|
|
19
19
|
<a href="https://github.com/bymaxone/nest-logger/blob/main/LICENSE"><img src="https://img.shields.io/github/license/bymaxone/nest-logger?style=flat-square&colorA=000000&colorB=000000" alt="license" /></a>
|
|
20
20
|
<a href="https://www.typescriptlang.org/"><img src="https://img.shields.io/badge/TypeScript-strict-3178C6?style=flat-square&logo=typescript&logoColor=white" alt="TypeScript" /></a>
|
|
@@ -745,12 +745,12 @@ When integrating `@bymax-one/nest-logger` in production, verify each of the foll
|
|
|
745
745
|
A logger runs on every request of every service that installs it, so the suite is held to a bar beyond "it runs" — every behavior is pinned so that a regression **fails a test**.
|
|
746
746
|
|
|
747
747
|
- ✅ **100% line coverage** — statements, branches, functions, and lines, enforced as a release gate across unit + e2e
|
|
748
|
-
- ✅ **
|
|
749
|
-
`break` threshold of 95. The ten
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
[report](./docs/mutation_testing_results.md))
|
|
753
|
-
- ✅ **Every
|
|
748
|
+
- ✅ **100% mutation score** — verified with [Stryker](https://stryker-mutator.io/) against a
|
|
749
|
+
`break` threshold of 95. The ten mutants no test can kill each carry their reason on the line
|
|
750
|
+
they apply to; a rule against those comments was retired once their cost was measured at
|
|
751
|
+
**+0.10 kB brotli** against 0.66 kB of headroom, roughly a tenth of what it had been assumed
|
|
752
|
+
to be (see the [report](./docs/mutation_testing_results.md))
|
|
753
|
+
- ✅ **Every suppression carries its reason** — each `// Stryker disable` names, after the `:` Stryker reads it from, why the mutant it silences cannot be observed; one of them is recorded as what it is, a mutant the suite kills but Stryker fails to attribute, rather than mislabelled an equivalent. `check:mutants` proves those reasons parse, so they reach the report rather than the `Ignored using a comment` fallback, and the score stays an accounting rather than a number
|
|
754
754
|
- ✅ **No real I/O in unit tests** — the Pino instance and every destination are mocked; e2e tests exercise the wired module through `@nestjs/testing` and supertest
|
|
755
755
|
|
|
756
756
|
```bash
|
package/dist/server/index.cjs
CHANGED
|
@@ -849,6 +849,7 @@ function destinationToStream(destination) {
|
|
|
849
849
|
// Keep string chunks as strings (Node's default re-encodes them to Buffers
|
|
850
850
|
// before `_write`): the common Pino path emits NDJSON strings, so this skips
|
|
851
851
|
// a string→Buffer→string round-trip on the hot logging path.
|
|
852
|
+
// Stryker disable next-line BooleanLiteral: equivalent for every chunk this stream receives — with `true`, Node encodes the string to a Buffer and `write()` below decodes it back with `toString('utf-8')`. Pino writes UTF-8 NDJSON strings at the default encoding, so the round-trip returns the identical string. It is NOT equivalent in general: a `write(chunk, 'latin1')` would round-trip through UTF-8 and change non-ASCII bytes, which is unreachable here because nothing writes to this stream but Pino. The flag stays because it skips the round-trip on the hot logging path.
|
|
852
853
|
decodeStrings: false,
|
|
853
854
|
write(chunk, _encoding, callback) {
|
|
854
855
|
const onFailure = (cause) => {
|
package/dist/server/index.mjs
CHANGED
|
@@ -843,6 +843,7 @@ function destinationToStream(destination) {
|
|
|
843
843
|
// Keep string chunks as strings (Node's default re-encodes them to Buffers
|
|
844
844
|
// before `_write`): the common Pino path emits NDJSON strings, so this skips
|
|
845
845
|
// a string→Buffer→string round-trip on the hot logging path.
|
|
846
|
+
// Stryker disable next-line BooleanLiteral: equivalent for every chunk this stream receives — with `true`, Node encodes the string to a Buffer and `write()` below decodes it back with `toString('utf-8')`. Pino writes UTF-8 NDJSON strings at the default encoding, so the round-trip returns the identical string. It is NOT equivalent in general: a `write(chunk, 'latin1')` would round-trip through UTF-8 and change non-ASCII bytes, which is unreachable here because nothing writes to this stream but Pino. The flag stays because it skips the round-trip on the hot logging path.
|
|
846
847
|
decodeStrings: false,
|
|
847
848
|
write(chunk, _encoding, callback) {
|
|
848
849
|
const onFailure = (cause) => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bymax-one/nest-logger",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.7",
|
|
4
4
|
"description": "Structured JSON logging for NestJS based on Pino 10, with optional OpenTelemetry correlation.",
|
|
5
5
|
"author": "Bymax One <support@bymax.one>",
|
|
6
6
|
"license": "MIT",
|
|
@@ -57,6 +57,7 @@
|
|
|
57
57
|
"bench": "node --expose-gc --import tsx bench/throughput.bench.ts",
|
|
58
58
|
"build": "pnpm clean && tsup",
|
|
59
59
|
"check:exports": "attw --pack .",
|
|
60
|
+
"check:mutants": "node scripts/check-mutation-directives.mjs",
|
|
60
61
|
"check:published": "node scripts/check-published-surface.mjs",
|
|
61
62
|
"clean": "rm -rf dist coverage",
|
|
62
63
|
"lint": "eslint src",
|
|
@@ -65,7 +66,7 @@
|
|
|
65
66
|
"mutation:dry-run": "stryker run --dryRunOnly",
|
|
66
67
|
"mutation:incremental": "stryker run --incremental",
|
|
67
68
|
"prepare": "husky",
|
|
68
|
-
"prepublishOnly": "pnpm clean && pnpm typecheck && pnpm lint && pnpm test:cov:all && pnpm build && pnpm check:published",
|
|
69
|
+
"prepublishOnly": "pnpm clean && pnpm typecheck && pnpm lint && pnpm check:mutants && pnpm test:cov:all && pnpm build && pnpm check:published",
|
|
69
70
|
"release": "npm publish --provenance --access public",
|
|
70
71
|
"size": "node scripts/check-size.mjs",
|
|
71
72
|
"test": "jest",
|