@bymax-one/nest-core 1.1.0 → 1.1.1
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 +35 -1
- package/README.md +8 -5
- package/dist/index.cjs +2 -0
- package/dist/index.mjs +2 -0
- package/dist/pagination/index.cjs +1 -0
- package/dist/pagination/index.mjs +1 -0
- package/package.json +3 -2
package/CHANGELOG.md
CHANGED
|
@@ -11,6 +11,39 @@ heading here.
|
|
|
11
11
|
|
|
12
12
|
## [Unreleased]
|
|
13
13
|
|
|
14
|
+
## [1.1.1] - 2026-08-07
|
|
15
|
+
|
|
16
|
+
**Documentation and tooling.** `dist/` differs from `1.1.0` 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.** The nine
|
|
22
|
+
now carry `// Stryker disable next-line <Mutator>: <reason>` on the line they apply to,
|
|
23
|
+
which is the convention now shared across the `@bymax-one/nest-*` libraries. The measured
|
|
24
|
+
score moves from **98.76%** to **100%** — no test and no production logic changed; Stryker
|
|
25
|
+
excludes an ignored mutant from the denominator instead of counting it as one the suite
|
|
26
|
+
failed to kill.
|
|
27
|
+
|
|
28
|
+
Two needed the block `disable`/`restore` form, because `next-line` binds to the following
|
|
29
|
+
statement and those mutants do not sit on one: the cursor-parse catch body, and
|
|
30
|
+
`setExtras({ isGlobal: true }, …)` inside the builder chain. The second was already known —
|
|
31
|
+
the note above that call said a directive does not attach there and left the mutant counted.
|
|
32
|
+
That prose is now the directive's reason, and the block brackets the builder statement alone
|
|
33
|
+
so nothing else in the file loses its `ObjectLiteral` mutants. Both were confirmed by
|
|
34
|
+
running them: the pass reports zero survivors where it reported nine.
|
|
35
|
+
|
|
36
|
+
- The README claimed **Zero suppressions** as a rule. It states what is true now: every
|
|
37
|
+
suppression carries its reason, in the grammar Stryker parses.
|
|
38
|
+
|
|
39
|
+
### Added
|
|
40
|
+
|
|
41
|
+
- `check:mutants` gate (`scripts/check-mutation-directives.mjs`) — validates every
|
|
42
|
+
`// Stryker` comment against the parser's own regular expression, rejecting a reason
|
|
43
|
+
written after `--` instead of a colon, a reason wrapped onto a second comment line, a stray
|
|
44
|
+
comma in the mutator list, and a mutator name Stryker does not know, which matches nothing
|
|
45
|
+
and so silences nothing. Wired into CI and `prepublishOnly`.
|
|
46
|
+
|
|
14
47
|
## [1.1.0] - 2026-08-05
|
|
15
48
|
|
|
16
49
|
Four optional integrations, each off by default and each loading nothing until it
|
|
@@ -230,4 +263,5 @@ have regressed from. They are kept because the reasoning is worth having.
|
|
|
230
263
|
[1.1.0]: https://github.com/bymaxone/nest-core/compare/v1.0.1...v1.1.0
|
|
231
264
|
[1.0.1]: https://github.com/bymaxone/nest-core/compare/v1.0.0...v1.0.1
|
|
232
265
|
[1.0.0]: https://github.com/bymaxone/nest-core/releases/tag/v1.0.0
|
|
233
|
-
[
|
|
266
|
+
[1.1.1]: https://github.com/bymaxone/nest-core/compare/v1.1.0...v1.1.1
|
|
267
|
+
[Unreleased]: https://github.com/bymaxone/nest-core/compare/v1.1.1...HEAD
|
package/README.md
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
<a href="https://www.npmjs.com/package/@bymax-one/nest-core"><img src="https://img.shields.io/npm/dm/@bymax-one/nest-core?style=flat-square&colorA=000000&colorB=000000" alt="npm downloads" /></a>
|
|
15
15
|
<a href="https://github.com/bymaxone/nest-core/actions/workflows/ci.yml"><img src="https://img.shields.io/github/actions/workflow/status/bymaxone/nest-core/ci.yml?branch=main&style=flat-square&colorA=000000&label=CI" alt="CI status" /></a>
|
|
16
16
|
<a href="https://github.com/bymaxone/nest-core/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-core/blob/main/docs/mutation_testing_results.md"><img src="https://img.shields.io/badge/mutation-
|
|
17
|
+
<a href="https://github.com/bymaxone/nest-core/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-core"><img src="https://api.scorecard.dev/projects/github.com/bymaxone/nest-core/badge?style=flat-square" alt="OpenSSF Scorecard" /></a>
|
|
19
19
|
<a href="https://github.com/bymaxone/nest-core/blob/main/LICENSE"><img src="https://img.shields.io/github/license/bymaxone/nest-core?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>
|
|
@@ -917,17 +917,20 @@ This library sits in the path of every request and every failure of every servic
|
|
|
917
917
|
installs it, so the suite is held to a bar beyond "the tests pass".
|
|
918
918
|
|
|
919
919
|
- ✅ **100% line coverage** — statements, branches, functions and lines, enforced as a gate
|
|
920
|
-
- ✅ **
|
|
920
|
+
- ✅ **100% mutation score** — verified with [Stryker](https://stryker-mutator.io/) at
|
|
921
921
|
`break: 95`; every killable survivor was killed by a strengthened test, with no production
|
|
922
|
-
change, and the nine that
|
|
923
|
-
([report](./docs/mutation_testing_results.md))
|
|
922
|
+
change, and the nine equivalents that no test can kill each carry their reason on the line
|
|
923
|
+
they apply to ([report](./docs/mutation_testing_results.md))
|
|
924
924
|
- ✅ **End-to-end against a real application** — the filter, the interceptor, the health and
|
|
925
925
|
metrics routes, the served OpenAPI document, discovered indicators, contributed metrics and
|
|
926
926
|
trace correlation are all exercised through a booted Nest app, not against mocks of it
|
|
927
927
|
- ✅ **Published-artifact gates** — `check:exports` resolves the types the way each module
|
|
928
928
|
system does, `check:runtime` loads every subpath from the packed tarball in ESM and
|
|
929
929
|
CommonJS, and `check:published` compiles this README's snippets against `dist/`
|
|
930
|
-
- ✅ **
|
|
930
|
+
- ✅ **Every suppression carries its reason** — no coverage directives anywhere; each
|
|
931
|
+
`// Stryker disable` in the production source names, after the `:` Stryker reads it from,
|
|
932
|
+
why the mutant it silences is behaviour-preserving, and `check:mutants` proves those reasons
|
|
933
|
+
parse so they reach the mutation report rather than the `Ignored using a comment` fallback
|
|
931
934
|
|
|
932
935
|
```bash
|
|
933
936
|
pnpm test # unit suite
|
package/dist/index.cjs
CHANGED
|
@@ -483,10 +483,12 @@ exports.BymaxExceptionFilter = class BymaxExceptionFilter {
|
|
|
483
483
|
path: context.path,
|
|
484
484
|
now: this.now,
|
|
485
485
|
...details !== void 0 ? { details } : {},
|
|
486
|
+
// Stryker disable next-line ConditionalExpression: equivalent — the always-spread form hands the builder `correlationId: undefined`, and `buildErrorEnvelope` re-guards `input.correlationId !== undefined` and omits an undefined value, so the emitted envelope is byte-for-byte identical whether or not a correlation id is present.
|
|
486
487
|
...context.correlationId !== void 0 ? { correlationId: context.correlationId } : {},
|
|
487
488
|
// Gated separately from the context above: the trace id reaches the
|
|
488
489
|
// observability seam either way, and the response body only when the
|
|
489
490
|
// operator opted into publishing it.
|
|
491
|
+
// Stryker disable next-line ConditionalExpression: equivalent — same as the correlation id above. The always-spread form hands the builder `traceId: undefined`, which `buildErrorEnvelope` re-guards and omits. The call-site guard exists because `exactOptionalPropertyTypes` rejects an explicit `undefined` for an optional field, not because it changes the output.
|
|
490
492
|
...this.options.telemetry.exposeTraceId && context.traceId !== void 0 ? { traceId: context.traceId } : {}
|
|
491
493
|
});
|
|
492
494
|
}
|
package/dist/index.mjs
CHANGED
|
@@ -481,10 +481,12 @@ var BymaxExceptionFilter = class {
|
|
|
481
481
|
path: context.path,
|
|
482
482
|
now: this.now,
|
|
483
483
|
...details !== void 0 ? { details } : {},
|
|
484
|
+
// Stryker disable next-line ConditionalExpression: equivalent — the always-spread form hands the builder `correlationId: undefined`, and `buildErrorEnvelope` re-guards `input.correlationId !== undefined` and omits an undefined value, so the emitted envelope is byte-for-byte identical whether or not a correlation id is present.
|
|
484
485
|
...context.correlationId !== void 0 ? { correlationId: context.correlationId } : {},
|
|
485
486
|
// Gated separately from the context above: the trace id reaches the
|
|
486
487
|
// observability seam either way, and the response body only when the
|
|
487
488
|
// operator opted into publishing it.
|
|
489
|
+
// Stryker disable next-line ConditionalExpression: equivalent — same as the correlation id above. The always-spread form hands the builder `traceId: undefined`, which `buildErrorEnvelope` re-guards and omits. The call-site guard exists because `exactOptionalPropertyTypes` rejects an explicit `undefined` for an optional field, not because it changes the output.
|
|
488
490
|
...this.options.telemetry.exposeTraceId && context.traceId !== void 0 ? { traceId: context.traceId } : {}
|
|
489
491
|
});
|
|
490
492
|
}
|
|
@@ -57,6 +57,7 @@ function isOrderingKeyRecord(value) {
|
|
|
57
57
|
return false;
|
|
58
58
|
}
|
|
59
59
|
return Object.values(value).every(
|
|
60
|
+
// Stryker disable next-line ConditionalExpression: equivalent — replacing the `typeof entry === 'number'` guard with `true` leaves `Number.isFinite(entry)`, which never coerces and so already returns `false` for every non-number. The guard is redundant and the predicate is unchanged for every value.
|
|
60
61
|
(entry) => typeof entry === "string" || typeof entry === "number" && Number.isFinite(entry)
|
|
61
62
|
);
|
|
62
63
|
}
|
|
@@ -55,6 +55,7 @@ function isOrderingKeyRecord(value) {
|
|
|
55
55
|
return false;
|
|
56
56
|
}
|
|
57
57
|
return Object.values(value).every(
|
|
58
|
+
// Stryker disable next-line ConditionalExpression: equivalent — replacing the `typeof entry === 'number'` guard with `true` leaves `Number.isFinite(entry)`, which never coerces and so already returns `false` for every non-number. The guard is redundant and the predicate is unchanged for every value.
|
|
58
59
|
(entry) => typeof entry === "string" || typeof entry === "number" && Number.isFinite(entry)
|
|
59
60
|
);
|
|
60
61
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bymax-one/nest-core",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.1",
|
|
4
4
|
"description": "Zero-dependency NestJS 11 application foundation kit: error-envelope exception filter, request-timing interceptor, pagination helpers, health endpoints with indicator discovery, an optional Prometheus metrics endpoint with a contribution contract, OpenAPI documents in development, and OpenTelemetry trace correlation.",
|
|
5
5
|
"author": "Bymax One <support@bymax.one>",
|
|
6
6
|
"license": "MIT",
|
|
@@ -78,6 +78,7 @@
|
|
|
78
78
|
"scripts": {
|
|
79
79
|
"build": "pnpm clean && tsup",
|
|
80
80
|
"check:exports": "attw --pack . --profile strict",
|
|
81
|
+
"check:mutants": "node scripts/check-mutation-directives.mjs",
|
|
81
82
|
"check:published": "node scripts/check-published-surface.mjs",
|
|
82
83
|
"check:runtime": "node scripts/check-consumer-runtime.mjs",
|
|
83
84
|
"clean": "node -e \"const fs=require('node:fs');for(const d of ['dist','coverage'])fs.rmSync(d,{recursive:true,force:true})\"",
|
|
@@ -88,7 +89,7 @@
|
|
|
88
89
|
"mutation:dry-run": "stryker run --dryRunOnly",
|
|
89
90
|
"mutation:incremental": "stryker run --incremental",
|
|
90
91
|
"prepare": "husky",
|
|
91
|
-
"prepublishOnly": "pnpm clean && pnpm typecheck && pnpm lint && pnpm test:cov:all && pnpm build && pnpm size && pnpm check:published",
|
|
92
|
+
"prepublishOnly": "pnpm clean && pnpm typecheck && pnpm lint && pnpm check:mutants && pnpm test:cov:all && pnpm build && pnpm size && pnpm check:published",
|
|
92
93
|
"release": "npm publish --provenance --access public",
|
|
93
94
|
"size": "node scripts/check-size.mjs",
|
|
94
95
|
"test": "jest",
|