@bymax-one/nest-core 1.0.1 → 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 +155 -1
- package/README.md +358 -55
- package/dist/health/index.cjs +10 -0
- package/dist/health/index.d.cts +33 -1
- package/dist/health/index.d.ts +33 -1
- package/dist/health/index.mjs +8 -0
- package/dist/index.cjs +408 -31
- package/dist/index.d.cts +224 -11
- package/dist/index.d.ts +224 -11
- package/dist/index.mjs +409 -33
- package/dist/metrics/index.cjs +12 -0
- package/dist/metrics/index.d.cts +57 -0
- package/dist/metrics/index.d.ts +57 -0
- package/dist/metrics/index.mjs +9 -0
- package/dist/openapi/index.cjs +268 -0
- package/dist/openapi/index.d.cts +44 -0
- package/dist/openapi/index.d.ts +44 -0
- package/dist/openapi/index.mjs +266 -0
- package/dist/pagination/index.cjs +1 -0
- package/dist/pagination/index.mjs +1 -0
- package/package.json +48 -17
package/CHANGELOG.md
CHANGED
|
@@ -11,6 +11,158 @@ 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
|
+
|
|
47
|
+
## [1.1.0] - 2026-08-05
|
|
48
|
+
|
|
49
|
+
Four optional integrations, each off by default and each loading nothing until it
|
|
50
|
+
is turned on: OpenAPI documents in development, health-indicator discovery, a
|
|
51
|
+
metrics contribution contract, and OpenTelemetry trace correlation.
|
|
52
|
+
|
|
53
|
+
### Added
|
|
54
|
+
|
|
55
|
+
- **OpenAPI documents, development only.** A new `openapi` option block and a new
|
|
56
|
+
`./openapi` subpath exporting `applyBymaxOpenApi`. Enabling the block and calling
|
|
57
|
+
the helper once during bootstrap serves an interactive UI and the raw document,
|
|
58
|
+
carrying the schemas this package already owns — the error envelope and its code
|
|
59
|
+
catalog, the health response, and the offset and cursor page shapes with their
|
|
60
|
+
query parameters.
|
|
61
|
+
|
|
62
|
+
`@nestjs/swagger` is an optional peer, reached only through a lazy dynamic import,
|
|
63
|
+
exactly like `prom-client`: an application that leaves the feature off never loads
|
|
64
|
+
it, and enabling the feature without installing it fails at boot with a message
|
|
65
|
+
naming the package and the install command.
|
|
66
|
+
|
|
67
|
+
The schemas are contributed as plain specification objects rather than decorated
|
|
68
|
+
classes. A decorator runs when its class is defined, so describing these contracts
|
|
69
|
+
with `@ApiProperty` would load the peer in every application that imports this
|
|
70
|
+
package, including the ones that never enable the feature.
|
|
71
|
+
|
|
72
|
+
A contributed entry never overwrites one the document already defines.
|
|
73
|
+
|
|
74
|
+
- **Health-indicator discovery.** A new `health.autoDiscover` option and a
|
|
75
|
+
`@BymaxHealthIndicator()` marker, exported from the `./health` subpath alongside
|
|
76
|
+
the contract it belongs to. With discovery enabled, every marked provider in the
|
|
77
|
+
application joins readiness — so a library an application merely imports can
|
|
78
|
+
contribute its own check without the application registering anything.
|
|
79
|
+
|
|
80
|
+
Discovery matches the marker, never the shape of an object: a provider that
|
|
81
|
+
happens to expose a `name` and a `check` is not a readiness probe, and scraping
|
|
82
|
+
one in would let an unrelated failure take an application out of rotation. A
|
|
83
|
+
provider that is marked but does not implement `IHealthIndicator` fails the boot
|
|
84
|
+
naming the class, rather than being skipped silently.
|
|
85
|
+
|
|
86
|
+
Explicit registration still wins: an indicator bound under
|
|
87
|
+
`BYMAX_HEALTH_INDICATORS` keeps its name and its position, and a discovered one
|
|
88
|
+
with the same name is dropped. Discovered indicators are sorted by name, so the
|
|
89
|
+
`checks` array is stable across restarts. The provider graph is walked once, at
|
|
90
|
+
bootstrap.
|
|
91
|
+
|
|
92
|
+
Off by default. It changes which failures can fail a readiness probe, which is
|
|
93
|
+
a decision an application makes rather than one it inherits from its imports.
|
|
94
|
+
|
|
95
|
+
- **A metrics contribution contract.** A new `./metrics` subpath exporting
|
|
96
|
+
`IMetricsContributor` and a `@BymaxMetricsContributor()` marker. A marked provider
|
|
97
|
+
is handed the registry once at bootstrap and registers its own collectors, so a
|
|
98
|
+
library's metrics appear on the application's existing scrape endpoint with
|
|
99
|
+
nothing wired.
|
|
100
|
+
|
|
101
|
+
Contributors receive the registry rather than injecting `BYMAX_METRICS_REGISTRY`:
|
|
102
|
+
a library that injected the token would depend on this package's DI tokens, and
|
|
103
|
+
therefore on the module. Receiving it as an argument means the only thing a
|
|
104
|
+
contributing library imports is the contract and the marker.
|
|
105
|
+
|
|
106
|
+
Registration failures are rethrown with the contributor named and the original
|
|
107
|
+
error chained. `prom-client` reports a duplicate metric name but not who
|
|
108
|
+
registered it, which in an application composing several libraries is the hard
|
|
109
|
+
half of the question. Contributors run sorted by class name, so a collision fails
|
|
110
|
+
the same way on every boot.
|
|
111
|
+
|
|
112
|
+
No separate flag: contribution rides on the metrics feature. With metrics
|
|
113
|
+
disabled no contributor runs and `prom-client` is still never loaded.
|
|
114
|
+
|
|
115
|
+
This is the one subpath whose types name `prom-client`. Implementing the contract
|
|
116
|
+
means constructing `prom-client` collectors, so anyone importing it already
|
|
117
|
+
depends on the peer; every other subpath stays free of it.
|
|
118
|
+
|
|
119
|
+
- **Trace correlation.** A new `telemetry` option block reads the active OpenTelemetry
|
|
120
|
+
span and carries its identifiers into the request-timing sample, into the exception
|
|
121
|
+
filter's observability seam, and — behind `telemetry.exposeTraceId` — into the error
|
|
122
|
+
envelope served to the client.
|
|
123
|
+
|
|
124
|
+
`@opentelemetry/api` is an optional peer. Unlike the other two it is read on every
|
|
125
|
+
request, so it is loaded once at bootstrap rather than at the point of use, and only
|
|
126
|
+
when the feature is enabled.
|
|
127
|
+
|
|
128
|
+
This package reads; it never traces. No span is created, no SDK configured, no
|
|
129
|
+
exporter registered: all of that belongs to the instrumentation an operator already
|
|
130
|
+
runs, and duplicating it would produce two spans per request.
|
|
131
|
+
|
|
132
|
+
A request with nothing recording, or an all-zero span context, resolves to no trace:
|
|
133
|
+
the fields are absent rather than set to a sentinel. Trace identifiers are never used
|
|
134
|
+
as metric labels — a trace id is unbounded, and one unbounded label is enough to make
|
|
135
|
+
a scrape endpoint the most expensive route in a service.
|
|
136
|
+
|
|
137
|
+
### Changed
|
|
138
|
+
|
|
139
|
+
- **The marker-based provider scan is now shared.** Readiness discovery and metrics
|
|
140
|
+
contribution use one scan, which reads Nest's provider graph, matches a literal
|
|
141
|
+
metadata key, and labels each match by class name — falling back to the provider
|
|
142
|
+
token for an anonymous class. Behavior is unchanged for readiness.
|
|
143
|
+
|
|
144
|
+
### Security
|
|
145
|
+
|
|
146
|
+
- **A trace id is not published in a response body by default.** `telemetry.exposeTraceId`
|
|
147
|
+
is off: a trace id is not a secret, but in a response it tells a caller that a tracing
|
|
148
|
+
backend exists and hands them the identifier correlating their request with everything
|
|
149
|
+
else in that trace. With the option off the identifiers still reach the timing sample and
|
|
150
|
+
the logging seam.
|
|
151
|
+
- **The OpenAPI document is never served in production.** `NODE_ENV` decides, and
|
|
152
|
+
the decision is fail-closed: only `development` and `test` are non-production, so
|
|
153
|
+
an unset or unrecognized value is production. The guard runs in two independent
|
|
154
|
+
layers — the option resolver forces the feature off, and the bootstrap helper
|
|
155
|
+
refuses again without trusting that resolution — and there is no override. Asking
|
|
156
|
+
for the document in production is a no-op with a warning, not an error, so one
|
|
157
|
+
configuration can be shared across environments.
|
|
158
|
+
|
|
159
|
+
### Notes
|
|
160
|
+
|
|
161
|
+
- `applyBymaxOpenApi` must be called **before** `app.listen()`. Mounting the document
|
|
162
|
+
re-registers routes on the HTTP adapter, and doing that against an
|
|
163
|
+
already-initialized Express 5 application replaces the router: every other route,
|
|
164
|
+
including this package's health endpoints, stops resolving.
|
|
165
|
+
|
|
14
166
|
## [1.0.1] - 2026-08-04
|
|
15
167
|
|
|
16
168
|
**Behaviour change on the readiness endpoint.** A failing indicator's message no
|
|
@@ -108,6 +260,8 @@ have regressed from. They are kept because the reasoning is worth having.
|
|
|
108
260
|
cleanly and silently. Corrected before the first publish, so no released version
|
|
109
261
|
ever carried the permissive range. No runtime behaviour changed.
|
|
110
262
|
|
|
263
|
+
[1.1.0]: https://github.com/bymaxone/nest-core/compare/v1.0.1...v1.1.0
|
|
111
264
|
[1.0.1]: https://github.com/bymaxone/nest-core/compare/v1.0.0...v1.0.1
|
|
112
265
|
[1.0.0]: https://github.com/bymaxone/nest-core/releases/tag/v1.0.0
|
|
113
|
-
[
|
|
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
|