@zudojs/events 0.0.1 → 1.0.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/README.md +70 -11
- package/dist/eventBus/eventBus.core.d.ts +28 -2
- package/dist/eventBus/eventBus.core.js +104 -31
- package/dist/eventBus/eventBus.publish.d.ts +23 -5
- package/dist/eventBus/eventBus.publish.js +72 -32
- package/dist/eventBus/eventBus.registration.d.ts +24 -13
- package/dist/eventBus/eventBus.registration.js +31 -28
- package/dist/eventBus/eventBus.type.d.ts +75 -3
- package/dist/eventBus/eventBus.type.js +9 -0
- package/dist/eventBus/index.d.ts +2 -0
- package/dist/eventBus/index.js +2 -0
- package/dist/eventEmitter/eventEmitter.abort.d.ts +11 -2
- package/dist/eventEmitter/eventEmitter.abort.js +20 -5
- package/dist/eventEmitter/eventEmitter.core.d.ts +14 -3
- package/dist/eventEmitter/eventEmitter.core.js +63 -55
- package/dist/eventEmitter/eventEmitter.parallel.d.ts +7 -1
- package/dist/eventEmitter/eventEmitter.parallel.js +31 -13
- package/dist/eventEmitter/eventEmitter.sequential.d.ts +17 -1
- package/dist/eventEmitter/eventEmitter.sequential.js +19 -12
- package/dist/eventEmitter/eventEmitter.type.d.ts +60 -0
- package/dist/eventErrors/eventError.base.d.ts +50 -3
- package/dist/eventErrors/eventError.base.js +64 -3
- package/dist/eventHandler/eventHandler.core.d.ts +19 -0
- package/dist/eventHandler/eventHandler.core.js +67 -4
- package/dist/eventMiddleware/eventMiddleware.builder.js +5 -11
- package/dist/eventMiddleware/eventMiddleware.helper.js +0 -1
- package/dist/eventMiddleware/eventMiddleware.pipeline.d.ts +5 -0
- package/dist/eventMiddleware/eventMiddleware.pipeline.js +33 -9
- package/dist/eventRegistry/eventRegistry.lifecycle.d.ts +10 -5
- package/dist/eventRegistry/eventRegistry.lifecycle.js +23 -10
- package/dist/eventRegistry/eventRegistry.queries.d.ts +16 -7
- package/dist/eventRegistry/eventRegistry.queries.js +22 -13
- package/dist/eventRegistry/eventRegistry.registration.d.ts +14 -7
- package/dist/eventRegistry/eventRegistry.registration.js +120 -41
- package/dist/eventRegistry/eventRegistry.store.d.ts +12 -5
- package/dist/eventRegistry/eventRegistry.store.js +37 -12
- package/dist/eventRegistry/eventRegistry.type.d.ts +87 -2
- package/dist/eventRegistry/eventRegistry.type.js +5 -0
- package/dist/eventSubscription/eventSubscription.core.d.ts +5 -0
- package/dist/eventSubscription/eventSubscription.core.js +17 -3
- package/dist/eventTypes/eventDefinition.type.d.ts +11 -4
- package/dist/eventTypes/eventDefinition.type.js +49 -17
- package/dist/eventTypes/eventPayload.type.d.ts +5 -0
- package/dist/eventTypes/eventPayload.type.js +56 -15
- package/dist/eventTypes/eventType.type.d.ts +22 -5
- package/dist/eventTypes/eventType.type.js +33 -11
- package/dist/eventTypes/index.d.ts +2 -2
- package/dist/eventTypes/index.js +2 -2
- package/package.json +15 -7
- package/dist/.tsbuildinfo +0 -1
- package/dist/eventBus/eventBus.core.d.ts.map +0 -1
- package/dist/eventBus/eventBus.core.js.map +0 -1
- package/dist/eventBus/eventBus.factory.d.ts.map +0 -1
- package/dist/eventBus/eventBus.factory.js.map +0 -1
- package/dist/eventBus/eventBus.publish.d.ts.map +0 -1
- package/dist/eventBus/eventBus.publish.js.map +0 -1
- package/dist/eventBus/eventBus.registration.d.ts.map +0 -1
- package/dist/eventBus/eventBus.registration.js.map +0 -1
- package/dist/eventBus/eventBus.type.d.ts.map +0 -1
- package/dist/eventBus/eventBus.type.js.map +0 -1
- package/dist/eventBus/index.d.ts.map +0 -1
- package/dist/eventBus/index.js.map +0 -1
- package/dist/eventEmitter/eventEmitter.abort.d.ts.map +0 -1
- package/dist/eventEmitter/eventEmitter.abort.js.map +0 -1
- package/dist/eventEmitter/eventEmitter.core.d.ts.map +0 -1
- package/dist/eventEmitter/eventEmitter.core.js.map +0 -1
- package/dist/eventEmitter/eventEmitter.parallel.d.ts.map +0 -1
- package/dist/eventEmitter/eventEmitter.parallel.js.map +0 -1
- package/dist/eventEmitter/eventEmitter.sequential.d.ts.map +0 -1
- package/dist/eventEmitter/eventEmitter.sequential.js.map +0 -1
- package/dist/eventEmitter/eventEmitter.type.d.ts.map +0 -1
- package/dist/eventEmitter/eventEmitter.type.js.map +0 -1
- package/dist/eventEmitter/index.d.ts.map +0 -1
- package/dist/eventEmitter/index.js.map +0 -1
- package/dist/eventErrors/eventError.base.d.ts.map +0 -1
- package/dist/eventErrors/eventError.base.js.map +0 -1
- package/dist/eventErrors/index.d.ts.map +0 -1
- package/dist/eventErrors/index.js.map +0 -1
- package/dist/eventHandler/eventHandler.core.d.ts.map +0 -1
- package/dist/eventHandler/eventHandler.core.js.map +0 -1
- package/dist/eventHandler/index.d.ts.map +0 -1
- package/dist/eventHandler/index.js.map +0 -1
- package/dist/eventMiddleware/eventMiddleware.builder.d.ts.map +0 -1
- package/dist/eventMiddleware/eventMiddleware.builder.js.map +0 -1
- package/dist/eventMiddleware/eventMiddleware.helper.d.ts.map +0 -1
- package/dist/eventMiddleware/eventMiddleware.helper.js.map +0 -1
- package/dist/eventMiddleware/eventMiddleware.pipeline.d.ts.map +0 -1
- package/dist/eventMiddleware/eventMiddleware.pipeline.js.map +0 -1
- package/dist/eventMiddleware/eventMiddleware.type.d.ts.map +0 -1
- package/dist/eventMiddleware/eventMiddleware.type.js.map +0 -1
- package/dist/eventMiddleware/index.d.ts.map +0 -1
- package/dist/eventMiddleware/index.js.map +0 -1
- package/dist/eventRegistry/eventRegistry.lifecycle.d.ts.map +0 -1
- package/dist/eventRegistry/eventRegistry.lifecycle.js.map +0 -1
- package/dist/eventRegistry/eventRegistry.queries.d.ts.map +0 -1
- package/dist/eventRegistry/eventRegistry.queries.js.map +0 -1
- package/dist/eventRegistry/eventRegistry.registration.d.ts.map +0 -1
- package/dist/eventRegistry/eventRegistry.registration.js.map +0 -1
- package/dist/eventRegistry/eventRegistry.store.d.ts.map +0 -1
- package/dist/eventRegistry/eventRegistry.store.js.map +0 -1
- package/dist/eventRegistry/eventRegistry.type.d.ts.map +0 -1
- package/dist/eventRegistry/eventRegistry.type.js.map +0 -1
- package/dist/eventRegistry/index.d.ts.map +0 -1
- package/dist/eventRegistry/index.js.map +0 -1
- package/dist/eventSubscription/eventSubscription.core.d.ts.map +0 -1
- package/dist/eventSubscription/eventSubscription.core.js.map +0 -1
- package/dist/eventSubscription/index.d.ts.map +0 -1
- package/dist/eventSubscription/index.js.map +0 -1
- package/dist/eventTypes/eventDefinition.type.d.ts.map +0 -1
- package/dist/eventTypes/eventDefinition.type.js.map +0 -1
- package/dist/eventTypes/eventPayload.type.d.ts.map +0 -1
- package/dist/eventTypes/eventPayload.type.js.map +0 -1
- package/dist/eventTypes/eventType.type.d.ts.map +0 -1
- package/dist/eventTypes/eventType.type.js.map +0 -1
- package/dist/eventTypes/index.d.ts.map +0 -1
- package/dist/eventTypes/index.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
|
@@ -146,17 +146,31 @@ export class EventSubscriptionGroup {
|
|
|
146
146
|
}
|
|
147
147
|
/**
|
|
148
148
|
* Unsubscribes every subscription in the group.
|
|
149
|
+
*
|
|
150
|
+
* Every subscription is attempted even if one throws; the
|
|
151
|
+
* failures are then re-thrown together as an AggregateError and
|
|
152
|
+
* the failed subscriptions stay in the group so the call can be
|
|
153
|
+
* retried.
|
|
149
154
|
*/
|
|
150
155
|
unsubscribe() {
|
|
151
156
|
if (!this.active) {
|
|
152
157
|
return;
|
|
153
158
|
}
|
|
154
|
-
this.currentState = EventSubscriptionState.CANCELLED;
|
|
155
159
|
const subscriptions = [...this.subscriptions];
|
|
156
|
-
|
|
160
|
+
const failures = [];
|
|
157
161
|
for (const subscription of subscriptions) {
|
|
158
|
-
|
|
162
|
+
try {
|
|
163
|
+
subscription.unsubscribe();
|
|
164
|
+
this.subscriptions.delete(subscription);
|
|
165
|
+
}
|
|
166
|
+
catch (error) {
|
|
167
|
+
failures.push(error);
|
|
168
|
+
}
|
|
159
169
|
}
|
|
170
|
+
if (failures.length > 0) {
|
|
171
|
+
throw new AggregateError(failures, `${failures.length} of ${subscriptions.length} subscriptions failed to unsubscribe.`);
|
|
172
|
+
}
|
|
173
|
+
this.currentState = EventSubscriptionState.CANCELLED;
|
|
160
174
|
}
|
|
161
175
|
/**
|
|
162
176
|
* Returns all subscriptions in the group.
|
|
@@ -95,9 +95,10 @@ export interface Event<TPayload = EventPayload> {
|
|
|
95
95
|
*/
|
|
96
96
|
export interface EventInput<TPayload = EventPayload> {
|
|
97
97
|
/**
|
|
98
|
-
* Optional event identifier.
|
|
98
|
+
* Optional event identifier. Plain strings are accepted and
|
|
99
|
+
* branded on the created event.
|
|
99
100
|
*/
|
|
100
|
-
readonly id?: EventId;
|
|
101
|
+
readonly id?: EventId | string;
|
|
101
102
|
/**
|
|
102
103
|
* Event type.
|
|
103
104
|
*/
|
|
@@ -115,9 +116,9 @@ export interface EventInput<TPayload = EventPayload> {
|
|
|
115
116
|
*/
|
|
116
117
|
readonly source?: EventSource;
|
|
117
118
|
/**
|
|
118
|
-
* Optional correlation identifier.
|
|
119
|
+
* Optional correlation identifier. Plain strings are accepted.
|
|
119
120
|
*/
|
|
120
|
-
readonly correlationId?: EventCorrelationId;
|
|
121
|
+
readonly correlationId?: EventCorrelationId | string;
|
|
121
122
|
/**
|
|
122
123
|
* Optional causation identifier.
|
|
123
124
|
*/
|
|
@@ -148,6 +149,12 @@ export declare function isEvent(value: unknown): value is Event;
|
|
|
148
149
|
export declare function createEventId(): EventId;
|
|
149
150
|
/**
|
|
150
151
|
* Creates an immutable event.
|
|
152
|
+
*
|
|
153
|
+
* The event type is normalized (trimmed, lower-cased, separators
|
|
154
|
+
* collapsed) and validated; invalid types, ids and timestamps
|
|
155
|
+
* throw InvalidEventError. The top-level event object is frozen;
|
|
156
|
+
* the payload is left as supplied (use deepFreeze / the emitter's
|
|
157
|
+
* freezeEvents option for deep immutability).
|
|
151
158
|
*/
|
|
152
159
|
export declare function createEvent<TPayload = EventPayload>(input: EventInput<TPayload>): Event<TPayload>;
|
|
153
160
|
/**
|
|
@@ -6,6 +6,8 @@
|
|
|
6
6
|
*
|
|
7
7
|
* This module intentionally contains no dispatching logic.
|
|
8
8
|
*/
|
|
9
|
+
import { InvalidEventError } from "../eventErrors/eventError.base.js";
|
|
10
|
+
import { normalizeEventType } from "./eventType.type.js";
|
|
9
11
|
/**
|
|
10
12
|
* Determines whether an unknown value satisfies the Event
|
|
11
13
|
* contract.
|
|
@@ -32,17 +34,39 @@ export function createEventId() {
|
|
|
32
34
|
* Normalizes an event timestamp.
|
|
33
35
|
*/
|
|
34
36
|
function normalizeTimestamp(timestamp) {
|
|
35
|
-
if (timestamp
|
|
36
|
-
return new Date(
|
|
37
|
+
if (timestamp === undefined) {
|
|
38
|
+
return new Date();
|
|
37
39
|
}
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
40
|
+
const date = timestamp instanceof Date
|
|
41
|
+
? new Date(timestamp.getTime())
|
|
42
|
+
: typeof timestamp === "number"
|
|
43
|
+
? new Date(timestamp)
|
|
44
|
+
: undefined;
|
|
45
|
+
if (date === undefined || Number.isNaN(date.getTime())) {
|
|
46
|
+
throw new InvalidEventError("Invalid event timestamp.");
|
|
47
|
+
}
|
|
48
|
+
return date;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Normalizes and validates an event type, converting validation
|
|
52
|
+
* failures into InvalidEventError.
|
|
53
|
+
*/
|
|
54
|
+
function normalizeInputType(type, eventId) {
|
|
55
|
+
if (typeof type !== "string" || type.trim().length === 0) {
|
|
56
|
+
throw new InvalidEventError("Event type must be a non-empty string.", {
|
|
57
|
+
eventId,
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
try {
|
|
61
|
+
return normalizeEventType(type);
|
|
62
|
+
}
|
|
63
|
+
catch (error) {
|
|
64
|
+
throw new InvalidEventError(`Invalid event type "${type}".`, {
|
|
65
|
+
eventType: type,
|
|
66
|
+
eventId,
|
|
67
|
+
cause: error,
|
|
68
|
+
});
|
|
44
69
|
}
|
|
45
|
-
return new Date();
|
|
46
70
|
}
|
|
47
71
|
/**
|
|
48
72
|
* Freezes event metadata.
|
|
@@ -57,14 +81,24 @@ function normalizeMetadata(metadata) {
|
|
|
57
81
|
}
|
|
58
82
|
/**
|
|
59
83
|
* Creates an immutable event.
|
|
84
|
+
*
|
|
85
|
+
* The event type is normalized (trimmed, lower-cased, separators
|
|
86
|
+
* collapsed) and validated; invalid types, ids and timestamps
|
|
87
|
+
* throw InvalidEventError. The top-level event object is frozen;
|
|
88
|
+
* the payload is left as supplied (use deepFreeze / the emitter's
|
|
89
|
+
* freezeEvents option for deep immutability).
|
|
60
90
|
*/
|
|
61
91
|
export function createEvent(input) {
|
|
62
|
-
if (typeof input
|
|
63
|
-
throw new
|
|
92
|
+
if (typeof input !== "object" || input === null) {
|
|
93
|
+
throw new InvalidEventError("Event input must be an object.");
|
|
94
|
+
}
|
|
95
|
+
if (input.id !== undefined && typeof input.id !== "string") {
|
|
96
|
+
throw new InvalidEventError("Event id must be a string.");
|
|
64
97
|
}
|
|
98
|
+
const type = normalizeInputType(input.type, input.id);
|
|
65
99
|
const event = {
|
|
66
100
|
id: input.id ?? createEventId(),
|
|
67
|
-
type
|
|
101
|
+
type,
|
|
68
102
|
payload: input.payload,
|
|
69
103
|
timestamp: normalizeTimestamp(input.timestamp),
|
|
70
104
|
source: input.source,
|
|
@@ -78,15 +112,13 @@ export function createEvent(input) {
|
|
|
78
112
|
* Creates a typed event definition.
|
|
79
113
|
*/
|
|
80
114
|
export function defineEvent(type) {
|
|
81
|
-
|
|
82
|
-
throw new TypeError("Event type must be a non-empty string.");
|
|
83
|
-
}
|
|
115
|
+
const normalized = normalizeInputType(type);
|
|
84
116
|
return Object.freeze({
|
|
85
|
-
type,
|
|
117
|
+
type: normalized,
|
|
86
118
|
create(payload, options = {}) {
|
|
87
119
|
return createEvent({
|
|
88
120
|
...options,
|
|
89
|
-
type,
|
|
121
|
+
type: normalized,
|
|
90
122
|
payload,
|
|
91
123
|
});
|
|
92
124
|
},
|
|
@@ -93,6 +93,11 @@ export declare function createJsonEventPayload<const TPayload extends JsonEventP
|
|
|
93
93
|
export declare function cloneEventPayload<TPayload extends EventPayload>(payload: TPayload): TPayload;
|
|
94
94
|
/**
|
|
95
95
|
* Deeply freezes an event payload.
|
|
96
|
+
*
|
|
97
|
+
* Cyclic and shared references are handled (each object is
|
|
98
|
+
* visited once), and an already frozen parent is still traversed
|
|
99
|
+
* so that unfrozen children are frozen too. ArrayBuffer views are
|
|
100
|
+
* left untouched because they cannot be frozen.
|
|
96
101
|
*/
|
|
97
102
|
export declare function deepFreeze<T>(value: T): T;
|
|
98
103
|
/**
|
|
@@ -24,6 +24,17 @@ export function isObjectEventPayload(value) {
|
|
|
24
24
|
* event payload.
|
|
25
25
|
*/
|
|
26
26
|
export function isJsonEventPayload(value) {
|
|
27
|
+
return isJsonValue(value, new WeakSet(), 0);
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Maximum nesting depth accepted by isJsonEventPayload.
|
|
31
|
+
*/
|
|
32
|
+
const MAX_JSON_PAYLOAD_DEPTH = 256;
|
|
33
|
+
function isPlainObject(value) {
|
|
34
|
+
const prototype = Object.getPrototypeOf(value);
|
|
35
|
+
return prototype === Object.prototype || prototype === null;
|
|
36
|
+
}
|
|
37
|
+
function isJsonValue(value, visited, depth) {
|
|
27
38
|
if (value === null ||
|
|
28
39
|
typeof value === "string" ||
|
|
29
40
|
typeof value === "boolean") {
|
|
@@ -32,13 +43,31 @@ export function isJsonEventPayload(value) {
|
|
|
32
43
|
if (typeof value === "number") {
|
|
33
44
|
return Number.isFinite(value);
|
|
34
45
|
}
|
|
35
|
-
if (
|
|
36
|
-
return
|
|
46
|
+
if (typeof value !== "object") {
|
|
47
|
+
return false;
|
|
48
|
+
}
|
|
49
|
+
if (depth > MAX_JSON_PAYLOAD_DEPTH) {
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
if (visited.has(value)) {
|
|
53
|
+
// A cycle can never be serialized to JSON.
|
|
54
|
+
return false;
|
|
37
55
|
}
|
|
38
|
-
|
|
39
|
-
|
|
56
|
+
visited.add(value);
|
|
57
|
+
try {
|
|
58
|
+
if (Array.isArray(value)) {
|
|
59
|
+
return value.every((item) => isJsonValue(item, visited, depth + 1));
|
|
60
|
+
}
|
|
61
|
+
if (!isPlainObject(value)) {
|
|
62
|
+
// Date, Map, Set, class instances, typed arrays, ... are not
|
|
63
|
+
// JSON values even though JSON.stringify may accept them.
|
|
64
|
+
return false;
|
|
65
|
+
}
|
|
66
|
+
return Object.values(value).every((item) => isJsonValue(item, visited, depth + 1));
|
|
67
|
+
}
|
|
68
|
+
finally {
|
|
69
|
+
visited.delete(value);
|
|
40
70
|
}
|
|
41
|
-
return false;
|
|
42
71
|
}
|
|
43
72
|
/**
|
|
44
73
|
* Creates a payload object from an input object.
|
|
@@ -87,24 +116,36 @@ export function cloneEventPayload(payload) {
|
|
|
87
116
|
}
|
|
88
117
|
/**
|
|
89
118
|
* Deeply freezes an event payload.
|
|
119
|
+
*
|
|
120
|
+
* Cyclic and shared references are handled (each object is
|
|
121
|
+
* visited once), and an already frozen parent is still traversed
|
|
122
|
+
* so that unfrozen children are frozen too. ArrayBuffer views are
|
|
123
|
+
* left untouched because they cannot be frozen.
|
|
90
124
|
*/
|
|
91
125
|
export function deepFreeze(value) {
|
|
92
|
-
|
|
93
|
-
|
|
126
|
+
freezeRecursively(value, new WeakSet());
|
|
127
|
+
return value;
|
|
128
|
+
}
|
|
129
|
+
function freezeRecursively(value, visited) {
|
|
130
|
+
if ((typeof value !== "object" && typeof value !== "function") ||
|
|
131
|
+
value === null) {
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
if (visited.has(value)) {
|
|
135
|
+
return;
|
|
94
136
|
}
|
|
95
|
-
|
|
96
|
-
|
|
137
|
+
visited.add(value);
|
|
138
|
+
if (ArrayBuffer.isView(value)) {
|
|
139
|
+
return;
|
|
97
140
|
}
|
|
98
141
|
const object = value;
|
|
99
142
|
for (const key of Reflect.ownKeys(object)) {
|
|
100
|
-
const
|
|
101
|
-
if (
|
|
102
|
-
|
|
103
|
-
!Object.isFrozen(child)) {
|
|
104
|
-
deepFreeze(child);
|
|
143
|
+
const descriptor = Object.getOwnPropertyDescriptor(object, key);
|
|
144
|
+
if (descriptor && "value" in descriptor) {
|
|
145
|
+
freezeRecursively(descriptor.value, visited);
|
|
105
146
|
}
|
|
106
147
|
}
|
|
107
|
-
|
|
148
|
+
Object.freeze(value);
|
|
108
149
|
}
|
|
109
150
|
/**
|
|
110
151
|
* Removes undefined properties from an object payload.
|
|
@@ -6,6 +6,8 @@
|
|
|
6
6
|
* and strongly typed event-type helpers.
|
|
7
7
|
*/
|
|
8
8
|
import type { Event, EventType } from "../eventTypes/eventDefinition.type.js";
|
|
9
|
+
import type { EventPayloadMap } from "./eventPayload.type.js";
|
|
10
|
+
export type { EventPayloadMap } from "./eventPayload.type.js";
|
|
9
11
|
/**
|
|
10
12
|
* A collection of event types.
|
|
11
13
|
*/
|
|
@@ -20,10 +22,6 @@ export type EventTypeList = readonly EventType[];
|
|
|
20
22
|
* "*"
|
|
21
23
|
*/
|
|
22
24
|
export type EventTypePattern = EventType | `${string}.*` | "*";
|
|
23
|
-
/**
|
|
24
|
-
* Type-safe mapping between event types and payloads.
|
|
25
|
-
*/
|
|
26
|
-
export type EventPayloadMap = Record<EventType, unknown>;
|
|
27
25
|
/**
|
|
28
26
|
* Extracts the event type keys from a payload map.
|
|
29
27
|
*/
|
|
@@ -39,7 +37,9 @@ export type EventUnion<TMap extends EventPayloadMap> = {
|
|
|
39
37
|
/**
|
|
40
38
|
* Validates an event type string.
|
|
41
39
|
*
|
|
42
|
-
* Zudojs event types use dot-separated lowercase names.
|
|
40
|
+
* Zudojs event types use dot-separated lowercase names. Wildcards
|
|
41
|
+
* are not part of an event type; they are only valid in patterns
|
|
42
|
+
* (see isValidEventTypePattern).
|
|
43
43
|
*
|
|
44
44
|
* Examples:
|
|
45
45
|
*
|
|
@@ -51,6 +51,10 @@ export type EventUnion<TMap extends EventPayloadMap> = {
|
|
|
51
51
|
export declare function isValidEventType(value: unknown): value is EventType;
|
|
52
52
|
/**
|
|
53
53
|
* Validates an event type pattern.
|
|
54
|
+
*
|
|
55
|
+
* Supported forms are an exact event type, a namespace wildcard
|
|
56
|
+
* ("user.*") and the catch-all "*". Wildcards in any other
|
|
57
|
+
* position ("user.*.created", "user.cre*") are rejected.
|
|
54
58
|
*/
|
|
55
59
|
export declare function isValidEventTypePattern(value: unknown): value is EventTypePattern;
|
|
56
60
|
/**
|
|
@@ -92,6 +96,13 @@ export declare function getEventAction(type: EventType): string;
|
|
|
92
96
|
* Returns all segments in an event type.
|
|
93
97
|
*/
|
|
94
98
|
export declare function getEventTypeSegments(type: EventType): readonly string[];
|
|
99
|
+
/**
|
|
100
|
+
* Normalizes an event type pattern.
|
|
101
|
+
*
|
|
102
|
+
* "*" is returned unchanged, "User.*" becomes "user.*" and any
|
|
103
|
+
* other value is normalized as an event type.
|
|
104
|
+
*/
|
|
105
|
+
export declare function normalizeEventTypePattern(pattern: string): EventTypePattern;
|
|
95
106
|
/**
|
|
96
107
|
* Checks whether an event type matches a pattern.
|
|
97
108
|
*
|
|
@@ -99,8 +110,14 @@ export declare function getEventTypeSegments(type: EventType): readonly string[]
|
|
|
99
110
|
*
|
|
100
111
|
* "user.created" matches "user.created"
|
|
101
112
|
* "user.created" matches "user.*"
|
|
113
|
+
* "user" matches "user.*" (a namespace pattern also
|
|
114
|
+
* matches the bare namespace event)
|
|
102
115
|
* "user.created" matches "*"
|
|
103
116
|
* "order.created" does not match "user.*"
|
|
117
|
+
*
|
|
118
|
+
* Both arguments are expected to be normalized (see
|
|
119
|
+
* normalizeEventType / normalizeEventTypePattern); no
|
|
120
|
+
* normalization happens here.
|
|
104
121
|
*/
|
|
105
122
|
export declare function matchesEventType(type: EventType, pattern: EventTypePattern): boolean;
|
|
106
123
|
/**
|
|
@@ -8,7 +8,9 @@
|
|
|
8
8
|
/**
|
|
9
9
|
* Validates an event type string.
|
|
10
10
|
*
|
|
11
|
-
* Zudojs event types use dot-separated lowercase names.
|
|
11
|
+
* Zudojs event types use dot-separated lowercase names. Wildcards
|
|
12
|
+
* are not part of an event type; they are only valid in patterns
|
|
13
|
+
* (see isValidEventTypePattern).
|
|
12
14
|
*
|
|
13
15
|
* Examples:
|
|
14
16
|
*
|
|
@@ -28,10 +30,14 @@ export function isValidEventType(value) {
|
|
|
28
30
|
if (normalized.length > 255) {
|
|
29
31
|
return false;
|
|
30
32
|
}
|
|
31
|
-
return /^[a-z0-9_]+(?:[.-][a-z0-9_
|
|
33
|
+
return /^[a-z0-9_]+(?:[.-][a-z0-9_]+)*$/.test(normalized);
|
|
32
34
|
}
|
|
33
35
|
/**
|
|
34
36
|
* Validates an event type pattern.
|
|
37
|
+
*
|
|
38
|
+
* Supported forms are an exact event type, a namespace wildcard
|
|
39
|
+
* ("user.*") and the catch-all "*". Wildcards in any other
|
|
40
|
+
* position ("user.*.created", "user.cre*") are rejected.
|
|
35
41
|
*/
|
|
36
42
|
export function isValidEventTypePattern(value) {
|
|
37
43
|
if (value === "*") {
|
|
@@ -56,26 +62,21 @@ export function isValidEventTypePattern(value) {
|
|
|
56
62
|
* 4. Removes leading/trailing separators
|
|
57
63
|
*/
|
|
58
64
|
export function normalizeEventType(type) {
|
|
65
|
+
if (typeof type !== "string") {
|
|
66
|
+
throw new TypeError(`Invalid event type: "${String(type)}".`);
|
|
67
|
+
}
|
|
59
68
|
const lower = type.trim().toLowerCase();
|
|
60
69
|
let result = "";
|
|
61
70
|
let lastWasDot = false;
|
|
62
|
-
let leadingDots = true;
|
|
63
71
|
for (let i = 0; i < lower.length; i++) {
|
|
64
72
|
const ch = lower[i];
|
|
65
|
-
if (ch === "/" || ch === "\\" || ch === ":") {
|
|
66
|
-
if (!lastWasDot) {
|
|
67
|
-
result += ".";
|
|
68
|
-
lastWasDot = true;
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
else if (ch === ".") {
|
|
73
|
+
if (ch === "/" || ch === "\\" || ch === ":" || ch === ".") {
|
|
72
74
|
if (!lastWasDot) {
|
|
73
75
|
result += ".";
|
|
74
76
|
lastWasDot = true;
|
|
75
77
|
}
|
|
76
78
|
}
|
|
77
79
|
else {
|
|
78
|
-
leadingDots = false;
|
|
79
80
|
result += ch;
|
|
80
81
|
lastWasDot = false;
|
|
81
82
|
}
|
|
@@ -139,6 +140,21 @@ export function getEventAction(type) {
|
|
|
139
140
|
export function getEventTypeSegments(type) {
|
|
140
141
|
return type.split(".");
|
|
141
142
|
}
|
|
143
|
+
/**
|
|
144
|
+
* Normalizes an event type pattern.
|
|
145
|
+
*
|
|
146
|
+
* "*" is returned unchanged, "User.*" becomes "user.*" and any
|
|
147
|
+
* other value is normalized as an event type.
|
|
148
|
+
*/
|
|
149
|
+
export function normalizeEventTypePattern(pattern) {
|
|
150
|
+
if (pattern === "*") {
|
|
151
|
+
return "*";
|
|
152
|
+
}
|
|
153
|
+
if (typeof pattern === "string" && pattern.trim().endsWith(".*")) {
|
|
154
|
+
return `${normalizeEventType(pattern.trim().slice(0, -2))}.*`;
|
|
155
|
+
}
|
|
156
|
+
return normalizeEventType(pattern);
|
|
157
|
+
}
|
|
142
158
|
/**
|
|
143
159
|
* Checks whether an event type matches a pattern.
|
|
144
160
|
*
|
|
@@ -146,8 +162,14 @@ export function getEventTypeSegments(type) {
|
|
|
146
162
|
*
|
|
147
163
|
* "user.created" matches "user.created"
|
|
148
164
|
* "user.created" matches "user.*"
|
|
165
|
+
* "user" matches "user.*" (a namespace pattern also
|
|
166
|
+
* matches the bare namespace event)
|
|
149
167
|
* "user.created" matches "*"
|
|
150
168
|
* "order.created" does not match "user.*"
|
|
169
|
+
*
|
|
170
|
+
* Both arguments are expected to be normalized (see
|
|
171
|
+
* normalizeEventType / normalizeEventTypePattern); no
|
|
172
|
+
* normalization happens here.
|
|
151
173
|
*/
|
|
152
174
|
export function matchesEventType(type, pattern) {
|
|
153
175
|
if (pattern === "*") {
|
|
@@ -4,6 +4,6 @@
|
|
|
4
4
|
* Event type definitions and payload types.
|
|
5
5
|
*/
|
|
6
6
|
export { type EventId, type EventType, type EventTimestamp, type EventSource, type EventCorrelationId, type EventCausationId, type EventPayload, type Event, type EventInput, type EventDefinition, isEvent, createEventId, createEvent, defineEvent, withEventMetadata, createDerivedEvent, getEventType, getEventPayload, describeEvent, } from "./eventDefinition.type.js";
|
|
7
|
-
export { type ObjectEventPayload, type PrimitiveEventPayload, type JsonEventPayload, type PayloadOf, type PayloadMap, type EventPayloadFactory, type EventPayloadOptions, isPrimitiveEventPayload, isObjectEventPayload, isJsonEventPayload, createEventPayload, validateEventPayload, } from "./eventPayload.type.js";
|
|
8
|
-
export { type EventTypeList, type EventTypePattern, type EventTypeOf, type EventUnion, isValidEventType, isValidEventTypePattern, normalizeEventType, createEventType, getEventNamespace, } from "./eventType.type.js";
|
|
7
|
+
export { type ObjectEventPayload, type PrimitiveEventPayload, type JsonEventPayload, type EventPayloadMap, type PayloadOf, type PayloadMap, type EventPayloadFactory, type EventPayloadOptions, isPrimitiveEventPayload, isObjectEventPayload, isJsonEventPayload, createEventPayload, createObjectEventPayload, createJsonEventPayload, cloneEventPayload, deepFreeze, stripUndefinedValues, mergeEventPayloads, staticPayload, definePayloadFactory, validateEventPayload, describeEventPayload, } from "./eventPayload.type.js";
|
|
8
|
+
export { type EventTypeList, type EventTypePattern, type EventTypeOf, type EventUnion, isValidEventType, isValidEventTypePattern, normalizeEventType, normalizeEventTypePattern, tryNormalizeEventType, assertEventType, createEventType, createEventTypePattern, getEventNamespace, getEventAction, getEventTypeSegments, matchesEventType, isSameEventNamespace, isChildEventType, eventMatchesType, filterEventsByType, defineEventTypes, defineEventType, } from "./eventType.type.js";
|
|
9
9
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/eventTypes/index.js
CHANGED
|
@@ -4,6 +4,6 @@
|
|
|
4
4
|
* Event type definitions and payload types.
|
|
5
5
|
*/
|
|
6
6
|
export { isEvent, createEventId, createEvent, defineEvent, withEventMetadata, createDerivedEvent, getEventType, getEventPayload, describeEvent, } from "./eventDefinition.type.js";
|
|
7
|
-
export { isPrimitiveEventPayload, isObjectEventPayload, isJsonEventPayload, createEventPayload, validateEventPayload, } from "./eventPayload.type.js";
|
|
8
|
-
export { isValidEventType, isValidEventTypePattern, normalizeEventType, createEventType, getEventNamespace, } from "./eventType.type.js";
|
|
7
|
+
export { isPrimitiveEventPayload, isObjectEventPayload, isJsonEventPayload, createEventPayload, createObjectEventPayload, createJsonEventPayload, cloneEventPayload, deepFreeze, stripUndefinedValues, mergeEventPayloads, staticPayload, definePayloadFactory, validateEventPayload, describeEventPayload, } from "./eventPayload.type.js";
|
|
8
|
+
export { isValidEventType, isValidEventTypePattern, normalizeEventType, normalizeEventTypePattern, tryNormalizeEventType, assertEventType, createEventType, createEventTypePattern, getEventNamespace, getEventAction, getEventTypeSegments, matchesEventType, isSameEventNamespace, isChildEventType, eventMatchesType, filterEventsByType, defineEventTypes, defineEventType, } from "./eventType.type.js";
|
|
9
9
|
//# sourceMappingURL=index.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zudojs/events",
|
|
3
|
-
"version": "0.0
|
|
3
|
+
"version": "1.0.0",
|
|
4
4
|
"description": "Event-driven architecture with event bus, emitter, middleware, and registry for decoupled communication.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -13,18 +13,22 @@
|
|
|
13
13
|
}
|
|
14
14
|
},
|
|
15
15
|
"files": [
|
|
16
|
-
"dist"
|
|
16
|
+
"dist",
|
|
17
|
+
"!dist/**/*.map",
|
|
18
|
+
"!dist/**/*.tsbuildinfo",
|
|
19
|
+
"!dist/.tsbuildinfo"
|
|
17
20
|
],
|
|
21
|
+
"sideEffects": false,
|
|
18
22
|
"dependencies": {
|
|
19
|
-
"@zudojs/errors": "0.0
|
|
20
|
-
"@zudojs/constants": "0.0
|
|
23
|
+
"@zudojs/errors": "1.0.0",
|
|
24
|
+
"@zudojs/constants": "1.0.0"
|
|
21
25
|
},
|
|
22
26
|
"engines": {
|
|
23
27
|
"node": ">=24.0.0"
|
|
24
28
|
},
|
|
25
29
|
"devDependencies": {
|
|
26
30
|
"vitest": "^4.1.11",
|
|
27
|
-
"typescript": "
|
|
31
|
+
"typescript": "7.0.2"
|
|
28
32
|
},
|
|
29
33
|
"license": "MIT",
|
|
30
34
|
"publishConfig": {
|
|
@@ -37,13 +41,17 @@
|
|
|
37
41
|
"pubsub"
|
|
38
42
|
],
|
|
39
43
|
"homepage": "https://github.com/oyinlola-tech/zudo#readme",
|
|
44
|
+
"bugs": {
|
|
45
|
+
"url": "https://github.com/oyinlola-tech/zudo/issues"
|
|
46
|
+
},
|
|
40
47
|
"repository": {
|
|
41
48
|
"type": "git",
|
|
42
|
-
"url": "https://github.com/oyinlola-tech/zudo"
|
|
49
|
+
"url": "https://github.com/oyinlola-tech/zudo",
|
|
50
|
+
"directory": "packages/events"
|
|
43
51
|
},
|
|
44
52
|
"scripts": {
|
|
45
53
|
"build": "tsc -p tsconfig.json",
|
|
46
|
-
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
54
|
+
"typecheck": "tsc -p tsconfig.json --noEmit && tsc -p tsconfig.test.json --noEmit",
|
|
47
55
|
"test": "vitest run",
|
|
48
56
|
"test:watch": "vitest",
|
|
49
57
|
"clean": "rm -rf dist"
|