@bymax-one/nest-core 1.2.0 → 1.2.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 +18 -1
- package/dist/index.cjs +26 -0
- package/dist/index.mjs +26 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -11,6 +11,22 @@ heading here.
|
|
|
11
11
|
|
|
12
12
|
## [Unreleased]
|
|
13
13
|
|
|
14
|
+
## [1.2.1] - 2026-08-08
|
|
15
|
+
|
|
16
|
+
A patch: the envelope fix below changes a response status for a class of client errors, without
|
|
17
|
+
touching the module's API or any option.
|
|
18
|
+
|
|
19
|
+
### Fixed
|
|
20
|
+
|
|
21
|
+
- **An error carrying a 4xx status it marked exposable keeps that status, instead of collapsing to 500.** Express's body pipeline throws `http-errors` instances before any handler runs — a payload
|
|
22
|
+
past the limit is `PayloadTooLargeError` (413), malformed JSON is a `SyntaxError` (400), an
|
|
23
|
+
unsupported media type is 415. None is a Nest `HttpException`, so each reached the generic
|
|
24
|
+
500 collapse: a client that sent too large a body, or malformed JSON, was told the server failed,
|
|
25
|
+
and a monitor counted a 5xx for a request that never entered the application. The filter now reads
|
|
26
|
+
the `expose: true` flag and the numeric status these carry and honours it — restricted to the 4xx
|
|
27
|
+
range, because a self-reported 5xx is still a server failure whose account of itself must not
|
|
28
|
+
surface, so it stays a generic 500.
|
|
29
|
+
|
|
14
30
|
## [1.2.0] - 2026-08-08
|
|
15
31
|
|
|
16
32
|
Both entries change what a caller receives, which is why this is a minor rather than a patch: an
|
|
@@ -301,5 +317,6 @@ have regressed from. They are kept because the reasoning is worth having.
|
|
|
301
317
|
[1.0.1]: https://github.com/bymaxone/nest-core/compare/v1.0.0...v1.0.1
|
|
302
318
|
[1.0.0]: https://github.com/bymaxone/nest-core/releases/tag/v1.0.0
|
|
303
319
|
[1.1.1]: https://github.com/bymaxone/nest-core/compare/v1.1.0...v1.1.1
|
|
320
|
+
[1.2.1]: https://github.com/bymaxone/nest-core/compare/v1.2.0...v1.2.1
|
|
304
321
|
[1.2.0]: https://github.com/bymaxone/nest-core/compare/v1.1.1...v1.2.0
|
|
305
|
-
[Unreleased]: https://github.com/bymaxone/nest-core/compare/v1.2.
|
|
322
|
+
[Unreleased]: https://github.com/bymaxone/nest-core/compare/v1.2.1...HEAD
|
package/dist/index.cjs
CHANGED
|
@@ -310,6 +310,23 @@ function extractExplicitDetails(carrier) {
|
|
|
310
310
|
const details = carrier.details;
|
|
311
311
|
return typeof details === "object" && details !== null ? details : void 0;
|
|
312
312
|
}
|
|
313
|
+
var CLIENT_ERROR_MIN2 = 400;
|
|
314
|
+
var CLIENT_ERROR_MAX2 = 500;
|
|
315
|
+
function resolveExposedClientError(exception) {
|
|
316
|
+
if (typeof exception !== "object" || exception === null) {
|
|
317
|
+
return void 0;
|
|
318
|
+
}
|
|
319
|
+
const candidate = exception;
|
|
320
|
+
if (candidate.expose !== true) {
|
|
321
|
+
return void 0;
|
|
322
|
+
}
|
|
323
|
+
const status = Number.isInteger(candidate.status) ? candidate.status : candidate.statusCode;
|
|
324
|
+
if (typeof status !== "number" || !Number.isInteger(status) || status < CLIENT_ERROR_MIN2 || status >= CLIENT_ERROR_MAX2) {
|
|
325
|
+
return void 0;
|
|
326
|
+
}
|
|
327
|
+
const message = exception instanceof Error ? exception.message : "";
|
|
328
|
+
return { status, message: message === "" ? INTERNAL_ERROR_MESSAGE : message };
|
|
329
|
+
}
|
|
313
330
|
function isValidationResponse(response) {
|
|
314
331
|
return typeof response === "object" && response !== null && "message" in response && Array.isArray(response.message);
|
|
315
332
|
}
|
|
@@ -424,6 +441,15 @@ exports.BymaxExceptionFilter = class BymaxExceptionFilter {
|
|
|
424
441
|
if (exception instanceof common.HttpException) {
|
|
425
442
|
return this.mapHttpException(exception, context);
|
|
426
443
|
}
|
|
444
|
+
const exposed = resolveExposedClientError(exception);
|
|
445
|
+
if (exposed !== void 0) {
|
|
446
|
+
return this.toEnvelope(
|
|
447
|
+
exposed.status,
|
|
448
|
+
codeForStatus(exposed.status),
|
|
449
|
+
exposed.message,
|
|
450
|
+
context
|
|
451
|
+
);
|
|
452
|
+
}
|
|
427
453
|
try {
|
|
428
454
|
this.onUnexpectedError(exception, context);
|
|
429
455
|
} catch {
|
package/dist/index.mjs
CHANGED
|
@@ -308,6 +308,23 @@ function extractExplicitDetails(carrier) {
|
|
|
308
308
|
const details = carrier.details;
|
|
309
309
|
return typeof details === "object" && details !== null ? details : void 0;
|
|
310
310
|
}
|
|
311
|
+
var CLIENT_ERROR_MIN2 = 400;
|
|
312
|
+
var CLIENT_ERROR_MAX2 = 500;
|
|
313
|
+
function resolveExposedClientError(exception) {
|
|
314
|
+
if (typeof exception !== "object" || exception === null) {
|
|
315
|
+
return void 0;
|
|
316
|
+
}
|
|
317
|
+
const candidate = exception;
|
|
318
|
+
if (candidate.expose !== true) {
|
|
319
|
+
return void 0;
|
|
320
|
+
}
|
|
321
|
+
const status = Number.isInteger(candidate.status) ? candidate.status : candidate.statusCode;
|
|
322
|
+
if (typeof status !== "number" || !Number.isInteger(status) || status < CLIENT_ERROR_MIN2 || status >= CLIENT_ERROR_MAX2) {
|
|
323
|
+
return void 0;
|
|
324
|
+
}
|
|
325
|
+
const message = exception instanceof Error ? exception.message : "";
|
|
326
|
+
return { status, message: message === "" ? INTERNAL_ERROR_MESSAGE : message };
|
|
327
|
+
}
|
|
311
328
|
function isValidationResponse(response) {
|
|
312
329
|
return typeof response === "object" && response !== null && "message" in response && Array.isArray(response.message);
|
|
313
330
|
}
|
|
@@ -422,6 +439,15 @@ var BymaxExceptionFilter = class {
|
|
|
422
439
|
if (exception instanceof HttpException) {
|
|
423
440
|
return this.mapHttpException(exception, context);
|
|
424
441
|
}
|
|
442
|
+
const exposed = resolveExposedClientError(exception);
|
|
443
|
+
if (exposed !== void 0) {
|
|
444
|
+
return this.toEnvelope(
|
|
445
|
+
exposed.status,
|
|
446
|
+
codeForStatus(exposed.status),
|
|
447
|
+
exposed.message,
|
|
448
|
+
context
|
|
449
|
+
);
|
|
450
|
+
}
|
|
425
451
|
try {
|
|
426
452
|
this.onUnexpectedError(exception, context);
|
|
427
453
|
} catch {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bymax-one/nest-core",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.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",
|