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.
- package/dist/cjs/BaseEvent.d.ts +53 -28
- package/dist/cjs/BaseEvent.js +148 -28
- package/dist/cjs/BaseEvent.js.map +2 -2
- package/dist/cjs/LockManager.js +1 -1
- package/dist/cjs/LockManager.js.map +2 -2
- package/dist/cjs/events_suck.d.ts +8 -15
- package/dist/cjs/events_suck.js +1 -1
- package/dist/cjs/events_suck.js.map +2 -2
- package/dist/cjs/jsonschema.d.ts +6 -0
- package/dist/cjs/jsonschema.js +155 -0
- package/dist/cjs/jsonschema.js.map +7 -0
- package/dist/cjs/retry.d.ts +2 -0
- package/dist/cjs/retry.js +110 -35
- package/dist/cjs/retry.js.map +3 -3
- package/dist/cjs/types.d.ts +6 -10
- package/dist/cjs/types.js +9 -16
- package/dist/cjs/types.js.map +2 -2
- package/dist/esm/BaseEvent.js +148 -28
- package/dist/esm/BaseEvent.js.map +2 -2
- package/dist/esm/LockManager.js +1 -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/jsonschema.js +135 -0
- package/dist/esm/jsonschema.js.map +7 -0
- package/dist/esm/retry.js +110 -35
- package/dist/esm/retry.js.map +3 -3
- package/dist/esm/types.js +8 -15
- package/dist/esm/types.js.map +2 -2
- package/dist/types/BaseEvent.d.ts +53 -28
- package/dist/types/events_suck.d.ts +8 -15
- package/dist/types/jsonschema.d.ts +6 -0
- package/dist/types/retry.d.ts +2 -0
- package/dist/types/types.d.ts +6 -10
- package/package.json +1 -1
- package/src/BaseEvent.ts +321 -80
- package/src/LockManager.ts +1 -1
- package/src/events_suck.ts +20 -22
- package/src/jsonschema.ts +146 -0
- package/src/retry.ts +132 -38
- 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 {
|
|
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
|
-
|
|
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
|
|
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> =
|
|
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
|
|
152
|
-
?
|
|
153
|
-
: TInput extends
|
|
154
|
-
?
|
|
155
|
-
: TInput extends
|
|
156
|
-
?
|
|
157
|
-
: TInput extends
|
|
158
|
-
?
|
|
159
|
-
: TInput extends
|
|
160
|
-
?
|
|
161
|
-
:
|
|
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
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
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
|
-
|
|
207
|
-
event_type
|
|
208
|
-
event_version
|
|
209
|
-
event_result_type
|
|
210
|
-
fromJSON
|
|
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
|
-
|
|
251
|
-
|
|
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
|
|
391
|
+
return shortcutLiteralSchema(value).default(value)
|
|
257
392
|
}
|
|
258
|
-
return
|
|
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:
|
|
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
|
|
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 (
|
|
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(
|
|
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
|
-
):
|
|
473
|
-
|
|
474
|
-
|
|
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
|
-
):
|
|
478
|
-
|
|
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
|
-
):
|
|
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
|
-
|
|
488
|
-
|
|
489
|
-
static
|
|
490
|
-
static
|
|
491
|
-
static
|
|
492
|
-
static
|
|
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
|
|
495
|
-
super(data
|
|
724
|
+
constructor(data?: EventInit<ZodShapeFrom<TShape>>) {
|
|
725
|
+
super(data)
|
|
496
726
|
}
|
|
497
727
|
}
|
|
498
728
|
|
|
499
|
-
|
|
729
|
+
Object.defineProperty(EventClass, 'name', { value: event_type, configurable: true })
|
|
730
|
+
defineStaticEventFields(EventClass, static_field_defaults)
|
|
500
731
|
|
|
501
|
-
|
|
502
|
-
|
|
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
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
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
|
|
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
|
|
522
|
-
const parsed = decodeEventSchema(
|
|
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
|
|
571
|
-
|
|
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,
|
package/src/LockManager.ts
CHANGED
|
@@ -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
|
|
package/src/events_suck.ts
CHANGED
|
@@ -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
|
|
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
|
|
12
|
-
Parameters<TFunc> extends [infer TArg] ? (TArg extends Record<string, unknown> ? TArg : ExtraDict) : ExtraDict
|
|
13
|
-
|
|
14
|
-
type
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
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]:
|
|
19
|
+
by_name: { [K in keyof TEvents]: EventClass<EventFromFn<TEvents[K]>, EventFieldsFromFn<TEvents[K]> & ExtraDict> }
|
|
26
20
|
} & {
|
|
27
|
-
[K in keyof TEvents]:
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
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,
|