@bymax-one/nest-core 1.6.5 → 1.6.6
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 +23 -1
- package/README.md +6 -0
- package/dist/index.cjs +11 -1
- package/dist/index.mjs +11 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -11,6 +11,27 @@ heading here.
|
|
|
11
11
|
|
|
12
12
|
## [Unreleased]
|
|
13
13
|
|
|
14
|
+
## [1.6.6] - 2026-11-07
|
|
15
|
+
|
|
16
|
+
A patch release. The error envelope no longer returns the parser's own text for a request refused before
|
|
17
|
+
routing; see Fixed.
|
|
18
|
+
|
|
19
|
+
**Apply to a derived backend:** `pnpm up @bymax-one/nest-core`. A client that matched on those
|
|
20
|
+
message strings must match `code` instead. A middleware that throws a plain `BadRequestException`
|
|
21
|
+
before routing now answers `Malformed request` with the same 400; to keep its message, throw it with
|
|
22
|
+
a `code` (`new HttpException({ code: 'TENANT_REQUIRED', message }, 400)`).
|
|
23
|
+
|
|
24
|
+
### Fixed
|
|
25
|
+
|
|
26
|
+
- **A request refused before routing no longer has the parser's own text returned.** The message of
|
|
27
|
+
a body-parser, router or decoding refusal quotes the request: V8's JSON excerpt (on a login body
|
|
28
|
+
with a missing value it ends in the password's last characters), a charset or content-encoding
|
|
29
|
+
header value, or the path. The status is unchanged and the envelope keeps its shape, but the
|
|
30
|
+
message is now fixed per status. It is chosen from the error's own `type` (the body pipeline's
|
|
31
|
+
refusals carry one) or, for the `SyntaxError` and `URIError` that Nest rewrites into a plain
|
|
32
|
+
`BadRequestException`, from a 400 raised while the request matched no route. Not covered: Fastify,
|
|
33
|
+
whose body errors take another path and were not measured here.
|
|
34
|
+
|
|
14
35
|
## [1.6.5] - 2026-10-31
|
|
15
36
|
|
|
16
37
|
A documentation release. The compiled JavaScript is byte-identical to `1.6.4`: what changes in the
|
|
@@ -1314,4 +1335,5 @@ have regressed from. They are kept because the reasoning is worth having.
|
|
|
1314
1335
|
[1.6.3]: https://github.com/bymaxone/nest-core/compare/v1.6.2...v1.6.3
|
|
1315
1336
|
[1.6.4]: https://github.com/bymaxone/nest-core/compare/v1.6.3...v1.6.4
|
|
1316
1337
|
[1.6.5]: https://github.com/bymaxone/nest-core/compare/v1.6.4...v1.6.5
|
|
1317
|
-
[
|
|
1338
|
+
[1.6.6]: https://github.com/bymaxone/nest-core/compare/v1.6.5...v1.6.6
|
|
1339
|
+
[Unreleased]: https://github.com/bymaxone/nest-core/compare/v1.6.6...HEAD
|
package/README.md
CHANGED
|
@@ -639,6 +639,12 @@ marks itself `expose: true` with a `4xx` status, which is the `http-errors`
|
|
|
639
639
|
convention Node's body pipeline follows. Nothing in the application failed, so
|
|
640
640
|
it is not routed through the unexpected-error seam either.
|
|
641
641
|
|
|
642
|
+
The message of such a refusal is fixed per status — `Malformed request` (400),
|
|
643
|
+
`Request entity too large` (413), `Unsupported media type` (415) — because the
|
|
644
|
+
parser's own text quotes the request: a JSON excerpt, a header value, the path.
|
|
645
|
+
A `BadRequestException` a middleware throws before routing gets the same 400
|
|
646
|
+
message; throw it with a `code` to keep its own. Fastify is not covered.
|
|
647
|
+
|
|
642
648
|
**An error that carries no such marking is a 500, including when a client
|
|
643
649
|
caused it.** The clearest case is depth: a body of a few kilobytes nested
|
|
644
650
|
thousands of levels deep overflows the stack during validation and surfaces as
|
package/dist/index.cjs
CHANGED
|
@@ -359,6 +359,12 @@ function extractRequestInfo(context) {
|
|
|
359
359
|
var INTERNAL_ERROR_STATUS = 500;
|
|
360
360
|
var INTERNAL_ERROR_MESSAGE = "Internal server error";
|
|
361
361
|
var VALIDATION_FAILED_MESSAGE = "Validation failed";
|
|
362
|
+
var MALFORMED_REQUEST_MESSAGE = "Malformed request";
|
|
363
|
+
var PRE_ROUTING_MESSAGES = /* @__PURE__ */ new Map([
|
|
364
|
+
[400, MALFORMED_REQUEST_MESSAGE],
|
|
365
|
+
[413, "Request entity too large"],
|
|
366
|
+
[415, "Unsupported media type"]
|
|
367
|
+
]);
|
|
362
368
|
var ABSOLUTE_FORM_PREFIX = /^[A-Za-z][A-Za-z0-9+.-]*:\/\//;
|
|
363
369
|
function pathOf(url) {
|
|
364
370
|
let target = String(url);
|
|
@@ -409,8 +415,9 @@ function resolveExposedClientError(exception) {
|
|
|
409
415
|
if (typeof status !== "number" || !Number.isInteger(status) || status < CLIENT_ERROR_MIN2 || status >= CLIENT_ERROR_MAX2) {
|
|
410
416
|
return void 0;
|
|
411
417
|
}
|
|
418
|
+
const fixed = typeof candidate.type === "string" ? PRE_ROUTING_MESSAGES.get(status) : void 0;
|
|
412
419
|
const message = exception instanceof Error ? exception.message : "";
|
|
413
|
-
return { status, message: message === "" ? INTERNAL_ERROR_MESSAGE : message };
|
|
420
|
+
return { status, message: fixed ?? (message === "" ? INTERNAL_ERROR_MESSAGE : message) };
|
|
414
421
|
}
|
|
415
422
|
function isValidationResponse(response) {
|
|
416
423
|
return typeof response === "object" && response !== null && "message" in response && Array.isArray(response.message);
|
|
@@ -611,6 +618,9 @@ exports.BymaxExceptionFilter = class BymaxExceptionFilter {
|
|
|
611
618
|
toValidationDetails(response.message)
|
|
612
619
|
);
|
|
613
620
|
}
|
|
621
|
+
if (status === 400 && readRequestInfo(request).route === UNMATCHED_ROUTE) {
|
|
622
|
+
return this.toEnvelope(status, codeForStatus(status), MALFORMED_REQUEST_MESSAGE, context);
|
|
623
|
+
}
|
|
614
624
|
const message = extractHttpMessage(response, exception);
|
|
615
625
|
const rawUrl = String(this.adapterHost.httpAdapter.getRequestUrl(request));
|
|
616
626
|
return this.toEnvelope(
|
package/dist/index.mjs
CHANGED
|
@@ -357,6 +357,12 @@ function extractRequestInfo(context) {
|
|
|
357
357
|
var INTERNAL_ERROR_STATUS = 500;
|
|
358
358
|
var INTERNAL_ERROR_MESSAGE = "Internal server error";
|
|
359
359
|
var VALIDATION_FAILED_MESSAGE = "Validation failed";
|
|
360
|
+
var MALFORMED_REQUEST_MESSAGE = "Malformed request";
|
|
361
|
+
var PRE_ROUTING_MESSAGES = /* @__PURE__ */ new Map([
|
|
362
|
+
[400, MALFORMED_REQUEST_MESSAGE],
|
|
363
|
+
[413, "Request entity too large"],
|
|
364
|
+
[415, "Unsupported media type"]
|
|
365
|
+
]);
|
|
360
366
|
var ABSOLUTE_FORM_PREFIX = /^[A-Za-z][A-Za-z0-9+.-]*:\/\//;
|
|
361
367
|
function pathOf(url) {
|
|
362
368
|
let target = String(url);
|
|
@@ -407,8 +413,9 @@ function resolveExposedClientError(exception) {
|
|
|
407
413
|
if (typeof status !== "number" || !Number.isInteger(status) || status < CLIENT_ERROR_MIN2 || status >= CLIENT_ERROR_MAX2) {
|
|
408
414
|
return void 0;
|
|
409
415
|
}
|
|
416
|
+
const fixed = typeof candidate.type === "string" ? PRE_ROUTING_MESSAGES.get(status) : void 0;
|
|
410
417
|
const message = exception instanceof Error ? exception.message : "";
|
|
411
|
-
return { status, message: message === "" ? INTERNAL_ERROR_MESSAGE : message };
|
|
418
|
+
return { status, message: fixed ?? (message === "" ? INTERNAL_ERROR_MESSAGE : message) };
|
|
412
419
|
}
|
|
413
420
|
function isValidationResponse(response) {
|
|
414
421
|
return typeof response === "object" && response !== null && "message" in response && Array.isArray(response.message);
|
|
@@ -609,6 +616,9 @@ var BymaxExceptionFilter = class {
|
|
|
609
616
|
toValidationDetails(response.message)
|
|
610
617
|
);
|
|
611
618
|
}
|
|
619
|
+
if (status === 400 && readRequestInfo(request).route === UNMATCHED_ROUTE) {
|
|
620
|
+
return this.toEnvelope(status, codeForStatus(status), MALFORMED_REQUEST_MESSAGE, context);
|
|
621
|
+
}
|
|
612
622
|
const message = extractHttpMessage(response, exception);
|
|
613
623
|
const rawUrl = String(this.adapterHost.httpAdapter.getRequestUrl(request));
|
|
614
624
|
return this.toEnvelope(
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bymax-one/nest-core",
|
|
3
|
-
"version": "1.6.
|
|
3
|
+
"version": "1.6.6",
|
|
4
4
|
"description": "Zero-dependency NestJS 11 application foundation kit: error-envelope exception filter, request-timing middleware, 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",
|