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
package/src/BaseEvent.ts CHANGED
@@ -13,7 +13,8 @@ import {
13
13
  withResolvers,
14
14
  } from './LockManager.js'
15
15
  import { _runWithTimeout } from './timing.js'
16
- import { isZodSchema, normalizeEventResultType, toJsonSchema } from './types.js'
16
+ import { toJsonSchema, type JsonSchema } from './jsonschema.js'
17
+ import { isZodSchema, normalizeEventResultType } from './types.js'
17
18
  import type { EventHandlerCallable, EventResultType } from './types.js'
18
19
  import { monotonicDatetime } from './helpers.js'
19
20
 
@@ -103,7 +104,17 @@ export const BaseEventSchema = z
103
104
  .loose()
104
105
 
105
106
  const KNOWN_BASE_EVENT_FIELDS = new Set(Object.keys(BaseEventSchema.shape))
106
- type AnyEventSchema = z.ZodTypeAny
107
+ const EVENT_FACTORY_METADATA_FIELDS = new Set([
108
+ 'class',
109
+ 'fromJSON',
110
+ 'prototype',
111
+ 'event_schema',
112
+ 'model_fields',
113
+ 'event_type',
114
+ 'event_version',
115
+ 'event_result_type',
116
+ ])
117
+ type AnyEventSchema = z.ZodObject<z.ZodRawShape>
107
118
 
108
119
  export type BaseEventData = z.infer<typeof BaseEventSchema>
109
120
  export type BaseEventJSON = BaseEventData & Record<string, unknown>
@@ -135,33 +146,104 @@ export type BaseEventInit<TFields extends Record<string, unknown>> = TFields & P
135
146
 
136
147
  type BaseEventSchemaShape = typeof BaseEventSchema.shape
137
148
  export type EventSchema<TShape extends z.ZodRawShape> = z.ZodObject<BaseEventSchemaShape & TShape>
138
- type EventPayload<TShape extends z.ZodRawShape> = TShape extends Record<string, never> ? {} : z.infer<z.ZodObject<TShape>>
149
+ type EventPayloadShape<TShape extends z.ZodRawShape> = {
150
+ [K in keyof TShape as K extends BaseEventFieldName ? never : K]: TShape[K]
151
+ }
152
+ type EventPayload<TShape extends z.ZodRawShape> =
153
+ EventPayloadShape<TShape> extends Record<string, never> ? {} : z.infer<z.ZodObject<EventPayloadShape<TShape>>>
154
+ type EventClassMetadataFieldName =
155
+ | 'fromJSON'
156
+ | 'prototype'
157
+ | 'event_schema'
158
+ | 'model_fields'
159
+ | 'event_type'
160
+ | 'event_version'
161
+ | 'event_result_type'
162
+ type StaticDefaultSchema = z.ZodDefault<z.ZodTypeAny> | z.ZodPrefault<z.ZodTypeAny> | z.ZodCatch<z.ZodTypeAny>
163
+ type EventModelFields<TShape extends z.ZodRawShape> = {
164
+ readonly [K in keyof TShape]: TShape[K]
165
+ }
166
+ type StaticEventDefaultValues<TShape extends z.ZodRawShape> = {
167
+ readonly [K in keyof TShape as K extends EventClassMetadataFieldName
168
+ ? never
169
+ : TShape[K] extends StaticDefaultSchema
170
+ ? K
171
+ : never]: z.output<TShape[K]>
172
+ }
173
+ type StaticEventDefaultValuesFromSchema<TSchema extends AnyEventSchema> =
174
+ TSchema extends z.ZodObject<infer TShape> ? StaticEventDefaultValues<TShape> : {}
175
+ type EventModelFieldsFromSchema<TSchema extends AnyEventSchema> =
176
+ TSchema extends z.ZodObject<infer TShape> ? TSchema['shape'] & EventModelFields<TShape> : {}
177
+ type OptionalFactoryArgs<TData> = {} extends TData ? [data?: TData] : [data: TData]
139
178
 
140
179
  type EventInput<TShape extends z.ZodRawShape> = z.input<EventSchema<TShape>>
141
180
  export type EventInit<TShape extends z.ZodRawShape> = Omit<EventInput<TShape>, keyof BaseEventFields> & Partial<BaseEventFields>
142
- type EventPayloadFromSchema<TSchema extends AnyEventSchema> = z.output<TSchema> extends Record<string, unknown> ? z.output<TSchema> : {}
181
+ type EventPayloadFromSchema<TSchema extends AnyEventSchema> =
182
+ z.output<TSchema> extends Record<string, unknown> ? Omit<z.output<TSchema>, keyof BaseEventFields> : {}
143
183
  type EventInputFromSchema<TSchema extends AnyEventSchema> = z.input<TSchema> extends Record<string, unknown> ? z.input<TSchema> : never
144
184
  export type EventInitFromSchema<TSchema extends AnyEventSchema> = Omit<EventInputFromSchema<TSchema>, keyof BaseEventFields> &
145
185
  Partial<BaseEventFields>
146
186
 
147
187
  type EventWithResultSchema<TResult> = BaseEvent & { __event_result_type__?: TResult }
188
+ type NormalizedEventResultSchema<TInput> = TInput extends z.ZodTypeAny
189
+ ? TInput
190
+ : TInput extends z.core.$ZodType
191
+ ? z.ZodType<z.output<TInput>>
192
+ : TInput extends StringConstructor
193
+ ? z.ZodString
194
+ : TInput extends NumberConstructor
195
+ ? z.ZodNumber
196
+ : TInput extends BooleanConstructor
197
+ ? z.ZodBoolean
198
+ : TInput extends ArrayConstructor
199
+ ? z.ZodArray<z.ZodUnknown>
200
+ : TInput extends ObjectConstructor
201
+ ? z.ZodRecord<z.ZodString, z.ZodUnknown>
202
+ : TInput extends JsonSchema
203
+ ? z.ZodTypeAny
204
+ : z.ZodTypeAny
205
+ type ResultTypeSchemaFromShape<TShape> = TShape extends { event_result_type: infer S }
206
+ ? NormalizedEventResultSchema<S>
207
+ : z.ZodTypeAny | undefined
208
+ type ResultTypeSchemaFromEventSchema<TSchema> =
209
+ TSchema extends z.ZodObject<infer TShape> ? ResultTypeSchemaFromShape<TShape> : z.ZodTypeAny | undefined
148
210
 
149
211
  type ResultTypeFromEventResultTypeInput<TInput> = TInput extends z.ZodTypeAny
150
212
  ? z.infer<TInput>
151
- : TInput extends StringConstructor
152
- ? string
153
- : TInput extends NumberConstructor
154
- ? number
155
- : TInput extends BooleanConstructor
156
- ? boolean
157
- : TInput extends ArrayConstructor
158
- ? unknown[]
159
- : TInput extends ObjectConstructor
160
- ? Record<string, unknown>
161
- : unknown
213
+ : TInput extends z.core.$ZodType
214
+ ? z.output<TInput>
215
+ : TInput extends StringConstructor
216
+ ? string
217
+ : TInput extends NumberConstructor
218
+ ? number
219
+ : TInput extends BooleanConstructor
220
+ ? boolean
221
+ : TInput extends ArrayConstructor
222
+ ? unknown[]
223
+ : TInput extends ObjectConstructor
224
+ ? Record<string, unknown>
225
+ : TInput extends JsonSchema
226
+ ? unknown
227
+ : unknown
162
228
 
163
229
  type ResultSchemaFromShape<TShape> = TShape extends { event_result_type: infer S } ? ResultTypeFromEventResultTypeInput<S> : unknown
164
230
  type ResultSchemaFromEventSchema<TSchema> = TSchema extends z.ZodObject<infer TShape> ? ResultSchemaFromShape<TShape> : unknown
231
+ type ZodLiteralValue = string | number | bigint | boolean | null | undefined
232
+ type SeenShortcutLiteralPairs = WeakMap<object, WeakSet<object>>
233
+ type ShortcutDefaultModelField<K, TValue> = K extends keyof BaseEventSchemaShape
234
+ ? z.ZodDefault<BaseEventSchemaShape[K]>
235
+ : z.ZodDefault<TValue extends ZodLiteralValue ? z.ZodLiteral<TValue> : z.ZodType<TValue>>
236
+ type ShortcutModelFields<TShape> = {
237
+ [K in keyof TShape as K extends 'event_result_type' ? never : K]: TShape[K] extends z.ZodTypeAny
238
+ ? TShape[K]
239
+ : ShortcutDefaultModelField<K, TShape[K]>
240
+ } & (TShape extends { event_result_type: infer TResultType } ? { event_result_type: NormalizedEventResultSchema<TResultType> } : {})
241
+ type ShortcutZodModelFields<TShape> = {
242
+ [K in keyof ShortcutModelFields<TShape>]: ShortcutModelFields<TShape>[K] extends z.ZodTypeAny ? ShortcutModelFields<TShape>[K] : never
243
+ }
244
+ type ShortcutStaticDefaultValues<TShape, TModelFields extends z.ZodRawShape> = StaticEventDefaultValues<TModelFields> & {
245
+ readonly [K in keyof TShape as K extends EventClassMetadataFieldName ? never : TShape[K] extends z.ZodTypeAny ? never : K]: TShape[K]
246
+ }
165
247
  export type EventResultInclude<TEvent extends BaseEvent> = (
166
248
  result: EventResult<TEvent>['result'],
167
249
  event_result: EventResult<TEvent>
@@ -188,26 +270,22 @@ type EventResultUpdateOptions<TEvent extends BaseEvent> = {
188
270
 
189
271
  const ROOT_EVENTBUS_ID = '00000000-0000-0000-0000-000000000000'
190
272
 
191
- export type EventFactory<TShape extends z.ZodRawShape, TResult = unknown> = {
192
- (data: EventInit<TShape>): EventWithResultSchema<TResult> & EventPayload<TShape>
193
- new (data: EventInit<TShape>): EventWithResultSchema<TResult> & EventPayload<TShape>
194
- event_schema: EventSchema<TShape>
195
- class?: new (data: EventInit<TShape>) => EventWithResultSchema<TResult> & EventPayload<TShape>
196
- event_type?: string
197
- event_version?: string
198
- event_result_type?: z.ZodTypeAny
199
- fromJSON?: (data: unknown) => EventWithResultSchema<TResult> & EventPayload<TShape>
200
- }
201
-
202
- export type SchemaEventFactory<TSchema extends AnyEventSchema, TResult = unknown> = {
203
- (data: EventInitFromSchema<TSchema>): EventWithResultSchema<TResult> & EventPayloadFromSchema<TSchema>
204
- new (data: EventInitFromSchema<TSchema>): EventWithResultSchema<TResult> & EventPayloadFromSchema<TSchema>
273
+ export type EventClass<
274
+ TEvent extends BaseEvent = BaseEvent,
275
+ TInit = never,
276
+ TSchema extends z.ZodTypeAny = AnyEventSchema,
277
+ TModelFields extends z.ZodRawShape = z.ZodRawShape,
278
+ TResultSchema extends z.ZodTypeAny | undefined = z.ZodTypeAny | undefined,
279
+ TStaticFields = {},
280
+ > = TStaticFields & {
281
+ (...args: OptionalFactoryArgs<TInit>): TEvent
282
+ new (...args: OptionalFactoryArgs<TInit>): TEvent
205
283
  event_schema: TSchema
206
- class?: new (data: EventInitFromSchema<TSchema>) => EventWithResultSchema<TResult> & EventPayloadFromSchema<TSchema>
207
- event_type?: string
208
- event_version?: string
209
- event_result_type?: z.ZodTypeAny
210
- fromJSON?: (data: unknown) => EventWithResultSchema<TResult> & EventPayloadFromSchema<TSchema>
284
+ model_fields: TModelFields
285
+ event_type: string
286
+ event_version: string
287
+ event_result_type: TResultSchema
288
+ fromJSON: (data: unknown) => TEvent
211
289
  }
212
290
 
213
291
  type ZodShapeFrom<TShape extends Record<string, unknown>> = {
@@ -247,15 +325,72 @@ function missingBaseFields(event_type: string, user_shape: z.ZodRawShape): z.Zod
247
325
  return Object.fromEntries(Object.entries(baseEventDefaultShape(event_type)).filter(([key]) => !(key in user_shape))) as z.ZodRawShape
248
326
  }
249
327
 
250
- type ZodSchemaWithPrefault = z.ZodTypeAny & {
251
- prefault: (value: unknown) => z.ZodTypeAny
328
+ function isZodLiteralValue(value: unknown): value is ZodLiteralValue {
329
+ return value === null || value === undefined || ['string', 'number', 'bigint', 'boolean'].includes(typeof value)
330
+ }
331
+
332
+ function isPlainShortcutLiteralObject(value: unknown): value is Record<string, unknown> {
333
+ if (!value || typeof value !== 'object' || Array.isArray(value)) {
334
+ return false
335
+ }
336
+ const prototype = Object.getPrototypeOf(value)
337
+ return prototype === Object.prototype || prototype === null
338
+ }
339
+
340
+ function alreadyComparedShortcutLiteralPair(left: object, right: object, seen: SeenShortcutLiteralPairs): boolean {
341
+ let right_values = seen.get(left)
342
+ if (right_values?.has(right)) {
343
+ return true
344
+ }
345
+ if (!right_values) {
346
+ right_values = new WeakSet<object>()
347
+ seen.set(left, right_values)
348
+ }
349
+ right_values.add(right)
350
+ return false
351
+ }
352
+
353
+ function shortcutLiteralValuesEqual(left: unknown, right: unknown, seen: SeenShortcutLiteralPairs = new WeakMap()): boolean {
354
+ if (Object.is(left, right)) {
355
+ return true
356
+ }
357
+ if (typeof left !== 'object' || left === null || typeof right !== 'object' || right === null) {
358
+ return false
359
+ }
360
+ if (alreadyComparedShortcutLiteralPair(left, right, seen)) {
361
+ return true
362
+ }
363
+ if (Array.isArray(left) || Array.isArray(right)) {
364
+ if (!Array.isArray(left) || !Array.isArray(right) || left.length !== right.length) {
365
+ return false
366
+ }
367
+ return left.every((item, index) => shortcutLiteralValuesEqual(item, right[index], seen))
368
+ }
369
+ if (!isPlainShortcutLiteralObject(left) || !isPlainShortcutLiteralObject(right)) {
370
+ return false
371
+ }
372
+ const left_keys = Object.keys(left)
373
+ const right_keys = Object.keys(right)
374
+ if (left_keys.length !== right_keys.length) {
375
+ return false
376
+ }
377
+ return left_keys.every((key) =>
378
+ Object.prototype.hasOwnProperty.call(right, key) ? shortcutLiteralValuesEqual(left[key], right[key], seen) : false
379
+ )
380
+ }
381
+
382
+ function shortcutLiteralSchema<TValue>(value: TValue): z.ZodType<TValue> {
383
+ if (isZodLiteralValue(value)) {
384
+ return z.literal(value) as z.ZodType<TValue>
385
+ }
386
+ return z.custom<TValue>((candidate) => shortcutLiteralValuesEqual(candidate, value), 'Invalid literal value')
252
387
  }
253
388
 
254
389
  function shortcutDefaultSchema(base_field_schema: z.ZodTypeAny | undefined, value: unknown): z.ZodTypeAny {
255
390
  if (!base_field_schema) {
256
- return z.unknown().optional().default(value)
391
+ return shortcutLiteralSchema(value).default(value)
257
392
  }
258
- return (base_field_schema as ZodSchemaWithPrefault).prefault(base_field_schema.parse(value))
393
+ return base_field_schema.default(base_field_schema.parse(value))
259
394
  }
260
395
 
261
396
  function schemaDefaultsForShortcut(event_type: string, raw_shape: Record<string, unknown>): z.ZodRawShape {
@@ -281,16 +416,54 @@ function zodFieldsForShortcut(raw_shape: Record<string, unknown>): z.ZodRawShape
281
416
  return fields
282
417
  }
283
418
 
419
+ function modelFieldsForShortcut(raw_shape: Record<string, unknown>, shortcut_shape: z.ZodRawShape): z.ZodRawShape {
420
+ const event_result_type = normalizeEventResultType(raw_shape.event_result_type)
421
+ return event_result_type ? { ...shortcut_shape, event_result_type } : shortcut_shape
422
+ }
423
+
424
+ function staticEventDefaultsFromModelFields(model_fields: z.ZodRawShape): Record<string, unknown> {
425
+ const fields: Record<string, unknown> = {}
426
+ for (const [key, value] of Object.entries(model_fields)) {
427
+ if (EVENT_FACTORY_METADATA_FIELDS.has(key)) {
428
+ continue
429
+ }
430
+ const parsed = (value as z.ZodTypeAny).safeParse(undefined)
431
+ if (parsed.success && parsed.data !== undefined) {
432
+ fields[key] = parsed.data
433
+ }
434
+ }
435
+ return fields
436
+ }
437
+
438
+ function defineStaticEventFields(target: object, fields: Record<string, unknown>): void {
439
+ for (const [key, value] of Object.entries(fields)) {
440
+ Object.defineProperty(target, key, {
441
+ value,
442
+ writable: false,
443
+ enumerable: true,
444
+ configurable: true,
445
+ })
446
+ }
447
+ }
448
+
284
449
  function eventResultTypeFromObjectSchema(schema: z.ZodObject<z.ZodRawShape>): z.ZodTypeAny | undefined {
285
450
  const raw_event_result_type = schema.shape.event_result_type
286
451
  return raw_event_result_type === undefined ? undefined : normalizeEventResultType(raw_event_result_type)
287
452
  }
288
453
 
454
+ function eventParseSchemaFromEventSchema(schema: z.ZodObject<z.ZodRawShape>): z.ZodObject<z.ZodRawShape> {
455
+ return schema.safeExtend({
456
+ event_result_type: z.unknown().optional(),
457
+ })
458
+ }
459
+
289
460
  function buildFullEventSchema(
290
461
  event_type: string,
291
462
  spec: unknown
292
463
  ): {
293
- event_schema: AnyEventSchema
464
+ event_schema: z.ZodObject<z.ZodRawShape>
465
+ event_parse_schema: z.ZodObject<z.ZodRawShape>
466
+ static_field_defaults: Record<string, unknown>
294
467
  event_result_type?: z.ZodTypeAny
295
468
  event_version?: string
296
469
  } {
@@ -300,11 +473,12 @@ function buildFullEventSchema(
300
473
  assertNoUnknownEventPrefixedFields(user_shape, `BaseEvent.extend(${event_type})`)
301
474
  assertNoModelPrefixedFields(user_shape, `BaseEvent.extend(${event_type})`)
302
475
  const full_schema = spec.safeExtend({
303
- event_result_type: z.unknown().optional(),
304
476
  ...missingBaseFields(event_type, user_shape),
305
477
  })
306
478
  return {
307
479
  event_schema: full_schema,
480
+ event_parse_schema: eventParseSchemaFromEventSchema(full_schema),
481
+ static_field_defaults: staticEventDefaultsFromModelFields(full_schema.shape),
308
482
  event_result_type: eventResultTypeFromObjectSchema(spec),
309
483
  }
310
484
  }
@@ -317,9 +491,12 @@ function buildFullEventSchema(
317
491
  ...schemaDefaultsForShortcut(event_type, raw_shape),
318
492
  ...zodFieldsForShortcut(raw_shape),
319
493
  }
320
- const full_schema = z.object(shortcut_shape).safeExtend(missingBaseFields(event_type, shortcut_shape)).loose()
494
+ const model_fields = modelFieldsForShortcut(raw_shape, shortcut_shape)
495
+ const full_schema = z.object(model_fields).safeExtend(missingBaseFields(event_type, model_fields)).loose()
321
496
  return {
322
497
  event_schema: full_schema,
498
+ event_parse_schema: eventParseSchemaFromEventSchema(full_schema),
499
+ static_field_defaults: staticEventDefaultsFromModelFields(full_schema.shape),
323
500
  event_result_type: normalizeEventResultType(raw_shape.event_result_type),
324
501
  event_version: typeof raw_shape.event_version === 'string' ? raw_shape.event_version : undefined,
325
502
  }
@@ -365,11 +542,14 @@ export class BaseEvent {
365
542
  event_handler_concurrency?: EventHandlerConcurrencyMode | null // concurrency mode for the handlers within the event
366
543
  event_handler_completion?: EventHandlerCompletionMode | null // completion strategy: 'all' (default) waits for every handler, 'first' returns earliest non-undefined result and cancels the rest
367
544
  event_schema?: z.ZodTypeAny
545
+ _event_parse_schema?: z.ZodTypeAny
368
546
 
369
547
  static event_type?: string // class name of the event, e.g. BaseEvent.extend("MyEvent").event_type === "MyEvent"
370
548
  static event_version = '0.0.1'
371
549
  static event_result_type?: z.ZodTypeAny
372
550
  static event_schema: AnyEventSchema = BaseEventSchema // generated Zod schema for local TS event data validation; never sent over the wire
551
+ static model_fields: z.ZodRawShape = BaseEventSchema.shape
552
+ static _event_parse_schema: AnyEventSchema = BaseEventSchema
373
553
 
374
554
  // internal runtime state
375
555
  event_bus?: EventBus // bus that dispatched this event, also used by event.emit(child)
@@ -387,6 +567,7 @@ export class BaseEvent {
387
567
  event_version?: string
388
568
  event_result_type?: z.ZodTypeAny
389
569
  event_schema?: AnyEventSchema
570
+ _event_parse_schema?: AnyEventSchema
390
571
  }
391
572
  const explicit_event_fields = new Set(Object.keys(data ?? {}))
392
573
  const merged_data = { ...data } as BaseEventInit<Record<string, unknown>>
@@ -396,6 +577,7 @@ export class BaseEvent {
396
577
  const event_result_type = normalizeEventResultType(raw_event_result_type)
397
578
 
398
579
  const event_schema = ctor.event_schema ?? BaseEventSchema
580
+ const event_parse_schema = ctor._event_parse_schema ?? event_schema
399
581
  const base_data: Record<string, unknown> = {
400
582
  ...merged_data,
401
583
  event_id: merged_data.event_id ?? uuidv7(),
@@ -404,12 +586,12 @@ export class BaseEvent {
404
586
  event_version,
405
587
  event_result_type,
406
588
  }
407
- if (event_schema === BaseEventSchema) {
589
+ if (event_parse_schema === BaseEventSchema) {
408
590
  base_data.event_timeout ??= null
409
591
  base_data.event_blocks_parent_completion ??= false
410
592
  }
411
593
 
412
- const parsed = decodeEventSchema(event_schema, base_data) as BaseEventData & Record<string, unknown>
594
+ const parsed = decodeEventSchema(event_parse_schema, base_data) as BaseEventData & Record<string, unknown>
413
595
 
414
596
  Object.assign(this, parsed)
415
597
  Object.defineProperty(this, 'event_schema', {
@@ -418,13 +600,18 @@ export class BaseEvent {
418
600
  enumerable: false,
419
601
  configurable: true,
420
602
  })
603
+ Object.defineProperty(this, '_event_parse_schema', {
604
+ value: event_parse_schema,
605
+ writable: true,
606
+ enumerable: false,
607
+ configurable: true,
608
+ })
421
609
  Object.defineProperty(this, '_event_fields_set', {
422
610
  value: explicit_event_fields,
423
611
  writable: true,
424
612
  enumerable: false,
425
613
  configurable: true,
426
614
  })
427
-
428
615
  const parsed_path = (parsed as { event_path?: string[] }).event_path
429
616
  this.event_path = Array.isArray(parsed_path) ? [...parsed_path] : []
430
617
  this.event_created_at = monotonicDatetime(parsed.event_created_at)
@@ -469,57 +656,110 @@ export class BaseEvent {
469
656
  static extend<TSchema extends z.ZodObject<z.ZodRawShape>>(
470
657
  event_type: string,
471
658
  event_schema: TSchema
472
- ): SchemaEventFactory<TSchema, ResultSchemaFromEventSchema<TSchema>>
473
- static extend<TShape extends z.ZodRawShape>(event_type: string, shape?: TShape): EventFactory<TShape, ResultSchemaFromShape<TShape>>
474
- static extend<TShape extends Record<string, unknown>>(
659
+ ): EventClass<
660
+ EventWithResultSchema<ResultSchemaFromEventSchema<TSchema>> & EventPayloadFromSchema<TSchema>,
661
+ EventInitFromSchema<TSchema>,
662
+ TSchema,
663
+ EventModelFieldsFromSchema<TSchema>,
664
+ ResultTypeSchemaFromEventSchema<TSchema>,
665
+ StaticEventDefaultValuesFromSchema<TSchema>
666
+ >
667
+ static extend<const TShape extends Record<string, unknown>>(
668
+ event_type: string,
669
+ shape?: TShape
670
+ ): EventClass<
671
+ EventWithResultSchema<ResultSchemaFromShape<ShortcutZodModelFields<TShape>>> & EventPayload<ShortcutZodModelFields<TShape>>,
672
+ EventInit<ShortcutZodModelFields<TShape>>,
673
+ EventSchema<ShortcutZodModelFields<TShape>>,
674
+ EventModelFields<ShortcutZodModelFields<TShape>>,
675
+ ResultTypeSchemaFromShape<ShortcutZodModelFields<TShape>>,
676
+ ShortcutStaticDefaultValues<TShape, ShortcutZodModelFields<TShape>>
677
+ >
678
+ static extend<TShape extends z.ZodRawShape>(
475
679
  event_type: string,
476
680
  shape?: TShape
477
- ): EventFactory<ZodShapeFrom<TShape>, ResultSchemaFromShape<TShape>>
478
- static extend<TShape extends Record<string, unknown>>(
681
+ ): EventClass<
682
+ EventWithResultSchema<ResultSchemaFromShape<TShape>> & EventPayload<TShape>,
683
+ EventInit<TShape>,
684
+ EventSchema<TShape>,
685
+ EventModelFields<TShape>,
686
+ ResultTypeSchemaFromShape<TShape>,
687
+ StaticEventDefaultValues<TShape>
688
+ >
689
+ static extend<const TShape extends Record<string, unknown>>(
479
690
  event_type: string,
480
691
  shape?: TShape
481
- ): EventFactory<ZodShapeFrom<TShape>, ResultSchemaFromShape<TShape>> | SchemaEventFactory<AnyEventSchema, unknown> {
692
+ ):
693
+ | EventClass<
694
+ EventWithResultSchema<ResultSchemaFromShape<ZodShapeFrom<TShape>>> & EventPayload<ZodShapeFrom<TShape>>,
695
+ EventInit<ZodShapeFrom<TShape>>,
696
+ EventSchema<ZodShapeFrom<TShape>>,
697
+ EventModelFields<ZodShapeFrom<TShape>>,
698
+ ResultTypeSchemaFromShape<ZodShapeFrom<TShape>>,
699
+ StaticEventDefaultValues<ZodShapeFrom<TShape>>
700
+ >
701
+ | EventClass<
702
+ EventWithResultSchema<ResultSchemaFromEventSchema<AnyEventSchema>> & EventPayloadFromSchema<AnyEventSchema>,
703
+ EventInitFromSchema<AnyEventSchema>,
704
+ AnyEventSchema,
705
+ EventModelFieldsFromSchema<AnyEventSchema>,
706
+ ResultTypeSchemaFromEventSchema<AnyEventSchema>,
707
+ StaticEventDefaultValuesFromSchema<AnyEventSchema>
708
+ > {
482
709
  const built = buildFullEventSchema(event_type, shape ?? {})
483
710
  const full_schema = built.event_schema
711
+ const event_parse_schema = built.event_parse_schema
712
+ const static_field_defaults = built.static_field_defaults
484
713
  const event_result_type = built.event_result_type
485
714
  const event_version = built.event_version
486
715
 
487
- // create a new event class that extends BaseEvent and adds the custom fields
488
- class ExtendedEvent extends BaseEvent {
489
- static event_schema = full_schema
490
- static event_type = event_type
491
- static event_version = event_version ?? BaseEvent.event_version
492
- static event_result_type = event_result_type
716
+ const EventClass = class extends BaseEvent {
717
+ static override event_schema = full_schema as EventSchema<ZodShapeFrom<TShape>>
718
+ static override model_fields = full_schema.shape as EventModelFields<ZodShapeFrom<TShape>>
719
+ static override _event_parse_schema = event_parse_schema
720
+ static override event_type = event_type
721
+ static override event_version = event_version ?? BaseEvent.event_version
722
+ static override event_result_type = event_result_type
493
723
 
494
- constructor(data: EventInit<ZodShapeFrom<TShape>> | EventInitFromSchema<AnyEventSchema>) {
495
- super(data as BaseEventInit<Record<string, unknown>>)
724
+ constructor(data?: EventInit<ZodShapeFrom<TShape>>) {
725
+ super(data)
496
726
  }
497
727
  }
498
728
 
499
- type FactoryResult = EventWithResultSchema<ResultSchemaFromShape<TShape>> & EventPayload<ZodShapeFrom<TShape>>
729
+ Object.defineProperty(EventClass, 'name', { value: event_type, configurable: true })
730
+ defineStaticEventFields(EventClass, static_field_defaults)
500
731
 
501
- function EventFactory(data: EventInit<ZodShapeFrom<TShape>>): FactoryResult {
502
- return new ExtendedEvent(data) as FactoryResult
503
- }
732
+ let CallableEventClass: typeof EventClass
733
+ CallableEventClass = new Proxy(EventClass, {
734
+ apply(target, _this_arg, args) {
735
+ return Reflect.construct(target, args, target)
736
+ },
737
+ construct(target, args, new_target) {
738
+ return Reflect.construct(target, args, new_target === CallableEventClass ? target : new_target)
739
+ },
740
+ })
504
741
 
505
- EventFactory.event_schema = full_schema as EventSchema<ZodShapeFrom<TShape>>
506
- EventFactory.event_type = event_type
507
- EventFactory.event_version = event_version ?? BaseEvent.event_version
508
- EventFactory.event_result_type = event_result_type
509
- EventFactory.class = ExtendedEvent as unknown as new (
510
- data: EventInit<ZodShapeFrom<TShape>>
511
- ) => EventWithResultSchema<ResultSchemaFromShape<TShape>> & EventPayload<ZodShapeFrom<TShape>>
512
- EventFactory.fromJSON = (data: unknown) => ExtendedEvent.fromJSON(data) as FactoryResult
513
- EventFactory.prototype = ExtendedEvent.prototype
514
- EVENT_TYPE_REGISTRY.set(event_type, ExtendedEvent)
742
+ Object.defineProperty(EventClass.prototype, 'constructor', {
743
+ value: CallableEventClass,
744
+ writable: true,
745
+ configurable: true,
746
+ })
747
+ EVENT_TYPE_REGISTRY.set(event_type, CallableEventClass as unknown as typeof BaseEvent)
515
748
 
516
- return EventFactory as unknown as EventFactory<ZodShapeFrom<TShape>, ResultSchemaFromShape<TShape>>
749
+ return CallableEventClass as unknown as EventClass<
750
+ EventWithResultSchema<ResultSchemaFromShape<ZodShapeFrom<TShape>>> & EventPayload<ZodShapeFrom<TShape>>,
751
+ EventInit<ZodShapeFrom<TShape>>,
752
+ EventSchema<ZodShapeFrom<TShape>>,
753
+ EventModelFields<ZodShapeFrom<TShape>>,
754
+ ResultTypeSchemaFromShape<ZodShapeFrom<TShape>>,
755
+ StaticEventDefaultValues<ZodShapeFrom<TShape>>
756
+ >
517
757
  }
518
758
 
519
759
  static fromJSON<T extends typeof BaseEvent>(this: T, data: unknown): InstanceType<T> {
520
760
  if (!data || typeof data !== 'object') {
521
- const event_schema = this.event_schema ?? BaseEventSchema
522
- const parsed = decodeEventSchema(event_schema, data)
761
+ const event_parse_schema = this._event_parse_schema ?? this.event_schema ?? BaseEventSchema
762
+ const parsed = decodeEventSchema(event_parse_schema, data)
523
763
  return new this(parsed) as InstanceType<T>
524
764
  }
525
765
  const record = { ...(data as Record<string, unknown>) }
@@ -536,9 +776,6 @@ export class BaseEvent {
536
776
  if (this !== BaseEvent && ctor.event_result_type && record.event_result_type !== undefined) {
537
777
  delete record.event_result_type
538
778
  }
539
- if (record.event_result_type !== undefined && record.event_result_type !== null) {
540
- record.event_result_type = normalizeEventResultType(record.event_result_type)
541
- }
542
779
  return new this(record as BaseEventInit<Record<string, unknown>>) as InstanceType<T>
543
780
  }
544
781
 
@@ -567,8 +804,12 @@ export class BaseEvent {
567
804
  Array.from(this.event_results.entries()).map(([handler_id, result]) => [handler_id, result.toJSON()])
568
805
  )
569
806
 
570
- const event_schema = ((this.constructor as typeof BaseEvent).event_schema ?? this.event_schema ?? BaseEventSchema) as AnyEventSchema
571
- const encoded = encodeEventSchema(event_schema, {
807
+ const event_parse_schema = ((this.constructor as typeof BaseEvent)._event_parse_schema ??
808
+ this._event_parse_schema ??
809
+ (this.constructor as typeof BaseEvent).event_schema ??
810
+ this.event_schema ??
811
+ BaseEventSchema) as AnyEventSchema
812
+ const encoded = encodeEventSchema(event_parse_schema, {
572
813
  ...record,
573
814
  event_id: this.event_id,
574
815
  event_type: this.event_type,
@@ -283,7 +283,7 @@ export class LockManager {
283
283
  this.idle_waiters.push(finish)
284
284
  this.scheduleIdleCheck()
285
285
 
286
- if (timeout_seconds === null || timeout_seconds === undefined) {
286
+ if (timeout_seconds === null || timeout_seconds === undefined || timeout_seconds <= 0) {
287
287
  return
288
288
  }
289
289
 
@@ -3,32 +3,27 @@ import { BaseEvent } from './BaseEvent.js'
3
3
 
4
4
  import type { EventClass, EventResultType } from './types.js'
5
5
 
6
- type EventMap = Record<string, EventClass<BaseEvent>>
7
- type AnyFn = (...args: any[]) => any
8
- type FunctionMap = Record<string, AnyFn>
6
+ type EventMap = Record<string, EventClass<BaseEvent, never>>
7
+ type FunctionMap = Record<string, (...args: never[]) => unknown>
9
8
  type ExtraDict = Record<string, unknown>
10
9
 
11
- type EventFieldsFromFn<TFunc extends AnyFn> =
12
- Parameters<TFunc> extends [infer TArg] ? (TArg extends Record<string, unknown> ? TArg : ExtraDict) : ExtraDict
13
-
14
- type GeneratedEvent<TFunc extends AnyFn> = {
15
- (
16
- data: EventFieldsFromFn<TFunc> & ExtraDict
17
- ): BaseEvent & EventFieldsFromFn<TFunc> & { __event_result_type__?: Awaited<ReturnType<TFunc>> }
18
- new (
19
- data: EventFieldsFromFn<TFunc> & ExtraDict
20
- ): BaseEvent & EventFieldsFromFn<TFunc> & { __event_result_type__?: Awaited<ReturnType<TFunc>> }
21
- event_type?: string
22
- }
10
+ type EventFieldsFromFn<TFunc extends FunctionMap[string]> =
11
+ Parameters<TFunc> extends [infer TArg, ...unknown[]] ? (TArg extends Record<string, unknown> ? TArg : ExtraDict) : ExtraDict
12
+
13
+ type EventFromFn<TFunc extends FunctionMap[string]> = BaseEvent &
14
+ EventFieldsFromFn<TFunc> & {
15
+ __event_result_type__?: Awaited<ReturnType<TFunc>>
16
+ }
23
17
 
24
18
  export type GeneratedEvents<TEvents extends FunctionMap> = {
25
- by_name: { [K in keyof TEvents]: GeneratedEvent<TEvents[K]> }
19
+ by_name: { [K in keyof TEvents]: EventClass<EventFromFn<TEvents[K]>, EventFieldsFromFn<TEvents[K]> & ExtraDict> }
26
20
  } & {
27
- [K in keyof TEvents]: GeneratedEvent<TEvents[K]>
21
+ [K in keyof TEvents]: EventClass<EventFromFn<TEvents[K]>, EventFieldsFromFn<TEvents[K]> & ExtraDict>
28
22
  }
29
23
 
30
- type EventInit<TEventClass extends EventClass<BaseEvent>> =
31
- ConstructorParameters<TEventClass> extends [infer TInit, ...unknown[]] ? TInit : never
24
+ type EventInit<TEventClass extends EventClass<BaseEvent>> = [ConstructorParameters<TEventClass>[0]] extends [undefined]
25
+ ? {}
26
+ : NonNullable<ConstructorParameters<TEventClass>[0]>
32
27
 
33
28
  type EventMethodArgs<TEventClass extends EventClass<BaseEvent>> =
34
29
  {} extends EventInit<TEventClass>
@@ -50,12 +45,12 @@ type DynamicWrappedClient = {
50
45
  } & Record<string, (...args: unknown[]) => Promise<unknown>>
51
46
 
52
47
  export const make_events = <TEvents extends FunctionMap>(events: TEvents): GeneratedEvents<TEvents> => {
53
- const by_name = {} as { [K in keyof TEvents]: GeneratedEvent<TEvents[K]> }
48
+ const by_name = {} as GeneratedEvents<TEvents>['by_name']
54
49
  for (const [event_name] of Object.entries(events) as Array<[keyof TEvents, TEvents[keyof TEvents]]>) {
55
50
  if (!/^[A-Za-z_$][\w$]*$/.test(String(event_name))) {
56
51
  throw new Error(`Invalid event name: ${String(event_name)}`)
57
52
  }
58
- by_name[event_name] = BaseEvent.extend(String(event_name), {}) as unknown as GeneratedEvent<TEvents[keyof TEvents]>
53
+ by_name[event_name] = BaseEvent.extend(String(event_name), {}) as unknown as GeneratedEvents<TEvents>['by_name'][typeof event_name]
59
54
  }
60
55
  return Object.assign({ by_name }, by_name) as GeneratedEvents<TEvents>
61
56
  }
@@ -75,7 +70,10 @@ export const wrap = <TEvents extends EventMap>(class_name: string, methods: TEve
75
70
  Object.defineProperty(WrappedClient.prototype, method_name, {
76
71
  value: async function (this: DynamicWrappedClient, init?: Record<string, unknown>, extra?: Record<string, unknown>) {
77
72
  const payload = { ...(init ?? {}), ...(extra ?? {}) }
78
- return await this.bus.emit(new EventCtor(payload)).now({ first_result: true }).eventResult()
73
+ return await this.bus
74
+ .emit((EventCtor as EventClass<BaseEvent, Record<string, unknown>>)(payload))
75
+ .now({ first_result: true })
76
+ .eventResult()
79
77
  },
80
78
  writable: true,
81
79
  configurable: true,