@zudojs/errors 1.1.0 → 1.2.0
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/dist/base/core/errorCause.redact.d.ts +8 -3
- package/dist/base/core/errorCause.redact.js +18 -7
- package/dist/base/types/errorCode.type.d.ts +1 -0
- package/dist/base/types/errorCode.type.js +1 -0
- package/dist/domain/event/event.error.d.ts +1 -1
- package/dist/domain/event/event.error.js +1 -1
- package/dist/domain/event/eventError.lifecycle.d.ts +16 -0
- package/dist/domain/event/eventError.lifecycle.js +31 -0
- package/package.json +1 -1
|
@@ -10,11 +10,16 @@
|
|
|
10
10
|
* Redacts sensitive keys inside a record without changing its shape:
|
|
11
11
|
* primitives, dates and class instances are kept, plain objects and arrays
|
|
12
12
|
* are walked, cycles stop at `"[Circular]"`, prototype keys are dropped.
|
|
13
|
+
*
|
|
14
|
+
* The walk is depth-bounded exactly as metadata cloning is: a subtree past
|
|
15
|
+
* {@link MAX_METADATA_DEPTH} becomes `"[MaxDepth]"`. Without that bound a
|
|
16
|
+
* parsed request body attached as a cause could overflow the stack *inside*
|
|
17
|
+
* the serializer, turning a logged error into an uncaught `RangeError`.
|
|
13
18
|
*/
|
|
14
|
-
export declare function redactCauseFields(fields: Record<string, unknown>, pattern: RegExp | undefined, seen?: WeakSet<object
|
|
19
|
+
export declare function redactCauseFields(fields: Record<string, unknown>, pattern: RegExp | undefined, seen?: WeakSet<object>, depth?: number): Record<string, unknown>;
|
|
15
20
|
/**
|
|
16
21
|
* Redacts one cause value: arrays and plain objects are walked, every other
|
|
17
|
-
* value is returned unchanged.
|
|
22
|
+
* value is returned unchanged. Walking stops at {@link MAX_METADATA_DEPTH}.
|
|
18
23
|
*/
|
|
19
|
-
export declare function redactCauseValue(value: unknown, pattern: RegExp | undefined, seen?: WeakSet<object
|
|
24
|
+
export declare function redactCauseValue(value: unknown, pattern: RegExp | undefined, seen?: WeakSet<object>, depth?: number): unknown;
|
|
20
25
|
//# sourceMappingURL=errorCause.redact.d.ts.map
|
|
@@ -6,7 +6,9 @@
|
|
|
6
6
|
*
|
|
7
7
|
* @module base/core/errorCause.redact
|
|
8
8
|
*/
|
|
9
|
-
import { isForbiddenMetadataKey, isSensitiveMetadataKey, REDACTED_METADATA_VALUE, } from "./errorMetadata.core.js";
|
|
9
|
+
import { isForbiddenMetadataKey, isSensitiveMetadataKey, MAX_METADATA_DEPTH, REDACTED_METADATA_VALUE, } from "./errorMetadata.core.js";
|
|
10
|
+
/** Marker substituted for a cause subtree deeper than {@link MAX_METADATA_DEPTH}. */
|
|
11
|
+
const MAX_DEPTH_VALUE = "[MaxDepth]";
|
|
10
12
|
/** Plain objects (Object.prototype or null prototype) are walked; anything else is kept as-is. */
|
|
11
13
|
function isPlainRecord(value) {
|
|
12
14
|
if (value === null || typeof value !== "object")
|
|
@@ -18,8 +20,13 @@ function isPlainRecord(value) {
|
|
|
18
20
|
* Redacts sensitive keys inside a record without changing its shape:
|
|
19
21
|
* primitives, dates and class instances are kept, plain objects and arrays
|
|
20
22
|
* are walked, cycles stop at `"[Circular]"`, prototype keys are dropped.
|
|
23
|
+
*
|
|
24
|
+
* The walk is depth-bounded exactly as metadata cloning is: a subtree past
|
|
25
|
+
* {@link MAX_METADATA_DEPTH} becomes `"[MaxDepth]"`. Without that bound a
|
|
26
|
+
* parsed request body attached as a cause could overflow the stack *inside*
|
|
27
|
+
* the serializer, turning a logged error into an uncaught `RangeError`.
|
|
21
28
|
*/
|
|
22
|
-
export function redactCauseFields(fields, pattern, seen = new WeakSet()) {
|
|
29
|
+
export function redactCauseFields(fields, pattern, seen = new WeakSet(), depth = 0) {
|
|
23
30
|
const result = {};
|
|
24
31
|
for (const key of Object.keys(fields)) {
|
|
25
32
|
if (isForbiddenMetadataKey(key))
|
|
@@ -29,21 +36,23 @@ export function redactCauseFields(fields, pattern, seen = new WeakSet()) {
|
|
|
29
36
|
: isSensitiveMetadataKey(key, pattern);
|
|
30
37
|
result[key] = sensitive
|
|
31
38
|
? REDACTED_METADATA_VALUE
|
|
32
|
-
: redactCauseValue(fields[key], pattern, seen);
|
|
39
|
+
: redactCauseValue(fields[key], pattern, seen, depth + 1);
|
|
33
40
|
}
|
|
34
41
|
return result;
|
|
35
42
|
}
|
|
36
43
|
/**
|
|
37
44
|
* Redacts one cause value: arrays and plain objects are walked, every other
|
|
38
|
-
* value is returned unchanged.
|
|
45
|
+
* value is returned unchanged. Walking stops at {@link MAX_METADATA_DEPTH}.
|
|
39
46
|
*/
|
|
40
|
-
export function redactCauseValue(value, pattern, seen = new WeakSet()) {
|
|
47
|
+
export function redactCauseValue(value, pattern, seen = new WeakSet(), depth = 0) {
|
|
41
48
|
if (Array.isArray(value)) {
|
|
49
|
+
if (depth > MAX_METADATA_DEPTH)
|
|
50
|
+
return MAX_DEPTH_VALUE;
|
|
42
51
|
if (seen.has(value))
|
|
43
52
|
return "[Circular]";
|
|
44
53
|
seen.add(value);
|
|
45
54
|
try {
|
|
46
|
-
return value.map((entry) => redactCauseValue(entry, pattern, seen));
|
|
55
|
+
return value.map((entry) => redactCauseValue(entry, pattern, seen, depth + 1));
|
|
47
56
|
}
|
|
48
57
|
finally {
|
|
49
58
|
seen.delete(value);
|
|
@@ -51,11 +60,13 @@ export function redactCauseValue(value, pattern, seen = new WeakSet()) {
|
|
|
51
60
|
}
|
|
52
61
|
if (!isPlainRecord(value))
|
|
53
62
|
return value;
|
|
63
|
+
if (depth > MAX_METADATA_DEPTH)
|
|
64
|
+
return MAX_DEPTH_VALUE;
|
|
54
65
|
if (seen.has(value))
|
|
55
66
|
return "[Circular]";
|
|
56
67
|
seen.add(value);
|
|
57
68
|
try {
|
|
58
|
-
return redactCauseFields(value, pattern, seen);
|
|
69
|
+
return redactCauseFields(value, pattern, seen, depth);
|
|
59
70
|
}
|
|
60
71
|
finally {
|
|
61
72
|
seen.delete(value);
|
|
@@ -114,6 +114,7 @@ export declare enum ErrorCode {
|
|
|
114
114
|
EVENT_REGISTRY_DISPOSED = "ERR_EVENT_REGISTRY_DISPOSED",
|
|
115
115
|
EVENT_BUS_DISPOSED = "ERR_EVENT_BUS_DISPOSED",
|
|
116
116
|
EVENT_SUBSCRIPTION_CLOSED = "ERR_EVENT_SUBSCRIPTION_CLOSED",
|
|
117
|
+
EVENT_LISTENER_LIMIT_EXCEEDED = "ERR_EVENT_LISTENER_LIMIT_EXCEEDED",
|
|
117
118
|
EVENT_TIMEOUT = "ERR_EVENT_TIMEOUT",
|
|
118
119
|
EVENT_SERIALIZATION_FAILED = "ERR_EVENT_SERIALIZATION_FAILED",
|
|
119
120
|
EVENT_DESERIALIZATION_FAILED = "ERR_EVENT_DESERIALIZATION_FAILED",
|
|
@@ -120,6 +120,7 @@ export var ErrorCode;
|
|
|
120
120
|
ErrorCode["EVENT_REGISTRY_DISPOSED"] = "ERR_EVENT_REGISTRY_DISPOSED";
|
|
121
121
|
ErrorCode["EVENT_BUS_DISPOSED"] = "ERR_EVENT_BUS_DISPOSED";
|
|
122
122
|
ErrorCode["EVENT_SUBSCRIPTION_CLOSED"] = "ERR_EVENT_SUBSCRIPTION_CLOSED";
|
|
123
|
+
ErrorCode["EVENT_LISTENER_LIMIT_EXCEEDED"] = "ERR_EVENT_LISTENER_LIMIT_EXCEEDED";
|
|
123
124
|
ErrorCode["EVENT_TIMEOUT"] = "ERR_EVENT_TIMEOUT";
|
|
124
125
|
ErrorCode["EVENT_SERIALIZATION_FAILED"] = "ERR_EVENT_SERIALIZATION_FAILED";
|
|
125
126
|
ErrorCode["EVENT_DESERIALIZATION_FAILED"] = "ERR_EVENT_DESERIALIZATION_FAILED";
|
|
@@ -4,6 +4,6 @@
|
|
|
4
4
|
export { EventError, createEventError, isEventError, toEventError, } from "./eventError.base.js";
|
|
5
5
|
export type { EventErrorOptions } from "./eventError.base.js";
|
|
6
6
|
export { EventHandlerError, createEventHandlerError, EventHandlerNotFoundError, DuplicateEventHandlerError, EventMiddlewareError, } from "./eventError.handler.js";
|
|
7
|
-
export { EventPublishError, InvalidEventError, EventTypeNotFoundError, DuplicateEventDefinitionError, EventDefinitionNotFoundError, EventDispatchAbortedError, EventEmitterDisposedError, EventRegistryDisposedError, EventSubscriptionClosedError, EventBusDisposedError, EventTimeoutError, } from "./eventError.lifecycle.js";
|
|
7
|
+
export { EventPublishError, InvalidEventError, EventTypeNotFoundError, DuplicateEventDefinitionError, EventDefinitionNotFoundError, EventDispatchAbortedError, EventEmitterDisposedError, EventRegistryDisposedError, EventSubscriptionClosedError, EventBusDisposedError, EventListenerLimitExceededError, EventTimeoutError, } from "./eventError.lifecycle.js";
|
|
8
8
|
export { EventSerializationError, EventDeserializationError, } from "./eventError.serialization.js";
|
|
9
9
|
//# sourceMappingURL=event.error.d.ts.map
|
|
@@ -3,6 +3,6 @@
|
|
|
3
3
|
*/
|
|
4
4
|
export { EventError, createEventError, isEventError, toEventError, } from "./eventError.base.js";
|
|
5
5
|
export { EventHandlerError, createEventHandlerError, EventHandlerNotFoundError, DuplicateEventHandlerError, EventMiddlewareError, } from "./eventError.handler.js";
|
|
6
|
-
export { EventPublishError, InvalidEventError, EventTypeNotFoundError, DuplicateEventDefinitionError, EventDefinitionNotFoundError, EventDispatchAbortedError, EventEmitterDisposedError, EventRegistryDisposedError, EventSubscriptionClosedError, EventBusDisposedError, EventTimeoutError, } from "./eventError.lifecycle.js";
|
|
6
|
+
export { EventPublishError, InvalidEventError, EventTypeNotFoundError, DuplicateEventDefinitionError, EventDefinitionNotFoundError, EventDispatchAbortedError, EventEmitterDisposedError, EventRegistryDisposedError, EventSubscriptionClosedError, EventBusDisposedError, EventListenerLimitExceededError, EventTimeoutError, } from "./eventError.lifecycle.js";
|
|
7
7
|
export { EventSerializationError, EventDeserializationError, } from "./eventError.serialization.js";
|
|
8
8
|
//# sourceMappingURL=event.error.js.map
|
|
@@ -62,6 +62,22 @@ export declare class EventSubscriptionClosedError extends EventError {
|
|
|
62
62
|
export declare class EventBusDisposedError extends EventError {
|
|
63
63
|
constructor();
|
|
64
64
|
}
|
|
65
|
+
/**
|
|
66
|
+
* Error thrown when a pattern exceeds its configured handler limit.
|
|
67
|
+
*
|
|
68
|
+
* The limit exists to catch a subscribe-without-unsubscribe leak. Registering
|
|
69
|
+
* past it is a programming fault rather than bad input, so this is reported as
|
|
70
|
+
* internal and is never exposed to a caller.
|
|
71
|
+
*
|
|
72
|
+
* A registry only raises this when it is configured to enforce the limit;
|
|
73
|
+
* the default is a one-shot warning, which does not interrupt registration.
|
|
74
|
+
*/
|
|
75
|
+
export declare class EventListenerLimitExceededError extends EventError {
|
|
76
|
+
readonly pattern: string;
|
|
77
|
+
readonly count: number;
|
|
78
|
+
readonly limit: number;
|
|
79
|
+
constructor(pattern: string, count: number, limit: number);
|
|
80
|
+
}
|
|
65
81
|
/** Error thrown when an event operation times out. */
|
|
66
82
|
export declare class EventTimeoutError extends EventError {
|
|
67
83
|
readonly timeoutMs: number;
|
|
@@ -130,6 +130,37 @@ export class EventBusDisposedError extends EventError {
|
|
|
130
130
|
});
|
|
131
131
|
}
|
|
132
132
|
}
|
|
133
|
+
/**
|
|
134
|
+
* Error thrown when a pattern exceeds its configured handler limit.
|
|
135
|
+
*
|
|
136
|
+
* The limit exists to catch a subscribe-without-unsubscribe leak. Registering
|
|
137
|
+
* past it is a programming fault rather than bad input, so this is reported as
|
|
138
|
+
* internal and is never exposed to a caller.
|
|
139
|
+
*
|
|
140
|
+
* A registry only raises this when it is configured to enforce the limit;
|
|
141
|
+
* the default is a one-shot warning, which does not interrupt registration.
|
|
142
|
+
*/
|
|
143
|
+
export class EventListenerLimitExceededError extends EventError {
|
|
144
|
+
pattern;
|
|
145
|
+
count;
|
|
146
|
+
limit;
|
|
147
|
+
constructor(pattern, count, limit) {
|
|
148
|
+
assertFiniteNonNegative("count", count);
|
|
149
|
+
assertFiniteNonNegative("limit", limit);
|
|
150
|
+
super(`Possible event handler leak: ${count} handlers registered for ` +
|
|
151
|
+
`"${pattern}" (limit ${limit}). Unsubscribe handlers you no longer ` +
|
|
152
|
+
"need or raise maxHandlersPerPattern / maxListeners.", {
|
|
153
|
+
code: ErrorCode.EVENT_LISTENER_LIMIT_EXCEEDED,
|
|
154
|
+
metadata: { pattern, count, limit },
|
|
155
|
+
statusCode: 500,
|
|
156
|
+
expose: false,
|
|
157
|
+
isOperational: false,
|
|
158
|
+
});
|
|
159
|
+
this.pattern = pattern;
|
|
160
|
+
this.count = count;
|
|
161
|
+
this.limit = limit;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
133
164
|
/** Error thrown when an event operation times out. */
|
|
134
165
|
export class EventTimeoutError extends EventError {
|
|
135
166
|
timeoutMs;
|