abxbus 2.5.4 → 2.5.9

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.
Files changed (41) hide show
  1. package/dist/cjs/BaseEvent.d.ts +53 -28
  2. package/dist/cjs/BaseEvent.js +148 -28
  3. package/dist/cjs/BaseEvent.js.map +2 -2
  4. package/dist/cjs/LockManager.js +1 -1
  5. package/dist/cjs/LockManager.js.map +2 -2
  6. package/dist/cjs/events_suck.d.ts +8 -15
  7. package/dist/cjs/events_suck.js +1 -1
  8. package/dist/cjs/events_suck.js.map +2 -2
  9. package/dist/cjs/jsonschema.d.ts +6 -0
  10. package/dist/cjs/jsonschema.js +155 -0
  11. package/dist/cjs/jsonschema.js.map +7 -0
  12. package/dist/cjs/retry.d.ts +2 -0
  13. package/dist/cjs/retry.js +110 -35
  14. package/dist/cjs/retry.js.map +3 -3
  15. package/dist/cjs/types.d.ts +6 -10
  16. package/dist/cjs/types.js +9 -16
  17. package/dist/cjs/types.js.map +2 -2
  18. package/dist/esm/BaseEvent.js +148 -28
  19. package/dist/esm/BaseEvent.js.map +2 -2
  20. package/dist/esm/LockManager.js +1 -1
  21. package/dist/esm/LockManager.js.map +2 -2
  22. package/dist/esm/events_suck.js +1 -1
  23. package/dist/esm/events_suck.js.map +2 -2
  24. package/dist/esm/jsonschema.js +135 -0
  25. package/dist/esm/jsonschema.js.map +7 -0
  26. package/dist/esm/retry.js +110 -35
  27. package/dist/esm/retry.js.map +3 -3
  28. package/dist/esm/types.js +8 -15
  29. package/dist/esm/types.js.map +2 -2
  30. package/dist/types/BaseEvent.d.ts +53 -28
  31. package/dist/types/events_suck.d.ts +8 -15
  32. package/dist/types/jsonschema.d.ts +6 -0
  33. package/dist/types/retry.d.ts +2 -0
  34. package/dist/types/types.d.ts +6 -10
  35. package/package.json +1 -1
  36. package/src/BaseEvent.ts +321 -80
  37. package/src/LockManager.ts +1 -1
  38. package/src/events_suck.ts +20 -22
  39. package/src/jsonschema.ts +146 -0
  40. package/src/retry.ts +132 -38
  41. package/src/types.ts +10 -19
@@ -10,7 +10,8 @@ import {
10
10
  withResolvers
11
11
  } from "./LockManager.js";
12
12
  import { _runWithTimeout } from "./timing.js";
13
- import { isZodSchema, normalizeEventResultType, toJsonSchema } from "./types.js";
13
+ import { toJsonSchema } from "./jsonschema.js";
14
+ import { isZodSchema, normalizeEventResultType } from "./types.js";
14
15
  import { monotonicDatetime } from "./helpers.js";
15
16
  const RESERVED_USER_EVENT_FIELDS = /* @__PURE__ */ new Set([
16
17
  "bus",
@@ -83,6 +84,16 @@ const BaseEventSchema = z.object({
83
84
  event_handler_completion: z.enum(EVENT_HANDLER_COMPLETION_MODES).nullable().optional()
84
85
  }).loose();
85
86
  const KNOWN_BASE_EVENT_FIELDS = new Set(Object.keys(BaseEventSchema.shape));
87
+ const EVENT_FACTORY_METADATA_FIELDS = /* @__PURE__ */ new Set([
88
+ "class",
89
+ "fromJSON",
90
+ "prototype",
91
+ "event_schema",
92
+ "model_fields",
93
+ "event_type",
94
+ "event_version",
95
+ "event_result_type"
96
+ ]);
86
97
  const ROOT_EVENTBUS_ID = "00000000-0000-0000-0000-000000000000";
87
98
  function baseEventDefaultShape(event_type) {
88
99
  return {
@@ -112,11 +123,67 @@ function baseEventDefaultShape(event_type) {
112
123
  function missingBaseFields(event_type, user_shape) {
113
124
  return Object.fromEntries(Object.entries(baseEventDefaultShape(event_type)).filter(([key]) => !(key in user_shape)));
114
125
  }
126
+ function isZodLiteralValue(value) {
127
+ return value === null || value === void 0 || ["string", "number", "bigint", "boolean"].includes(typeof value);
128
+ }
129
+ function isPlainShortcutLiteralObject(value) {
130
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
131
+ return false;
132
+ }
133
+ const prototype = Object.getPrototypeOf(value);
134
+ return prototype === Object.prototype || prototype === null;
135
+ }
136
+ function alreadyComparedShortcutLiteralPair(left, right, seen) {
137
+ let right_values = seen.get(left);
138
+ if (right_values?.has(right)) {
139
+ return true;
140
+ }
141
+ if (!right_values) {
142
+ right_values = /* @__PURE__ */ new WeakSet();
143
+ seen.set(left, right_values);
144
+ }
145
+ right_values.add(right);
146
+ return false;
147
+ }
148
+ function shortcutLiteralValuesEqual(left, right, seen = /* @__PURE__ */ new WeakMap()) {
149
+ if (Object.is(left, right)) {
150
+ return true;
151
+ }
152
+ if (typeof left !== "object" || left === null || typeof right !== "object" || right === null) {
153
+ return false;
154
+ }
155
+ if (alreadyComparedShortcutLiteralPair(left, right, seen)) {
156
+ return true;
157
+ }
158
+ if (Array.isArray(left) || Array.isArray(right)) {
159
+ if (!Array.isArray(left) || !Array.isArray(right) || left.length !== right.length) {
160
+ return false;
161
+ }
162
+ return left.every((item, index) => shortcutLiteralValuesEqual(item, right[index], seen));
163
+ }
164
+ if (!isPlainShortcutLiteralObject(left) || !isPlainShortcutLiteralObject(right)) {
165
+ return false;
166
+ }
167
+ const left_keys = Object.keys(left);
168
+ const right_keys = Object.keys(right);
169
+ if (left_keys.length !== right_keys.length) {
170
+ return false;
171
+ }
172
+ return left_keys.every(
173
+ (key) => Object.prototype.hasOwnProperty.call(right, key) ? shortcutLiteralValuesEqual(left[key], right[key], seen) : false
174
+ );
175
+ }
176
+ function shortcutLiteralSchema(value) {
177
+ if (isZodLiteralValue(value)) {
178
+ return z.literal(value);
179
+ }
180
+ return z.custom((candidate) => shortcutLiteralValuesEqual(candidate, value), "Invalid literal value");
181
+ }
115
182
  function shortcutDefaultSchema(base_field_schema, value) {
116
183
  if (!base_field_schema) {
117
- return z.unknown().optional().default(value);
184
+ return shortcutLiteralSchema(value).default(value);
118
185
  }
119
- return base_field_schema.prefault(base_field_schema.parse(value));
186
+ return base_field_schema.default(base_field_schema.parse(value));
120
187
  }
121
188
  function schemaDefaultsForShortcut(event_type, raw_shape) {
122
189
  const defaults = {};
@@ -139,10 +206,42 @@ function zodFieldsForShortcut(raw_shape) {
139
206
  }
140
207
  return fields;
141
208
  }
209
+ function modelFieldsForShortcut(raw_shape, shortcut_shape) {
210
+ const event_result_type = normalizeEventResultType(raw_shape.event_result_type);
211
+ return event_result_type ? { ...shortcut_shape, event_result_type } : shortcut_shape;
212
+ }
213
+ function staticEventDefaultsFromModelFields(model_fields) {
214
+ const fields = {};
215
+ for (const [key, value] of Object.entries(model_fields)) {
216
+ if (EVENT_FACTORY_METADATA_FIELDS.has(key)) {
217
+ continue;
218
+ }
219
+ const parsed = value.safeParse(void 0);
220
+ if (parsed.success && parsed.data !== void 0) {
221
+ fields[key] = parsed.data;
222
+ }
223
+ }
224
+ return fields;
225
+ }
226
+ function defineStaticEventFields(target, fields) {
227
+ for (const [key, value] of Object.entries(fields)) {
228
+ Object.defineProperty(target, key, {
229
+ value,
230
+ writable: false,
231
+ enumerable: true,
232
+ configurable: true
233
+ });
234
+ }
235
+ }
142
236
  function eventResultTypeFromObjectSchema(schema) {
143
237
  const raw_event_result_type = schema.shape.event_result_type;
144
238
  return raw_event_result_type === void 0 ? void 0 : normalizeEventResultType(raw_event_result_type);
145
239
  }
240
+ function eventParseSchemaFromEventSchema(schema) {
241
+ return schema.safeExtend({
242
+ event_result_type: z.unknown().optional()
243
+ });
244
+ }
146
245
  function buildFullEventSchema(event_type, spec) {
147
246
  if (isZodObjectSchema(spec)) {
148
247
  const user_shape = spec.shape;
@@ -150,11 +249,12 @@ function buildFullEventSchema(event_type, spec) {
150
249
  assertNoUnknownEventPrefixedFields(user_shape, `BaseEvent.extend(${event_type})`);
151
250
  assertNoModelPrefixedFields(user_shape, `BaseEvent.extend(${event_type})`);
152
251
  const full_schema2 = spec.safeExtend({
153
- event_result_type: z.unknown().optional(),
154
252
  ...missingBaseFields(event_type, user_shape)
155
253
  });
156
254
  return {
157
255
  event_schema: full_schema2,
256
+ event_parse_schema: eventParseSchemaFromEventSchema(full_schema2),
257
+ static_field_defaults: staticEventDefaultsFromModelFields(full_schema2.shape),
158
258
  event_result_type: eventResultTypeFromObjectSchema(spec)
159
259
  };
160
260
  }
@@ -166,9 +266,12 @@ function buildFullEventSchema(event_type, spec) {
166
266
  ...schemaDefaultsForShortcut(event_type, raw_shape),
167
267
  ...zodFieldsForShortcut(raw_shape)
168
268
  };
169
- const full_schema = z.object(shortcut_shape).safeExtend(missingBaseFields(event_type, shortcut_shape)).loose();
269
+ const model_fields = modelFieldsForShortcut(raw_shape, shortcut_shape);
270
+ const full_schema = z.object(model_fields).safeExtend(missingBaseFields(event_type, model_fields)).loose();
170
271
  return {
171
272
  event_schema: full_schema,
273
+ event_parse_schema: eventParseSchemaFromEventSchema(full_schema),
274
+ static_field_defaults: staticEventDefaultsFromModelFields(full_schema.shape),
172
275
  event_result_type: normalizeEventResultType(raw_shape.event_result_type),
173
276
  event_version: typeof raw_shape.event_version === "string" ? raw_shape.event_version : void 0
174
277
  };
@@ -229,12 +332,15 @@ class BaseEvent {
229
332
  event_handler_completion;
230
333
  // completion strategy: 'all' (default) waits for every handler, 'first' returns earliest non-undefined result and cancels the rest
231
334
  event_schema;
335
+ _event_parse_schema;
232
336
  static event_type;
233
337
  // class name of the event, e.g. BaseEvent.extend("MyEvent").event_type === "MyEvent"
234
338
  static event_version = "0.0.1";
235
339
  static event_result_type;
236
340
  static event_schema = BaseEventSchema;
237
341
  // generated Zod schema for local TS event data validation; never sent over the wire
342
+ static model_fields = BaseEventSchema.shape;
343
+ static _event_parse_schema = BaseEventSchema;
238
344
  // internal runtime state
239
345
  event_bus;
240
346
  // bus that dispatched this event, also used by event.emit(child)
@@ -257,6 +363,7 @@ class BaseEvent {
257
363
  const raw_event_result_type = merged_data.event_result_type ?? ctor.event_result_type;
258
364
  const event_result_type = normalizeEventResultType(raw_event_result_type);
259
365
  const event_schema = ctor.event_schema ?? BaseEventSchema;
366
+ const event_parse_schema = ctor._event_parse_schema ?? event_schema;
260
367
  const base_data = {
261
368
  ...merged_data,
262
369
  event_id: merged_data.event_id ?? uuidv7(),
@@ -265,11 +372,11 @@ class BaseEvent {
265
372
  event_version,
266
373
  event_result_type
267
374
  };
268
- if (event_schema === BaseEventSchema) {
375
+ if (event_parse_schema === BaseEventSchema) {
269
376
  base_data.event_timeout ??= null;
270
377
  base_data.event_blocks_parent_completion ??= false;
271
378
  }
272
- const parsed = decodeEventSchema(event_schema, base_data);
379
+ const parsed = decodeEventSchema(event_parse_schema, base_data);
273
380
  Object.assign(this, parsed);
274
381
  Object.defineProperty(this, "event_schema", {
275
382
  value: event_schema,
@@ -277,6 +384,12 @@ class BaseEvent {
277
384
  enumerable: false,
278
385
  configurable: true
279
386
  });
387
+ Object.defineProperty(this, "_event_parse_schema", {
388
+ value: event_parse_schema,
389
+ writable: true,
390
+ enumerable: false,
391
+ configurable: true
392
+ });
280
393
  Object.defineProperty(this, "_event_fields_set", {
281
394
  value: explicit_event_fields,
282
395
  writable: true,
@@ -306,34 +419,44 @@ class BaseEvent {
306
419
  static extend(event_type, shape) {
307
420
  const built = buildFullEventSchema(event_type, shape ?? {});
308
421
  const full_schema = built.event_schema;
422
+ const event_parse_schema = built.event_parse_schema;
423
+ const static_field_defaults = built.static_field_defaults;
309
424
  const event_result_type = built.event_result_type;
310
425
  const event_version = built.event_version;
311
- class ExtendedEvent extends BaseEvent {
426
+ const EventClass = class extends BaseEvent {
312
427
  static event_schema = full_schema;
428
+ static model_fields = full_schema.shape;
429
+ static _event_parse_schema = event_parse_schema;
313
430
  static event_type = event_type;
314
431
  static event_version = event_version ?? BaseEvent.event_version;
315
432
  static event_result_type = event_result_type;
316
433
  constructor(data) {
317
434
  super(data);
318
435
  }
319
- }
320
- function EventFactory(data) {
321
- return new ExtendedEvent(data);
322
- }
323
- EventFactory.event_schema = full_schema;
324
- EventFactory.event_type = event_type;
325
- EventFactory.event_version = event_version ?? BaseEvent.event_version;
326
- EventFactory.event_result_type = event_result_type;
327
- EventFactory.class = ExtendedEvent;
328
- EventFactory.fromJSON = (data) => ExtendedEvent.fromJSON(data);
329
- EventFactory.prototype = ExtendedEvent.prototype;
330
- EVENT_TYPE_REGISTRY.set(event_type, ExtendedEvent);
331
- return EventFactory;
436
+ };
437
+ Object.defineProperty(EventClass, "name", { value: event_type, configurable: true });
438
+ defineStaticEventFields(EventClass, static_field_defaults);
439
+ let CallableEventClass;
440
+ CallableEventClass = new Proxy(EventClass, {
441
+ apply(target, _this_arg, args) {
442
+ return Reflect.construct(target, args, target);
443
+ },
444
+ construct(target, args, new_target) {
445
+ return Reflect.construct(target, args, new_target === CallableEventClass ? target : new_target);
446
+ }
447
+ });
448
+ Object.defineProperty(EventClass.prototype, "constructor", {
449
+ value: CallableEventClass,
450
+ writable: true,
451
+ configurable: true
452
+ });
453
+ EVENT_TYPE_REGISTRY.set(event_type, CallableEventClass);
454
+ return CallableEventClass;
332
455
  }
333
456
  static fromJSON(data) {
334
457
  if (!data || typeof data !== "object") {
335
- const event_schema = this.event_schema ?? BaseEventSchema;
336
- const parsed = decodeEventSchema(event_schema, data);
458
+ const event_parse_schema = this._event_parse_schema ?? this.event_schema ?? BaseEventSchema;
459
+ const parsed = decodeEventSchema(event_parse_schema, data);
337
460
  return new this(parsed);
338
461
  }
339
462
  const record = { ...data };
@@ -350,9 +473,6 @@ class BaseEvent {
350
473
  if (this !== BaseEvent && ctor.event_result_type && record.event_result_type !== void 0) {
351
474
  delete record.event_result_type;
352
475
  }
353
- if (record.event_result_type !== void 0 && record.event_result_type !== null) {
354
- record.event_result_type = normalizeEventResultType(record.event_result_type);
355
- }
356
476
  return new this(record);
357
477
  }
358
478
  static toJSONArray(events) {
@@ -377,8 +497,8 @@ class BaseEvent {
377
497
  const event_results = Object.fromEntries(
378
498
  Array.from(this.event_results.entries()).map(([handler_id, result]) => [handler_id, result.toJSON()])
379
499
  );
380
- const event_schema = this.constructor.event_schema ?? this.event_schema ?? BaseEventSchema;
381
- const encoded = encodeEventSchema(event_schema, {
500
+ const event_parse_schema = this.constructor._event_parse_schema ?? this._event_parse_schema ?? this.constructor.event_schema ?? this.event_schema ?? BaseEventSchema;
501
+ const encoded = encodeEventSchema(event_parse_schema, {
382
502
  ...record,
383
503
  event_id: this.event_id,
384
504
  event_type: this.event_type,