abxbus 2.4.31 → 2.5.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 +74 -51
- package/dist/cjs/BaseEvent.d.ts +45 -55
- package/dist/cjs/BaseEvent.js +350 -169
- package/dist/cjs/BaseEvent.js.map +3 -3
- package/dist/cjs/EventBus.d.ts +8 -1
- package/dist/cjs/EventBus.js +153 -85
- package/dist/cjs/EventBus.js.map +2 -2
- package/dist/cjs/EventHandler.d.ts +3 -3
- package/dist/cjs/EventHandler.js.map +1 -1
- package/dist/cjs/EventResult.js +16 -22
- package/dist/cjs/EventResult.js.map +2 -2
- package/dist/cjs/LockManager.d.ts +1 -0
- package/dist/cjs/LockManager.js +4 -1
- package/dist/cjs/LockManager.js.map +2 -2
- package/dist/cjs/base_event.d.ts +2 -2
- package/dist/cjs/bridge_ipc.d.ts +45 -0
- package/dist/cjs/event_handler.d.ts +1 -0
- package/dist/cjs/events_suck.js +1 -1
- package/dist/cjs/events_suck.js.map +2 -2
- package/dist/cjs/index.d.ts +1 -0
- package/dist/cjs/index.js.map +2 -2
- package/dist/cjs/middleware_otel_tracing.d.ts +49 -0
- package/dist/cjs/timing.js +1 -1
- package/dist/cjs/timing.js.map +2 -2
- package/dist/esm/BaseEvent.js +351 -170
- package/dist/esm/BaseEvent.js.map +3 -3
- package/dist/esm/EventBus.js +153 -85
- package/dist/esm/EventBus.js.map +2 -2
- package/dist/esm/EventHandler.js.map +1 -1
- package/dist/esm/EventResult.js +16 -22
- package/dist/esm/EventResult.js.map +2 -2
- package/dist/esm/LockManager.js +4 -1
- package/dist/esm/LockManager.js.map +2 -2
- package/dist/esm/events_suck.js +1 -1
- package/dist/esm/events_suck.js.map +2 -2
- package/dist/esm/index.js.map +2 -2
- package/dist/esm/timing.js +1 -1
- package/dist/esm/timing.js.map +2 -2
- package/dist/types/BaseEvent.d.ts +45 -55
- package/dist/types/EventBus.d.ts +8 -1
- package/dist/types/EventHandler.d.ts +3 -3
- package/dist/types/LockManager.d.ts +1 -0
- package/dist/types/base_event.d.ts +2 -2
- package/dist/types/bridge_ipc.d.ts +45 -0
- package/dist/types/event_handler.d.ts +1 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/middleware_otel_tracing.d.ts +49 -0
- package/package.json +4 -3
- package/src/BaseEvent.ts +452 -219
- package/src/EventBus.ts +186 -99
- package/src/EventHandler.ts +3 -3
- package/src/EventResult.ts +18 -22
- package/src/LockManager.ts +5 -1
- package/src/events_suck.ts +1 -1
- package/src/index.ts +1 -0
- package/src/timing.ts +1 -1
package/dist/esm/BaseEvent.js
CHANGED
|
@@ -10,9 +10,20 @@ import {
|
|
|
10
10
|
withResolvers
|
|
11
11
|
} from "./LockManager.js";
|
|
12
12
|
import { _runWithTimeout } from "./timing.js";
|
|
13
|
-
import {
|
|
13
|
+
import { isZodSchema, normalizeEventResultType, toJsonSchema } from "./types.js";
|
|
14
14
|
import { monotonicDatetime } from "./helpers.js";
|
|
15
|
-
const RESERVED_USER_EVENT_FIELDS = /* @__PURE__ */ new Set([
|
|
15
|
+
const RESERVED_USER_EVENT_FIELDS = /* @__PURE__ */ new Set([
|
|
16
|
+
"bus",
|
|
17
|
+
"emit",
|
|
18
|
+
"wait",
|
|
19
|
+
"now",
|
|
20
|
+
"eventResult",
|
|
21
|
+
"eventResultsList",
|
|
22
|
+
"toString",
|
|
23
|
+
"toJSON",
|
|
24
|
+
"fromJSON"
|
|
25
|
+
]);
|
|
26
|
+
const EVENT_TYPE_REGISTRY = /* @__PURE__ */ new Map();
|
|
16
27
|
function assertNoReservedUserEventFields(data, context) {
|
|
17
28
|
for (const field_name of RESERVED_USER_EVENT_FIELDS) {
|
|
18
29
|
if (Object.prototype.hasOwnProperty.call(data, field_name)) {
|
|
@@ -34,6 +45,12 @@ function assertNoModelPrefixedFields(data, context) {
|
|
|
34
45
|
}
|
|
35
46
|
}
|
|
36
47
|
}
|
|
48
|
+
function isRecord(value) {
|
|
49
|
+
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
50
|
+
}
|
|
51
|
+
function isZodObjectSchema(value) {
|
|
52
|
+
return isZodSchema(value) && typeof value.safeExtend === "function" && isRecord(value.shape);
|
|
53
|
+
}
|
|
37
54
|
function compareIsoDatetime(left, right) {
|
|
38
55
|
const left_value = left ?? "";
|
|
39
56
|
const right_value = right ?? "";
|
|
@@ -47,10 +64,10 @@ const BaseEventSchema = z.object({
|
|
|
47
64
|
event_created_at: z.string().datetime(),
|
|
48
65
|
event_type: z.string(),
|
|
49
66
|
event_version: z.string().default("0.0.1"),
|
|
50
|
-
event_timeout: z.number().
|
|
51
|
-
event_slow_timeout: z.number().
|
|
52
|
-
event_handler_timeout: z.number().
|
|
53
|
-
event_handler_slow_timeout: z.number().
|
|
67
|
+
event_timeout: z.number().nonnegative().nullable(),
|
|
68
|
+
event_slow_timeout: z.number().nonnegative().nullable().optional(),
|
|
69
|
+
event_handler_timeout: z.number().nonnegative().nullable().optional(),
|
|
70
|
+
event_handler_slow_timeout: z.number().nonnegative().nullable().optional(),
|
|
54
71
|
event_blocks_parent_completion: z.boolean().optional(),
|
|
55
72
|
event_parent_id: z.string().uuid().nullable().optional(),
|
|
56
73
|
event_path: z.array(z.string()).optional(),
|
|
@@ -66,8 +83,110 @@ const BaseEventSchema = z.object({
|
|
|
66
83
|
event_handler_completion: z.enum(EVENT_HANDLER_COMPLETION_MODES).nullable().optional()
|
|
67
84
|
}).loose();
|
|
68
85
|
const KNOWN_BASE_EVENT_FIELDS = new Set(Object.keys(BaseEventSchema.shape));
|
|
69
|
-
const EVENT_CLASS_DEFAULTS = /* @__PURE__ */ new WeakMap();
|
|
70
86
|
const ROOT_EVENTBUS_ID = "00000000-0000-0000-0000-000000000000";
|
|
87
|
+
function baseEventDefaultShape(event_type) {
|
|
88
|
+
return {
|
|
89
|
+
event_id: z.string().uuid(),
|
|
90
|
+
event_created_at: z.string().datetime(),
|
|
91
|
+
event_type: z.string().default(event_type),
|
|
92
|
+
event_version: z.string().default("0.0.1"),
|
|
93
|
+
event_timeout: z.number().nonnegative().nullable().default(null),
|
|
94
|
+
event_slow_timeout: z.number().nonnegative().nullable().optional(),
|
|
95
|
+
event_handler_timeout: z.number().nonnegative().nullable().optional(),
|
|
96
|
+
event_handler_slow_timeout: z.number().nonnegative().nullable().optional(),
|
|
97
|
+
event_blocks_parent_completion: z.boolean().default(false),
|
|
98
|
+
event_parent_id: z.string().uuid().nullable().optional(),
|
|
99
|
+
event_path: z.array(z.string()).optional(),
|
|
100
|
+
event_result_type: z.unknown().optional(),
|
|
101
|
+
event_emitted_by_handler_id: z.string().uuid().nullable().optional(),
|
|
102
|
+
event_pending_bus_count: z.number().nonnegative().optional(),
|
|
103
|
+
event_status: z.enum(["pending", "started", "completed"]).optional(),
|
|
104
|
+
event_started_at: z.string().datetime().nullable().optional(),
|
|
105
|
+
event_completed_at: z.string().datetime().nullable().optional(),
|
|
106
|
+
event_results: z.record(z.string(), z.unknown()).optional(),
|
|
107
|
+
event_concurrency: z.enum(EVENT_CONCURRENCY_MODES).nullable().optional(),
|
|
108
|
+
event_handler_concurrency: z.enum(EVENT_HANDLER_CONCURRENCY_MODES).nullable().optional(),
|
|
109
|
+
event_handler_completion: z.enum(EVENT_HANDLER_COMPLETION_MODES).nullable().optional()
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
function missingBaseFields(event_type, user_shape) {
|
|
113
|
+
return Object.fromEntries(Object.entries(baseEventDefaultShape(event_type)).filter(([key]) => !(key in user_shape)));
|
|
114
|
+
}
|
|
115
|
+
function shortcutDefaultSchema(base_field_schema, value) {
|
|
116
|
+
if (!base_field_schema) {
|
|
117
|
+
return z.unknown().optional().default(value);
|
|
118
|
+
}
|
|
119
|
+
return base_field_schema.prefault(base_field_schema.parse(value));
|
|
120
|
+
}
|
|
121
|
+
function schemaDefaultsForShortcut(event_type, raw_shape) {
|
|
122
|
+
const defaults = {};
|
|
123
|
+
const base_shape = baseEventDefaultShape(event_type);
|
|
124
|
+
for (const [key, value] of Object.entries(raw_shape)) {
|
|
125
|
+
if (key === "event_result_type") continue;
|
|
126
|
+
if (!isZodSchema(value)) {
|
|
127
|
+
defaults[key] = shortcutDefaultSchema(base_shape[key], value);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
return defaults;
|
|
131
|
+
}
|
|
132
|
+
function zodFieldsForShortcut(raw_shape) {
|
|
133
|
+
const fields = {};
|
|
134
|
+
for (const [key, value] of Object.entries(raw_shape)) {
|
|
135
|
+
if (key === "event_result_type") continue;
|
|
136
|
+
if (isZodSchema(value)) {
|
|
137
|
+
fields[key] = value;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
return fields;
|
|
141
|
+
}
|
|
142
|
+
function eventResultTypeFromObjectSchema(schema) {
|
|
143
|
+
const raw_event_result_type = schema.shape.event_result_type;
|
|
144
|
+
return raw_event_result_type === void 0 ? void 0 : normalizeEventResultType(raw_event_result_type);
|
|
145
|
+
}
|
|
146
|
+
function buildFullEventSchema(event_type, spec) {
|
|
147
|
+
if (isZodObjectSchema(spec)) {
|
|
148
|
+
const user_shape = spec.shape;
|
|
149
|
+
assertNoReservedUserEventFields(user_shape, `BaseEvent.extend(${event_type})`);
|
|
150
|
+
assertNoUnknownEventPrefixedFields(user_shape, `BaseEvent.extend(${event_type})`);
|
|
151
|
+
assertNoModelPrefixedFields(user_shape, `BaseEvent.extend(${event_type})`);
|
|
152
|
+
const full_schema2 = spec.safeExtend({
|
|
153
|
+
event_result_type: z.unknown().optional(),
|
|
154
|
+
...missingBaseFields(event_type, user_shape)
|
|
155
|
+
});
|
|
156
|
+
return {
|
|
157
|
+
event_schema: full_schema2,
|
|
158
|
+
event_result_type: eventResultTypeFromObjectSchema(spec)
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
const raw_shape = isRecord(spec) ? spec : {};
|
|
162
|
+
assertNoReservedUserEventFields(raw_shape, `BaseEvent.extend(${event_type})`);
|
|
163
|
+
assertNoUnknownEventPrefixedFields(raw_shape, `BaseEvent.extend(${event_type})`);
|
|
164
|
+
assertNoModelPrefixedFields(raw_shape, `BaseEvent.extend(${event_type})`);
|
|
165
|
+
const shortcut_shape = {
|
|
166
|
+
...schemaDefaultsForShortcut(event_type, raw_shape),
|
|
167
|
+
...zodFieldsForShortcut(raw_shape)
|
|
168
|
+
};
|
|
169
|
+
const full_schema = z.object(shortcut_shape).safeExtend(missingBaseFields(event_type, shortcut_shape)).loose();
|
|
170
|
+
return {
|
|
171
|
+
event_schema: full_schema,
|
|
172
|
+
event_result_type: normalizeEventResultType(raw_shape.event_result_type),
|
|
173
|
+
event_version: typeof raw_shape.event_version === "string" ? raw_shape.event_version : void 0
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
function decodeEventSchema(schema, input) {
|
|
177
|
+
const decoded = z.decode(schema, input);
|
|
178
|
+
if (!isRecord(decoded)) {
|
|
179
|
+
throw new Error("BaseEvent schema must decode to an object");
|
|
180
|
+
}
|
|
181
|
+
return decoded;
|
|
182
|
+
}
|
|
183
|
+
function encodeEventSchema(schema, input) {
|
|
184
|
+
const encoded = z.encode(schema, input);
|
|
185
|
+
if (!isRecord(encoded)) {
|
|
186
|
+
throw new Error("BaseEvent schema must encode to an object");
|
|
187
|
+
}
|
|
188
|
+
return encoded;
|
|
189
|
+
}
|
|
71
190
|
class BaseEvent {
|
|
72
191
|
// event metadata fields
|
|
73
192
|
event_id;
|
|
@@ -86,7 +205,7 @@ class BaseEvent {
|
|
|
86
205
|
event_handler_slow_timeout;
|
|
87
206
|
// optional per-event slow handler warning threshold in seconds
|
|
88
207
|
event_blocks_parent_completion;
|
|
89
|
-
// true only for children explicitly awaited via
|
|
208
|
+
// true only for children explicitly awaited via now()
|
|
90
209
|
event_parent_id;
|
|
91
210
|
// id of the parent event that triggered this event, if this event was emitted during handling of another event, else null
|
|
92
211
|
event_path;
|
|
@@ -109,11 +228,13 @@ class BaseEvent {
|
|
|
109
228
|
// concurrency mode for the handlers within the event
|
|
110
229
|
event_handler_completion;
|
|
111
230
|
// completion strategy: 'all' (default) waits for every handler, 'first' returns earliest non-undefined result and cancels the rest
|
|
231
|
+
event_schema;
|
|
112
232
|
static event_type;
|
|
113
233
|
// class name of the event, e.g. BaseEvent.extend("MyEvent").event_type === "MyEvent"
|
|
114
234
|
static event_version = "0.0.1";
|
|
115
|
-
static
|
|
116
|
-
|
|
235
|
+
static event_result_type;
|
|
236
|
+
static event_schema = BaseEventSchema;
|
|
237
|
+
// generated Zod schema for local TS event data validation; never sent over the wire
|
|
117
238
|
// internal runtime state
|
|
118
239
|
event_bus;
|
|
119
240
|
// bus that dispatched this event, also used by event.emit(child)
|
|
@@ -121,6 +242,7 @@ class BaseEvent {
|
|
|
121
242
|
// underlying event object that was dispatched, if this is a bus-scoped proxy wrapping it
|
|
122
243
|
_event_dispatch_context;
|
|
123
244
|
// captured AsyncLocalStorage context at dispatch site, used to restore that context when running handlers
|
|
245
|
+
_event_fields_set;
|
|
124
246
|
_event_completed_signal;
|
|
125
247
|
_lock_for_event_handler;
|
|
126
248
|
constructor(data = {}) {
|
|
@@ -128,34 +250,42 @@ class BaseEvent {
|
|
|
128
250
|
assertNoUnknownEventPrefixedFields(data, "BaseEvent");
|
|
129
251
|
assertNoModelPrefixedFields(data, "BaseEvent");
|
|
130
252
|
const ctor = this.constructor;
|
|
131
|
-
const
|
|
132
|
-
const merged_data = {
|
|
133
|
-
...ctor_defaults,
|
|
134
|
-
...data
|
|
135
|
-
};
|
|
253
|
+
const explicit_event_fields = new Set(Object.keys(data ?? {}));
|
|
254
|
+
const merged_data = { ...data };
|
|
136
255
|
const event_type = merged_data.event_type ?? ctor.event_type ?? ctor.name;
|
|
137
256
|
const event_version = merged_data.event_version ?? ctor.event_version ?? "0.0.1";
|
|
138
257
|
const raw_event_result_type = merged_data.event_result_type ?? ctor.event_result_type;
|
|
139
258
|
const event_result_type = normalizeEventResultType(raw_event_result_type);
|
|
140
|
-
const
|
|
141
|
-
const event_created_at = monotonicDatetime(merged_data.event_created_at);
|
|
142
|
-
const event_timeout = merged_data.event_timeout ?? null;
|
|
143
|
-
const event_blocks_parent_completion = merged_data.event_blocks_parent_completion ?? false;
|
|
259
|
+
const event_schema = ctor.event_schema ?? BaseEventSchema;
|
|
144
260
|
const base_data = {
|
|
145
261
|
...merged_data,
|
|
146
|
-
event_id,
|
|
147
|
-
event_created_at,
|
|
262
|
+
event_id: merged_data.event_id ?? uuidv7(),
|
|
263
|
+
event_created_at: merged_data.event_created_at ?? monotonicDatetime(),
|
|
148
264
|
event_type,
|
|
149
265
|
event_version,
|
|
150
|
-
event_timeout,
|
|
151
|
-
event_blocks_parent_completion,
|
|
152
266
|
event_result_type
|
|
153
267
|
};
|
|
154
|
-
|
|
155
|
-
|
|
268
|
+
if (event_schema === BaseEventSchema) {
|
|
269
|
+
base_data.event_timeout ??= null;
|
|
270
|
+
base_data.event_blocks_parent_completion ??= false;
|
|
271
|
+
}
|
|
272
|
+
const parsed = decodeEventSchema(event_schema, base_data);
|
|
156
273
|
Object.assign(this, parsed);
|
|
274
|
+
Object.defineProperty(this, "event_schema", {
|
|
275
|
+
value: event_schema,
|
|
276
|
+
writable: true,
|
|
277
|
+
enumerable: false,
|
|
278
|
+
configurable: true
|
|
279
|
+
});
|
|
280
|
+
Object.defineProperty(this, "_event_fields_set", {
|
|
281
|
+
value: explicit_event_fields,
|
|
282
|
+
writable: true,
|
|
283
|
+
enumerable: false,
|
|
284
|
+
configurable: true
|
|
285
|
+
});
|
|
157
286
|
const parsed_path = parsed.event_path;
|
|
158
287
|
this.event_path = Array.isArray(parsed_path) ? [...parsed_path] : [];
|
|
288
|
+
this.event_created_at = monotonicDatetime(parsed.event_created_at);
|
|
159
289
|
this.event_results = hydrateEventResults(this, parsed.event_results);
|
|
160
290
|
this.event_pending_bus_count = typeof parsed.event_pending_bus_count === "number" ? Math.max(0, Number(parsed.event_pending_bus_count)) : 0;
|
|
161
291
|
const parsed_status = parsed.event_status;
|
|
@@ -164,7 +294,7 @@ class BaseEvent {
|
|
|
164
294
|
this.event_completed_at = parsed.event_completed_at === null || parsed.event_completed_at === void 0 ? null : monotonicDatetime(parsed.event_completed_at);
|
|
165
295
|
this.event_parent_id = typeof parsed.event_parent_id === "string" ? parsed.event_parent_id : null;
|
|
166
296
|
this.event_emitted_by_handler_id = typeof parsed.event_emitted_by_handler_id === "string" ? parsed.event_emitted_by_handler_id : null;
|
|
167
|
-
this.event_result_type = event_result_type;
|
|
297
|
+
this.event_result_type = normalizeEventResultType(parsed.event_result_type ?? event_result_type);
|
|
168
298
|
this._event_completed_signal = null;
|
|
169
299
|
this._lock_for_event_handler = null;
|
|
170
300
|
this._event_dispatch_context = void 0;
|
|
@@ -173,23 +303,13 @@ class BaseEvent {
|
|
|
173
303
|
toString() {
|
|
174
304
|
return `${this.event_type}#${this.event_id.slice(-4)}`;
|
|
175
305
|
}
|
|
176
|
-
static extend(event_type, shape
|
|
177
|
-
const
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
const raw_event_result_type = raw_shape.event_result_type;
|
|
182
|
-
const event_result_type = normalizeEventResultType(raw_event_result_type);
|
|
183
|
-
const event_version = typeof raw_shape.event_version === "string" ? raw_shape.event_version : void 0;
|
|
184
|
-
const event_defaults = Object.fromEntries(
|
|
185
|
-
Object.entries(raw_shape).filter(
|
|
186
|
-
([key, value]) => key !== "event_result_type" && key !== "event_version" && !(value instanceof z.ZodType)
|
|
187
|
-
)
|
|
188
|
-
);
|
|
189
|
-
const zod_shape = extractZodShape(raw_shape);
|
|
190
|
-
const full_schema = BaseEventSchema.extend(zod_shape);
|
|
306
|
+
static extend(event_type, shape) {
|
|
307
|
+
const built = buildFullEventSchema(event_type, shape ?? {});
|
|
308
|
+
const full_schema = built.event_schema;
|
|
309
|
+
const event_result_type = built.event_result_type;
|
|
310
|
+
const event_version = built.event_version;
|
|
191
311
|
class ExtendedEvent extends BaseEvent {
|
|
192
|
-
static
|
|
312
|
+
static event_schema = full_schema;
|
|
193
313
|
static event_type = event_type;
|
|
194
314
|
static event_version = event_version ?? BaseEvent.event_version;
|
|
195
315
|
static event_result_type = event_result_type;
|
|
@@ -200,23 +320,36 @@ class BaseEvent {
|
|
|
200
320
|
function EventFactory(data) {
|
|
201
321
|
return new ExtendedEvent(data);
|
|
202
322
|
}
|
|
203
|
-
EventFactory.
|
|
323
|
+
EventFactory.event_schema = full_schema;
|
|
204
324
|
EventFactory.event_type = event_type;
|
|
205
325
|
EventFactory.event_version = event_version ?? BaseEvent.event_version;
|
|
206
326
|
EventFactory.event_result_type = event_result_type;
|
|
207
327
|
EventFactory.class = ExtendedEvent;
|
|
208
328
|
EventFactory.fromJSON = (data) => ExtendedEvent.fromJSON(data);
|
|
209
329
|
EventFactory.prototype = ExtendedEvent.prototype;
|
|
210
|
-
|
|
330
|
+
EVENT_TYPE_REGISTRY.set(event_type, ExtendedEvent);
|
|
211
331
|
return EventFactory;
|
|
212
332
|
}
|
|
213
333
|
static fromJSON(data) {
|
|
214
334
|
if (!data || typeof data !== "object") {
|
|
215
|
-
const
|
|
216
|
-
const parsed =
|
|
335
|
+
const event_schema = this.event_schema ?? BaseEventSchema;
|
|
336
|
+
const parsed = decodeEventSchema(event_schema, data);
|
|
217
337
|
return new this(parsed);
|
|
218
338
|
}
|
|
219
339
|
const record = { ...data };
|
|
340
|
+
if (this === BaseEvent) {
|
|
341
|
+
const event_type = record.event_type;
|
|
342
|
+
if (typeof event_type === "string") {
|
|
343
|
+
const KnownEvent = EVENT_TYPE_REGISTRY.get(event_type);
|
|
344
|
+
if (KnownEvent) {
|
|
345
|
+
return KnownEvent.fromJSON(record);
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
const ctor = this;
|
|
350
|
+
if (this !== BaseEvent && ctor.event_result_type && record.event_result_type !== void 0) {
|
|
351
|
+
delete record.event_result_type;
|
|
352
|
+
}
|
|
220
353
|
if (record.event_result_type !== void 0 && record.event_result_type !== null) {
|
|
221
354
|
record.event_result_type = normalizeEventResultType(record.event_result_type);
|
|
222
355
|
}
|
|
@@ -237,18 +370,47 @@ class BaseEvent {
|
|
|
237
370
|
toJSON() {
|
|
238
371
|
const record = {};
|
|
239
372
|
for (const [key, value] of Object.entries(this)) {
|
|
240
|
-
if (key.startsWith("_") || key === "bus" || key === "event_bus" || key === "event_results") continue;
|
|
373
|
+
if (key.startsWith("_") || key === "bus" || key === "event_bus" || key === "event_schema" || key === "event_results") continue;
|
|
241
374
|
if (value === void 0 || typeof value === "function") continue;
|
|
242
375
|
record[key] = value;
|
|
243
376
|
}
|
|
244
377
|
const event_results = Object.fromEntries(
|
|
245
378
|
Array.from(this.event_results.entries()).map(([handler_id, result]) => [handler_id, result.toJSON()])
|
|
246
379
|
);
|
|
247
|
-
|
|
380
|
+
const event_schema = this.constructor.event_schema ?? this.event_schema ?? BaseEventSchema;
|
|
381
|
+
const encoded = encodeEventSchema(event_schema, {
|
|
248
382
|
...record,
|
|
249
383
|
event_id: this.event_id,
|
|
250
384
|
event_type: this.event_type,
|
|
251
385
|
event_version: this.event_version,
|
|
386
|
+
event_result_type: this.event_result_type,
|
|
387
|
+
// static configuration options
|
|
388
|
+
event_timeout: this.event_timeout,
|
|
389
|
+
event_slow_timeout: this.event_slow_timeout,
|
|
390
|
+
event_concurrency: this.event_concurrency,
|
|
391
|
+
event_handler_concurrency: this.event_handler_concurrency,
|
|
392
|
+
event_handler_completion: this.event_handler_completion,
|
|
393
|
+
event_handler_slow_timeout: this.event_handler_slow_timeout,
|
|
394
|
+
event_handler_timeout: this.event_handler_timeout,
|
|
395
|
+
event_blocks_parent_completion: this.event_blocks_parent_completion,
|
|
396
|
+
// mutable parent/child/bus tracking runtime state
|
|
397
|
+
event_parent_id: this.event_parent_id,
|
|
398
|
+
event_path: this.event_path,
|
|
399
|
+
event_emitted_by_handler_id: this.event_emitted_by_handler_id,
|
|
400
|
+
event_pending_bus_count: this.event_pending_bus_count,
|
|
401
|
+
// mutable runtime status and timestamps
|
|
402
|
+
event_status: this.event_status,
|
|
403
|
+
event_created_at: this.event_created_at,
|
|
404
|
+
event_started_at: this.event_started_at ?? null,
|
|
405
|
+
event_completed_at: this.event_completed_at ?? null,
|
|
406
|
+
...Object.keys(event_results).length > 0 ? { event_results } : {}
|
|
407
|
+
});
|
|
408
|
+
delete encoded.event_schema;
|
|
409
|
+
return {
|
|
410
|
+
...encoded,
|
|
411
|
+
event_id: this.event_id,
|
|
412
|
+
event_type: this.event_type,
|
|
413
|
+
event_version: this.event_version,
|
|
252
414
|
event_result_type: this.event_result_type ? toJsonSchema(this.event_result_type) : this.event_result_type,
|
|
253
415
|
// static configuration options
|
|
254
416
|
event_timeout: this.event_timeout,
|
|
@@ -273,13 +435,12 @@ class BaseEvent {
|
|
|
273
435
|
...Object.keys(event_results).length > 0 ? { event_results } : {}
|
|
274
436
|
};
|
|
275
437
|
}
|
|
276
|
-
_createSlowEventWarningTimer() {
|
|
277
|
-
const
|
|
278
|
-
const event_warn_ms = event_slow_timeout === null ? null : event_slow_timeout * 1e3;
|
|
438
|
+
_createSlowEventWarningTimer(event_slow_timeout = this.event_slow_timeout ?? null, bus_name) {
|
|
439
|
+
const event_warn_ms = event_slow_timeout === null || event_slow_timeout <= 0 ? null : event_slow_timeout * 1e3;
|
|
279
440
|
if (event_warn_ms === null) {
|
|
280
441
|
return null;
|
|
281
442
|
}
|
|
282
|
-
const name = this.event_bus?.name ?? "EventBus";
|
|
443
|
+
const name = bus_name ?? this.event_bus?.name ?? "EventBus";
|
|
283
444
|
return setTimeout(() => {
|
|
284
445
|
if (this.event_status === "completed") {
|
|
285
446
|
return;
|
|
@@ -365,7 +526,13 @@ class BaseEvent {
|
|
|
365
526
|
return Array.from(original.event_results.values()).filter((result) => result.eventbus_id === this.event_bus.id);
|
|
366
527
|
}
|
|
367
528
|
_isFirstModeWinningResult(entry) {
|
|
368
|
-
return
|
|
529
|
+
return BaseEvent._defaultResultInclude(entry.result, entry);
|
|
530
|
+
}
|
|
531
|
+
static _defaultResultInclude(result, event_result) {
|
|
532
|
+
return event_result.status === "completed" && result !== void 0 && result !== null && !(result instanceof Error) && !(result instanceof BaseEvent) && event_result.error === void 0;
|
|
533
|
+
}
|
|
534
|
+
static _includeEventResult(include, event_result) {
|
|
535
|
+
return include(event_result.result, event_result);
|
|
369
536
|
}
|
|
370
537
|
_markFirstModeWinnerIfNeeded(original, entry, first_state) {
|
|
371
538
|
if (first_state.found || !this._isFirstModeWinningResult(entry)) {
|
|
@@ -378,9 +545,13 @@ class BaseEvent {
|
|
|
378
545
|
if (!this.event_bus) {
|
|
379
546
|
throw new Error("event has no bus attached");
|
|
380
547
|
}
|
|
381
|
-
await this.event_bus.locks._runWithHandlerLock(
|
|
382
|
-
|
|
383
|
-
|
|
548
|
+
await this.event_bus.locks._runWithHandlerLock(
|
|
549
|
+
original,
|
|
550
|
+
original.event_handler_concurrency ?? this.event_bus.event_handler_concurrency,
|
|
551
|
+
async (handler_lock) => {
|
|
552
|
+
await entry.runHandler(handler_lock);
|
|
553
|
+
}
|
|
554
|
+
);
|
|
384
555
|
}
|
|
385
556
|
// Run all pending handler results for the current bus context.
|
|
386
557
|
async _runHandlers(pending_entries) {
|
|
@@ -391,7 +562,7 @@ class BaseEvent {
|
|
|
391
562
|
}
|
|
392
563
|
const resolved_completion = original.event_handler_completion ?? this.event_bus?.event_handler_completion ?? "all";
|
|
393
564
|
if (resolved_completion === "first") {
|
|
394
|
-
if (original._getHandlerLock(this.event_bus?.event_handler_concurrency) !== null) {
|
|
565
|
+
if (original._getHandlerLock(original.event_handler_concurrency ?? this.event_bus?.event_handler_concurrency ?? "serial") !== null) {
|
|
395
566
|
for (const entry of pending_results) {
|
|
396
567
|
await this._runHandlerWithLock(original, entry);
|
|
397
568
|
if (!this._isFirstModeWinningResult(entry)) {
|
|
@@ -418,7 +589,7 @@ class BaseEvent {
|
|
|
418
589
|
}
|
|
419
590
|
_getHandlerLock(default_concurrency) {
|
|
420
591
|
const original = this._event_original ?? this;
|
|
421
|
-
const resolved = original.event_handler_concurrency ?? default_concurrency ??
|
|
592
|
+
const resolved = original.event_handler_concurrency ?? default_concurrency ?? "serial";
|
|
422
593
|
if (resolved === "parallel") {
|
|
423
594
|
return null;
|
|
424
595
|
}
|
|
@@ -530,18 +701,18 @@ class BaseEvent {
|
|
|
530
701
|
cancelChildEvent(child);
|
|
531
702
|
}
|
|
532
703
|
}
|
|
533
|
-
// Cancel all handler results for an event except the winner, used by first
|
|
704
|
+
// Cancel all handler results for an event except the winner, used by event_handler_completion='first'.
|
|
534
705
|
// Cancels pending handlers immediately, aborts started handlers via _signalAbort(),
|
|
535
706
|
// and cancels any child events emitted by the losing handlers.
|
|
536
707
|
_markRemainingFirstModeResultCancelled(winner) {
|
|
537
|
-
const cause = new Error("first
|
|
708
|
+
const cause = new Error("event_handler_completion='first' resolved: another handler returned a result first");
|
|
538
709
|
const bus_id = winner.eventbus_id;
|
|
539
710
|
for (const result of this.event_results.values()) {
|
|
540
711
|
if (result === winner) continue;
|
|
541
712
|
if (result.eventbus_id !== bus_id) continue;
|
|
542
713
|
if (result.status === "pending") {
|
|
543
714
|
result._markError(
|
|
544
|
-
new EventHandlerCancelledError(`Cancelled: first
|
|
715
|
+
new EventHandlerCancelledError(`Cancelled: event_handler_completion='first' resolved`, {
|
|
545
716
|
event_result: result,
|
|
546
717
|
cause
|
|
547
718
|
})
|
|
@@ -556,7 +727,7 @@ class BaseEvent {
|
|
|
556
727
|
original_child._markCancelled(cause);
|
|
557
728
|
}
|
|
558
729
|
result._lock?.exitHandlerRun();
|
|
559
|
-
const aborted_error = new EventHandlerAbortedError(`Aborted: first
|
|
730
|
+
const aborted_error = new EventHandlerAbortedError(`Aborted: event_handler_completion='first' resolved`, {
|
|
560
731
|
event_result: result,
|
|
561
732
|
cause
|
|
562
733
|
});
|
|
@@ -633,92 +804,41 @@ class BaseEvent {
|
|
|
633
804
|
parent_id = parent.event_parent_id;
|
|
634
805
|
}
|
|
635
806
|
}
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
return
|
|
641
|
-
}
|
|
807
|
+
_withEventResultMethods(promise) {
|
|
808
|
+
const chainable = promise;
|
|
809
|
+
chainable.eventResult = async (options) => {
|
|
810
|
+
const event = await promise;
|
|
811
|
+
return event.eventResult(options);
|
|
812
|
+
};
|
|
813
|
+
chainable.eventResultsList = async (options) => {
|
|
814
|
+
const event = await promise;
|
|
815
|
+
return event.eventResultsList(options);
|
|
816
|
+
};
|
|
817
|
+
return chainable;
|
|
818
|
+
}
|
|
819
|
+
_timeoutPromise(timeout, message, fn) {
|
|
820
|
+
return timeout === null || timeout <= 0 ? fn() : _runWithTimeout(timeout, () => new Error(message()), fn);
|
|
821
|
+
}
|
|
822
|
+
_orderedEventResults() {
|
|
642
823
|
const original = this._event_original ?? this;
|
|
643
|
-
original.
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
if (!raise_if_any) {
|
|
647
|
-
return completion_promise;
|
|
648
|
-
}
|
|
649
|
-
return completion_promise.then((completed_event) => {
|
|
650
|
-
const first_error = completed_event._firstProcessingError();
|
|
651
|
-
if (first_error !== void 0) {
|
|
652
|
-
if (first_error instanceof Error) {
|
|
653
|
-
throw first_error;
|
|
654
|
-
}
|
|
655
|
-
throw new Error(String(first_error));
|
|
656
|
-
}
|
|
657
|
-
return completed_event;
|
|
658
|
-
});
|
|
824
|
+
return Array.from(original.event_results.values()).sort(
|
|
825
|
+
(a, b) => compareIsoDatetime(a.completed_at, b.completed_at)
|
|
826
|
+
);
|
|
659
827
|
}
|
|
660
|
-
|
|
661
|
-
// when any handler completes. Works with all event_handler_concurrency modes:
|
|
662
|
-
// parallel: races all handlers, returns first non-undefined, aborts the rest
|
|
663
|
-
// serial: runs handlers sequentially, returns first non-undefined, skips remaining
|
|
664
|
-
first() {
|
|
665
|
-
if (!this.event_bus) {
|
|
666
|
-
return Promise.reject(new Error("event has no bus attached"));
|
|
667
|
-
}
|
|
828
|
+
_orderedEventResultsByRegistration() {
|
|
668
829
|
const original = this._event_original ?? this;
|
|
669
|
-
original.
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
if (first_error !== void 0) {
|
|
673
|
-
if (first_error instanceof Error) {
|
|
674
|
-
throw first_error;
|
|
675
|
-
}
|
|
676
|
-
throw new Error(String(first_error));
|
|
677
|
-
}
|
|
678
|
-
const orig = completed_event._event_original ?? completed_event;
|
|
679
|
-
return Array.from(orig.event_results.values()).filter(
|
|
680
|
-
(result) => result.status === "completed" && result.result !== void 0 && result.result !== null && !(result.result instanceof BaseEvent)
|
|
681
|
-
).sort((a, b) => compareIsoDatetime(a.completed_at, b.completed_at)).map((result) => result.result).at(0);
|
|
682
|
-
});
|
|
830
|
+
return Array.from(original.event_results.values()).sort(
|
|
831
|
+
(a, b) => compareIsoDatetime(a.handler.handler_registered_at, b.handler.handler_registered_at) || compareIsoDatetime(a.started_at, b.started_at) || a.handler_id.localeCompare(b.handler_id)
|
|
832
|
+
);
|
|
683
833
|
}
|
|
684
|
-
|
|
685
|
-
const
|
|
686
|
-
let options;
|
|
687
|
-
let include;
|
|
688
|
-
if (typeof include_or_options === "function") {
|
|
689
|
-
options = maybe_options ?? {};
|
|
690
|
-
include = include_or_options;
|
|
691
|
-
} else {
|
|
692
|
-
options = include_or_options ?? {};
|
|
693
|
-
include = options.include ?? default_include;
|
|
694
|
-
}
|
|
834
|
+
_collectResultValues(options = {}, order = "completion") {
|
|
835
|
+
const include = options.include ?? BaseEvent._defaultResultInclude;
|
|
695
836
|
const raise_if_any = options.raise_if_any ?? true;
|
|
696
|
-
const raise_if_none = options.raise_if_none ??
|
|
697
|
-
const
|
|
698
|
-
const resolved_timeout_seconds = options.timeout ?? original.event_timeout ?? this.event_bus?.event_timeout ?? null;
|
|
699
|
-
let completed_event;
|
|
700
|
-
if (resolved_timeout_seconds === null) {
|
|
701
|
-
completed_event = await this.done({ raise_if_any: false });
|
|
702
|
-
} else {
|
|
703
|
-
completed_event = await _runWithTimeout(
|
|
704
|
-
resolved_timeout_seconds,
|
|
705
|
-
() => new Error(`Timed out waiting for ${original.event_type} results after ${resolved_timeout_seconds}s`),
|
|
706
|
-
() => this.done({ raise_if_any: false })
|
|
707
|
-
);
|
|
708
|
-
}
|
|
709
|
-
const all_results = Array.from(completed_event.event_results.values());
|
|
837
|
+
const raise_if_none = options.raise_if_none ?? false;
|
|
838
|
+
const all_results = order === "registration" ? this._orderedEventResultsByRegistration() : this._orderedEventResults();
|
|
710
839
|
const error_results = all_results.filter((event_result) => event_result.error !== void 0 || event_result.result instanceof Error);
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
const first_error = error_results[0];
|
|
714
|
-
if (first_error.error instanceof Error) {
|
|
715
|
-
throw first_error.error;
|
|
716
|
-
}
|
|
717
|
-
if (first_error.result instanceof Error) {
|
|
718
|
-
throw first_error.result;
|
|
719
|
-
}
|
|
720
|
-
throw new Error(String(first_error.error ?? first_error.result));
|
|
721
|
-
}
|
|
840
|
+
const included_results = all_results.filter((event_result) => BaseEvent._includeEventResult(include, event_result));
|
|
841
|
+
if (error_results.length > 0 && raise_if_any) {
|
|
722
842
|
const errors = error_results.map((event_result) => {
|
|
723
843
|
if (event_result.error instanceof Error) {
|
|
724
844
|
return event_result.error;
|
|
@@ -728,28 +848,104 @@ class BaseEvent {
|
|
|
728
848
|
}
|
|
729
849
|
return new Error(String(event_result.error ?? event_result.result));
|
|
730
850
|
});
|
|
731
|
-
|
|
732
|
-
errors
|
|
733
|
-
|
|
734
|
-
);
|
|
851
|
+
if (errors.length === 1) {
|
|
852
|
+
throw errors[0];
|
|
853
|
+
}
|
|
854
|
+
throw new AggregateError(errors, `Event ${this.event_type}#${this.event_id.slice(-4)} had ${errors.length} handler error(s)`);
|
|
735
855
|
}
|
|
736
|
-
const included_results = all_results.filter((event_result) => include(event_result.result, event_result));
|
|
737
856
|
if (raise_if_none && included_results.length === 0) {
|
|
738
857
|
throw new Error(
|
|
739
|
-
`Expected at least one handler to return a non-null result, but none did: ${
|
|
858
|
+
`Expected at least one handler to return a non-null result, but none did: ${this.event_type}#${this.event_id.slice(-4)}`
|
|
740
859
|
);
|
|
741
860
|
}
|
|
742
861
|
return included_results.map((event_result) => event_result.result);
|
|
743
862
|
}
|
|
744
|
-
|
|
745
|
-
|
|
863
|
+
_hasIncludedResult(options = {}) {
|
|
864
|
+
const include = options.include ?? BaseEvent._defaultResultInclude;
|
|
865
|
+
return this._orderedEventResults().some((event_result) => BaseEvent._includeEventResult(include, event_result));
|
|
866
|
+
}
|
|
867
|
+
async _waitForFirstResultOrCompletion(options = {}) {
|
|
746
868
|
const original = this._event_original ?? this;
|
|
869
|
+
if (options.timeout !== void 0 && options.timeout !== null && options.timeout < 0) {
|
|
870
|
+
throw new Error("timeout must be >= 0 or null");
|
|
871
|
+
}
|
|
872
|
+
if (!this.event_bus && original.event_status !== "completed") {
|
|
873
|
+
throw new Error("event has no bus attached");
|
|
874
|
+
}
|
|
875
|
+
if (original.event_status === "completed" || this._hasIncludedResult(options)) {
|
|
876
|
+
return this;
|
|
877
|
+
}
|
|
878
|
+
const waitForResult = async () => {
|
|
879
|
+
for (; ; ) {
|
|
880
|
+
if (original.event_status === "completed" || this._hasIncludedResult(options)) {
|
|
881
|
+
return this;
|
|
882
|
+
}
|
|
883
|
+
await new Promise((resolve) => setTimeout(resolve, 1));
|
|
884
|
+
}
|
|
885
|
+
};
|
|
886
|
+
const timeout = options.timeout ?? null;
|
|
887
|
+
return this._timeoutPromise(timeout, () => `Timed out waiting for ${original.event_type} result after ${timeout}s`, waitForResult);
|
|
888
|
+
}
|
|
889
|
+
// Active awaitable that triggers immediate (queue-jump) processing of the event on all buses where it is queued.
|
|
890
|
+
now(options = {}) {
|
|
891
|
+
const original = this._event_original ?? this;
|
|
892
|
+
if (options.timeout !== void 0 && options.timeout !== null && options.timeout < 0) {
|
|
893
|
+
return this._withEventResultMethods(Promise.reject(new Error("timeout must be >= 0 or null")));
|
|
894
|
+
}
|
|
895
|
+
if (!this.event_bus && original.event_status !== "completed") {
|
|
896
|
+
return this._withEventResultMethods(Promise.reject(new Error("event has no bus attached")));
|
|
897
|
+
}
|
|
747
898
|
original._markBlocksParentCompletionIfAwaitedFromEmittingHandler();
|
|
748
|
-
|
|
749
|
-
|
|
899
|
+
const resolved_timeout_seconds = options.timeout ?? null;
|
|
900
|
+
const processing = original.event_status === "completed" ? Promise.resolve(this) : this._timeoutPromise(
|
|
901
|
+
resolved_timeout_seconds,
|
|
902
|
+
() => `Timed out waiting for ${original.event_type} completion after ${resolved_timeout_seconds}s`,
|
|
903
|
+
() => this.event_bus._processEventImmediately(this)
|
|
904
|
+
);
|
|
905
|
+
if (options.first_result) {
|
|
906
|
+
void processing.catch(() => void 0);
|
|
907
|
+
return this._withEventResultMethods(this._waitForFirstResultOrCompletion(options));
|
|
908
|
+
}
|
|
909
|
+
return this._withEventResultMethods(processing);
|
|
910
|
+
}
|
|
911
|
+
// Passive awaitable that waits for normal queue-order processing without forcing execution.
|
|
912
|
+
wait(options = {}) {
|
|
913
|
+
const original = this._event_original ?? this;
|
|
914
|
+
if (options.timeout !== void 0 && options.timeout !== null && options.timeout < 0) {
|
|
915
|
+
return this._withEventResultMethods(Promise.reject(new Error("timeout must be >= 0 or null")));
|
|
916
|
+
}
|
|
917
|
+
if (!this.event_bus && original.event_status !== "completed") {
|
|
918
|
+
return this._withEventResultMethods(Promise.reject(new Error("event has no bus attached")));
|
|
919
|
+
}
|
|
920
|
+
if (options.first_result) {
|
|
921
|
+
return this._withEventResultMethods(this._waitForFirstResultOrCompletion(options));
|
|
922
|
+
}
|
|
923
|
+
if (original.event_status === "completed") {
|
|
924
|
+
return this._withEventResultMethods(Promise.resolve(this));
|
|
750
925
|
}
|
|
751
926
|
this._notifyDoneListeners();
|
|
752
|
-
|
|
927
|
+
const timeout = options.timeout ?? null;
|
|
928
|
+
return this._withEventResultMethods(
|
|
929
|
+
this._timeoutPromise(
|
|
930
|
+
timeout,
|
|
931
|
+
() => `Timed out waiting for ${original.event_type} completion after ${timeout}s`,
|
|
932
|
+
() => this._event_completed_signal.promise.then(() => this)
|
|
933
|
+
)
|
|
934
|
+
);
|
|
935
|
+
}
|
|
936
|
+
async eventResult(options = {}) {
|
|
937
|
+
const original = this._event_original ?? this;
|
|
938
|
+
if (original.event_status === "pending" && original.event_results.size === 0) {
|
|
939
|
+
await this.now({ first_result: true });
|
|
940
|
+
}
|
|
941
|
+
return this._collectResultValues(options, "registration").at(0);
|
|
942
|
+
}
|
|
943
|
+
async eventResultsList(options = {}) {
|
|
944
|
+
const original = this._event_original ?? this;
|
|
945
|
+
if (original.event_status === "pending" && original.event_results.size === 0) {
|
|
946
|
+
await this.now({ first_result: false });
|
|
947
|
+
}
|
|
948
|
+
return this._collectResultValues(options, "registration");
|
|
753
949
|
}
|
|
754
950
|
_markBlocksParentCompletionIfAwaitedFromEmittingHandler() {
|
|
755
951
|
const original = this._event_original ?? this;
|
|
@@ -843,23 +1039,8 @@ class BaseEvent {
|
|
|
843
1039
|
get event_errors() {
|
|
844
1040
|
return Array.from(this.event_results.values()).filter((event_result) => event_result.error !== void 0 && event_result.completed_at !== null).sort((event_result_a, event_result_b) => compareIsoDatetime(event_result_a.completed_at, event_result_b.completed_at)).map((event_result) => event_result.error);
|
|
845
1041
|
}
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
return false;
|
|
849
|
-
}
|
|
850
|
-
if (error.message.includes("first() resolved")) {
|
|
851
|
-
return true;
|
|
852
|
-
}
|
|
853
|
-
return error.cause instanceof Error && error.cause.message.includes("first() resolved");
|
|
854
|
-
}
|
|
855
|
-
_firstProcessingError(options = {}) {
|
|
856
|
-
const ignore_first_mode_control_errors = options.ignore_first_mode_control_errors ?? false;
|
|
857
|
-
return Array.from(this.event_results.values()).filter((event_result) => event_result.error !== void 0 && event_result.completed_at !== null).filter((event_result) => ignore_first_mode_control_errors ? !this._isFirstModeControlError(event_result.error) : true).sort((event_result_a, event_result_b) => compareIsoDatetime(event_result_a.completed_at, event_result_b.completed_at)).map((event_result) => event_result.error).at(0);
|
|
858
|
-
}
|
|
859
|
-
// Returns the first non-undefined completed handler result, sorted by completion time.
|
|
860
|
-
// Useful after first() or done() to get the winning result value.
|
|
861
|
-
get event_result() {
|
|
862
|
-
return Array.from(this.event_results.values()).filter((event_result) => event_result.completed_at !== null && event_result.result !== void 0).sort((event_result_a, event_result_b) => compareIsoDatetime(event_result_a.completed_at, event_result_b.completed_at)).map((event_result) => event_result.result).at(0);
|
|
1042
|
+
_firstProcessingError() {
|
|
1043
|
+
return Array.from(this.event_results.values()).filter((event_result) => event_result.error !== void 0 && event_result.completed_at !== null).sort((event_result_a, event_result_b) => compareIsoDatetime(event_result_a.completed_at, event_result_b.completed_at)).map((event_result) => event_result.error).at(0);
|
|
863
1044
|
}
|
|
864
1045
|
_areAllChildrenComplete(visited = /* @__PURE__ */ new Set()) {
|
|
865
1046
|
const original = this._event_original ?? this;
|