@requence/event-sourcing 1.4.1 → 1.5.1
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 +6 -5
- package/dist/{chunk-24xjphpk.js → chunk-06anxtk6.js} +6 -6
- package/dist/{chunk-24xjphpk.js.map → chunk-06anxtk6.js.map} +2 -2
- package/dist/{chunk-263c07sn.js → chunk-1mr4cwpw.js} +8 -8
- package/dist/{chunk-263c07sn.js.map → chunk-1mr4cwpw.js.map} +2 -2
- package/dist/{chunk-3ejt4h7x.js → chunk-2wqpktzp.js} +78 -66
- package/dist/chunk-2wqpktzp.js.map +10 -0
- package/dist/{chunk-dgzw1nj9.js → chunk-467qtkth.js} +8 -3
- package/dist/chunk-467qtkth.js.map +10 -0
- package/dist/chunk-6dn6wxg7.js +11 -0
- package/dist/{chunk-jd4q8fcf.js.map → chunk-6dn6wxg7.js.map} +2 -2
- package/dist/{chunk-pc1q4se9.js → chunk-9qtjz725.js} +2 -2
- package/dist/{chunk-pc1q4se9.js.map → chunk-9qtjz725.js.map} +2 -2
- package/dist/{chunk-tfy01fah.js → chunk-c7sytwpp.js} +4 -4
- package/dist/{chunk-tfy01fah.js.map → chunk-c7sytwpp.js.map} +2 -2
- package/dist/{chunk-vvv14qxy.js → chunk-d6jqbrq2.js} +33 -31
- package/dist/{chunk-vvv14qxy.js.map → chunk-d6jqbrq2.js.map} +3 -3
- package/dist/{chunk-vep2byx4.js → chunk-f95c3da4.js} +77 -64
- package/dist/chunk-f95c3da4.js.map +10 -0
- package/dist/chunk-fpjnk143.js +13 -0
- package/dist/{chunk-6q8mr1sg.js.map → chunk-fpjnk143.js.map} +2 -2
- package/dist/{chunk-8qn1nqnh.js → chunk-fxb9fbvz.js} +9 -9
- package/dist/{chunk-8qn1nqnh.js.map → chunk-fxb9fbvz.js.map} +2 -2
- package/dist/chunk-hmvwn02w.js +22 -0
- package/dist/{chunk-6yrb30rx.js.map → chunk-hmvwn02w.js.map} +2 -2
- package/dist/{chunk-ty9bhdvx.js → chunk-j4mwjx07.js} +5 -3
- package/dist/chunk-j4mwjx07.js.map +10 -0
- package/dist/{chunk-391m4mfp.js → chunk-jw9e0fr0.js} +13 -13
- package/dist/{chunk-391m4mfp.js.map → chunk-jw9e0fr0.js.map} +2 -2
- package/dist/chunk-mbxxvskx.js +67 -0
- package/dist/chunk-mbxxvskx.js.map +10 -0
- package/dist/{chunk-yn2sjcg3.js → chunk-nrhw3kde.js} +57 -8
- package/dist/chunk-nrhw3kde.js.map +10 -0
- package/dist/{chunk-57b88rt5.js → chunk-pcggjrxr.js} +32 -32
- package/dist/{chunk-57b88rt5.js.map → chunk-pcggjrxr.js.map} +2 -2
- package/dist/chunk-tkwe4r0y.js +22 -0
- package/dist/{chunk-2fe8jjdc.js.map → chunk-tkwe4r0y.js.map} +2 -2
- package/dist/{chunk-z388cd25.js → chunk-zkz6ew8c.js} +5 -5
- package/dist/{chunk-z388cd25.js.map → chunk-zkz6ew8c.js.map} +2 -2
- package/dist/createAggregateRoot.d.ts +1 -1
- package/dist/createAggregateRoot.d.ts.map +1 -1
- package/dist/createAggregateRoot.js +15 -14
- package/dist/createAggregateRoot.js.map +1 -1
- package/dist/createCheckpointApi.d.ts +30 -0
- package/dist/createCheckpointApi.d.ts.map +1 -1
- package/dist/createCheckpointApi.js +5 -5
- package/dist/createCheckpointApi.js.map +1 -1
- package/dist/createEventListener.js +8 -8
- package/dist/createEventListener.js.map +1 -1
- package/dist/createEventStore.js +16 -16
- package/dist/createEventStore.js.map +1 -1
- package/dist/createProcessManager.d.ts.map +1 -1
- package/dist/createProcessManager.js +12 -12
- package/dist/createProcessManager.js.map +1 -1
- package/dist/createProjection.d.ts.map +1 -1
- package/dist/createProjection.js +12 -12
- package/dist/createProjection.js.map +1 -1
- package/dist/drizzle/index.js +132 -132
- package/dist/drizzle/index.js.map +2 -2
- package/dist/drizzle/postgres.js +14 -14
- package/dist/drizzle/postgres.js.map +1 -1
- package/dist/errors.js +24 -24
- package/dist/errors.js.map +1 -1
- package/dist/index.js +63 -63
- package/dist/index.js.map +1 -1
- package/dist/lock.d.ts +11 -3
- package/dist/lock.d.ts.map +1 -1
- package/dist/lock.js +4 -2
- package/dist/lock.js.map +1 -1
- package/dist/memory/index.d.ts +14 -3
- package/dist/memory/index.d.ts.map +1 -1
- package/dist/memory/index.js +52 -45
- package/dist/memory/index.js.map +3 -3
- package/dist/memory/index.spec.d.ts +2 -0
- package/dist/memory/index.spec.d.ts.map +1 -0
- package/dist/redis/index.js +5 -4
- package/dist/redis/index.js.map +1 -1
- package/dist/redis/redisLock.d.ts +1 -1
- package/dist/redis/redisLock.d.ts.map +1 -1
- package/dist/redis/redisLock.js +5 -4
- package/dist/redis/redisLock.js.map +1 -1
- package/dist/refresh.js +9 -9
- package/dist/refresh.js.map +1 -1
- package/dist/replay.js +9 -9
- package/dist/replay.js.map +1 -1
- package/dist/snapshotGenerator.js +2 -2
- package/dist/superjson.js +8 -8
- package/dist/superjson.js.map +1 -1
- package/dist/surreal/index.d.ts +35 -0
- package/dist/surreal/index.d.ts.map +1 -0
- package/dist/surreal/index.js +415 -0
- package/dist/surreal/index.js.map +10 -0
- package/dist/surreal/index.spec.d.ts +2 -0
- package/dist/surreal/index.spec.d.ts.map +1 -0
- package/dist/surreal/schema.d.ts +12 -0
- package/dist/surreal/schema.d.ts.map +1 -0
- package/dist/surreal/schema.js +12 -0
- package/dist/surreal/schema.js.map +9 -0
- package/dist/tests/projectionMultiInstance.spec.d.ts +2 -0
- package/dist/tests/projectionMultiInstance.spec.d.ts.map +1 -0
- package/dist/tests/storageDriverContract.d.ts +19 -0
- package/dist/tests/storageDriverContract.d.ts.map +1 -0
- package/dist/transaction.js +1 -1
- package/dist/utils.js +6 -6
- package/dist/utils.js.map +1 -1
- package/dist/wrappedEventBuilder.js +8 -8
- package/dist/wrappedEventBuilder.js.map +1 -1
- package/package.json +19 -10
- package/src/createAggregateRoot.ts +24 -5
- package/src/createCheckpointApi.ts +98 -0
- package/src/createProcessManager.ts +7 -6
- package/src/createProjection.ts +91 -65
- package/src/lock.ts +17 -3
- package/src/memory/index.spec.ts +4 -0
- package/src/memory/index.ts +55 -29
- package/src/redis/redisLock.ts +6 -2
- package/src/surreal/index.spec.ts +152 -0
- package/src/surreal/index.ts +604 -0
- package/src/surreal/schema.ts +68 -0
- package/src/tests/aggregateRoot.spec.ts +48 -3
- package/src/tests/eventStore.spec.ts +1 -3
- package/src/tests/processManagerMultiInstance.spec.ts +18 -7
- package/src/tests/projectionMultiInstance.spec.ts +283 -0
- package/src/tests/storageDriverContract.ts +612 -0
- package/dist/chunk-2fe8jjdc.js +0 -22
- package/dist/chunk-3ejt4h7x.js.map +0 -10
- package/dist/chunk-6q8mr1sg.js +0 -13
- package/dist/chunk-6yrb30rx.js +0 -22
- package/dist/chunk-dgzw1nj9.js.map +0 -10
- package/dist/chunk-jd4q8fcf.js +0 -11
- package/dist/chunk-ty9bhdvx.js.map +0 -10
- package/dist/chunk-vep2byx4.js.map +0 -10
- package/dist/chunk-yn2sjcg3.js.map +0 -10
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/createAggregateRoot.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"import { AsyncLocalStorage } from 'node:async_hooks'\n\nimport { deepEqual } from 'fast-equals'\nimport { z } from 'zod/v4'\n\nimport type {\n EmitEvents,\n InternalAppendEvents,\n LoadEvents,\n} from './createEventStore.ts'\nimport { getProcessManagerInfo } from './createProcessManager.ts'\nimport { getProjectionInfo } from './createProjection.ts'\nimport {\n CommandError,\n ConcurrencyError,\n EventValidationError,\n InfiniteLoopError,\n ValidationError,\n} from './errors.ts'\nimport { DEFAULT_LOCK_TTL, type LockCreator } from './lock.ts'\nimport { isRefreshing } from './refresh.ts'\nimport createSnapshotGenerator, {\n type CompleteSnapshotGenerator,\n type InternalSnapshotGenerator,\n type SnapshotGenerator,\n} from './snapshotGenerator.ts'\nimport { clone } from './superjson.ts'\nimport type { Transaction, TransactionDelay } from './transaction.ts'\nimport type {\n BaseInputEvent,\n BaseOutputEvent,\n EventTemplate,\n Keys,\n MaybePromise,\n Merge,\n OutputEvents,\n Prettify,\n} from './utilityTypes.ts'\nimport { awaitAll, normalizeArray } from './utils.ts'\nimport {\n type WrappedEvent,\n type WrappedEventBuilder,\n handleEventError,\n unwrapEvent,\n wrappedEventBuilder,\n} from './wrappedEventBuilder.ts'\n\ntype UppercaseRecord<T extends Record<string, any>> = {\n [K in keyof T]: K extends Capitalize<K & string>\n ? any\n : `Error: Key '${K & string}' must be Capitalized`\n}\n\ntype BaseEventMap = Record<\n string,\n z.ZodType | (z.ZodType | { schema: z.ZodType; version: number })[]\n>\n\ntype DownstreamRootPromise = () => Promise<unknown>\nconst downstreamRootsPromiseStore = new AsyncLocalStorage<\n DownstreamRootPromise[]\n>()\n\nfunction registerRootPromiseToUpstream(rootPromise: DownstreamRootPromise) {\n downstreamRootsPromiseStore.getStore()?.push(rootPromise)\n}\n\nasync function collectDownstreamRootPromise(handler: () => Promise<void>) {\n const rootPromises: DownstreamRootPromise[] = []\n await downstreamRootsPromiseStore.run(rootPromises, handler)\n return async () => {\n await Promise.all(rootPromises.map((promise) => promise()))\n }\n}\n\ntype BaseInternalEvent<\n Type extends string,\n Version extends number,\n Payload = unknown,\n> = BaseOutputEvent<Type, Version, Payload>\n\ntype InternalEvent<Event extends EventTemplate> = Prettify<\n {\n [K in Event as K['version']]: Omit<\n BaseInternalEvent<K['type'], K['version'], z.output<K['schema']>>,\n 'createdAt' | 'position' | 'streamVersion'\n > & {\n // only set when folding persisted events (stream loading/replay);\n // events yielded by a command fold before they are appended and have\n // no position yet\n position?: number\n }\n }[Event['version']]\n>\n\ntype InternalEventHandlers<Events extends EventTemplate> = {\n [K in Events as `on${K['type']}`]?: (\n event: InternalEvent<K>,\n ) => MaybePromise<void>\n}\n\ntype EventsFromMap<EventMap extends BaseEventMap> = Prettify<\n {\n [K in keyof EventMap]: { type: K & string } & (EventMap[K] extends z.ZodType\n ? { schema: EventMap[K]; version: 0 }\n : EventMap[K] extends { schema: infer S; version: infer V }\n ? S extends z.ZodType\n ? { schema: S; version: V }\n : never\n : EventMap[K] extends Array<infer I>\n ? I extends z.ZodType\n ? { schema: I; version: 0 }\n : I extends { schema: infer S; version: infer V }\n ? { schema: S; version: V }\n : never\n : never)\n }[keyof EventMap]\n>\n\ntype Constructor<T> = new (...args: any[]) => T\n\ntype Command = (\n ...args: any[]\n) =>\n | MaybePromise<void | WrappedEvent | WrappedEvent[]>\n | Iterable<WrappedEvent>\n | AsyncIterable<WrappedEvent>\n\ntype Utils = {\n reset: () => void\n replayUntil: (streamVersion: number) => Promise<void>\n}\n\ntype VersionBuilder = <V extends number, S extends z.ZodType>(\n version: V,\n schema: S,\n) => { schema: S; version: V }\n\n/**\n * Options for {@link Stream.settled}.\n *\n * `maxRetries` — how many times to reload the stream and re-apply the dispatched\n * commands when the append loses the optimistic-concurrency race\n * ({@link ConcurrencyError}). Defaults to `0` (no retry — surface the error, the\n * historical behaviour). Only the append is retried; command handlers must be\n * pure functions of loaded state and their arguments for retries to be safe.\n */\nexport type SettledOptions = {\n maxRetries?: number\n}\n\ntype Stream<Commands extends Record<string, Command>, State> = {\n [A in keyof Commands]: (\n ...args: Parameters<Commands[A]>\n ) => Stream<Commands, State>\n} & {\n settled: (options?: SettledOptions) => Promise<Stream<Commands, State>>\n state: () => Promise<State>\n transformError: <T extends Error>(\n error: Constructor<T>,\n errorHandler: (commandError: CommandError<T>) => Error,\n ) => Stream<Commands, State>\n readonly streamId: string\n}\n\nexport type AnyStream = {\n settled: (options?: SettledOptions) => Promise<AnyStream>\n state: () => Promise<unknown>\n transformError: <T extends Error>(\n error: Constructor<T>,\n errorHandler: (error: CommandError<T>) => Error,\n ) => AnyStream\n}\n\nexport type AnyAggregateRoot = {\n type: string\n loadStream: (\n id: string,\n filter?: (event: BaseOutputEvent) => MaybePromise<boolean>,\n ) => AnyStream\n newStream: () => AnyStream\n $inferState: any\n $inferEvents: any\n $inferEvent: any\n $inferCommandParameters: any\n}\n\ntype EventHandlerOptions = {\n streamId: string\n extendLock: (ms?: number) => Promise<boolean>\n}\n\nexport type AggregateRootApi<\n Name,\n State = never,\n Events extends EventTemplate = never,\n Commands extends Record<string, Command> = Record<string, Command>,\n Flags extends {\n withInitialState: boolean\n withEvents: boolean\n withCommands: boolean\n withEventHandlers: boolean\n withSnapshots: boolean\n } = {\n withInitialState: false\n withEvents: false\n withCommands: true\n withEventHandlers: true\n withSnapshots: false\n },\n> = {\n withInitialState: <NextState extends Record<string, unknown>>(\n state: NextState,\n ) => Omit<\n AggregateRootApi<\n Name,\n NextState,\n Events,\n Commands,\n Merge<Flags, { withInitialState: true; withEventHandlers: false }>\n >,\n Keys<Merge<Flags, { withInitialState: true; withEventHandlers: false }>>\n >\n withCommands: <\n NextCommands extends Record<\n Exclude<string, 'state' | 'settled' | 'transformError' | 'streamId'>,\n Command\n >,\n >(\n handlers: [State] extends [never]\n ? (\n event: WrappedEventBuilder<Events>,\n options: EventHandlerOptions,\n ) => NextCommands\n : (\n state: Readonly<State>,\n event: WrappedEventBuilder<Events>,\n options: EventHandlerOptions,\n ) => NextCommands,\n ) => Omit<\n AggregateRootApi<\n Name,\n State,\n Events,\n NextCommands,\n Merge<\n Flags,\n { withInitialState: true; withCommands: true; withEvents: true }\n >\n >,\n Keys<\n Merge<\n Flags,\n { withInitialState: true; withCommands: true; withEvents: true }\n >\n >\n >\n withEvents: {\n <EventMap extends BaseEventMap>(\n handler: EventMap & UppercaseRecord<EventMap>,\n ): Omit<\n AggregateRootApi<\n Name,\n State,\n EventsFromMap<EventMap>,\n Commands,\n Merge<\n Flags,\n {\n withInitialState: true\n withEvents: true\n withCommands: false\n }\n >\n >,\n Keys<\n Merge<\n Flags,\n {\n withInitialState: true\n withEvents: true\n withCommands: false\n }\n >\n >\n >\n <EventMap extends BaseEventMap>(\n handler: (utils: {\n version: VersionBuilder\n z: typeof z\n }) => EventMap & UppercaseRecord<EventMap>,\n ): Omit<\n AggregateRootApi<\n Name,\n State,\n EventsFromMap<EventMap>,\n Commands,\n Merge<\n Flags,\n {\n withInitialState: true\n withEvents: true\n withCommands: false\n }\n >\n >,\n Keys<\n Merge<\n Flags,\n {\n withInitialState: true\n withEvents: true\n withCommands: false\n }\n >\n >\n >\n }\n withEventHandlers: (\n handler: (state: State, utils: Utils) => InternalEventHandlers<Events>,\n ) => Omit<\n AggregateRootApi<\n Name,\n State,\n Events,\n Commands,\n Merge<\n Flags,\n { withInitialState: true; withEventHandlers: true; withEvents: true }\n >\n >,\n Keys<\n Merge<\n Flags,\n { withInitialState: true; withEventHandlers: true; withEvents: true }\n >\n >\n >\n withSnapshots: (\n handler: (\n state: State,\n generate: SnapshotGenerator<Omit<Snapshot, 'schemaVersion' | 'state'>>,\n utils: { z: typeof z },\n ) => CompleteSnapshotGenerator,\n ) => Omit<\n AggregateRootApi<\n Name,\n State,\n Events,\n Commands,\n Merge<Flags, { withSnapshots: true }>\n >,\n Keys<Merge<Flags, { withSnapshots: true }>>\n >\n loadStream: (\n id: string,\n filter?: (event: OutputEvents<Events>) => MaybePromise<boolean>,\n ) => Stream<Commands, State>\n newStream: (id?: string) => Stream<Commands, State>\n\n $inferEvents: OutputEvents<Events>\n $inferEvent: OutputEvents<Events> extends BaseOutputEvent\n ? { [E in OutputEvents<Events> as E['type']]: E }\n : never\n $inferState: State\n $inferCommandParameters: {\n [CommandName in keyof Commands]: Parameters<Commands[CommandName]>\n }\n readonly type: Name\n}\n\nexport type InternalAggregateRootApi = {\n linkEventStore: (\n loadEvents: LoadEvents,\n appendEvents: InternalAppendEvents,\n emitEvents: EmitEvents,\n transaction: Transaction,\n lock: LockCreator,\n snapshots?: AggregateRootSnapshotMethods,\n ) => void\n eventTypes: string[]\n readonly type: string\n}\n\nconst snapshotSchema = z.object({\n streamId: z.string(),\n schemaVersion: z.int(),\n state: z.unknown(),\n createdAt: z.date(),\n streamVersion: z.int(),\n streamType: z.string(),\n lastEventPosition: z.int(),\n metadata: z.record(z.string(), z.unknown()).optional(),\n})\n\nexport type Snapshot = z.output<typeof snapshotSchema>\n\nexport type AggregateRootSnapshotMethods = {\n get: (select: {\n stream: string\n id: string\n }) => MaybePromise<Snapshot | null | undefined>\n put: (snapshot: Snapshot) => MaybePromise<void>\n delete: (\n target: {\n stream: string\n id: string\n },\n fromPosition: number,\n ) => MaybePromise<void>\n}\n\nexport function createAggregateRoot<Name extends string>(type: Name) {\n let initialState: any = null\n let createEventHandlers: (\n state: any,\n ) => InternalEventHandlers<any> = () => ({})\n\n let loadEvents!: LoadEvents\n let appendEvents!: InternalAppendEvents\n let emitEvents!: EmitEvents\n let snapshots: AggregateRootSnapshotMethods | undefined\n let createLock!: LockCreator\n let transaction!: Transaction\n\n let createCommands: (\n state: any,\n eventBuilder: (name: string, payload: unknown) => WrappedEvent,\n options: EventHandlerOptions,\n ) => Record<string, Command> = () => ({})\n\n const registeredEvents = new Map<string, Map<number, z.ZodType>>()\n let createSnapshotApi:\n | ((\n state: any,\n generate: SnapshotGenerator<any>,\n utils: { z: typeof z },\n ) => CompleteSnapshotGenerator & InternalSnapshotGenerator)\n | null = null\n\n const loadUntil = async (\n state: any,\n snapshotApi:\n | (CompleteSnapshotGenerator & InternalSnapshotGenerator)\n | undefined,\n id: string,\n untilPosition?: number,\n filter?: (event: BaseOutputEvent) => MaybePromise<boolean>,\n ) => {\n let position = 0\n let version = 0\n if (snapshotApi) {\n const snapshot = await snapshots?.get({\n stream: type,\n id,\n })\n if (snapshot) {\n const result = snapshotSchema.safeParse(snapshot)\n\n if (!result.success) {\n throw new ValidationError(\n 'loaded aggregate root snapshot does not comply with schema',\n result.error,\n )\n }\n\n snapshotApi.internalApply(result.data)\n position = snapshot.lastEventPosition\n version = snapshot.streamVersion\n }\n }\n\n const events = loadEvents(\n { stream: type, id },\n {\n from: position,\n to: untilPosition,\n },\n )\n const eventHandlers = createEventHandlers(state)\n for await (const event of events) {\n version += 1\n if ((await filter?.(event)) === false) {\n continue\n }\n await (eventHandlers as any)[`on${event.type}`]?.(event)\n }\n\n return version\n }\n\n // A command as dispatched by the caller, recorded so it can be re-applied\n // against a freshly-loaded stream when a settle() retries a ConcurrencyError.\n type RecordedCommand = { name: string; args: any[] }\n\n type CreateStreamConfig = {\n // Whether to load the existing stream before commands run. `false` for\n // newStream (expects version 0); `true` for loadStream and every retry.\n load?: boolean\n filter?: (event: BaseOutputEvent) => MaybePromise<boolean>\n // Seeded on a retry so replayed commands re-apply automatically, and\n // transformError handlers registered before settle() carry over.\n replayCommands?: RecordedCommand[]\n errorHandlerEntries?: [\n Constructor<Error>,\n (error: CommandError<Error>) => Error,\n ][]\n }\n\n const createStream = (\n state: any,\n streamId: string,\n config: CreateStreamConfig = {},\n ) => {\n // Captured at the dispatch site so a settle() retry can re-apply the\n // commands within the same AsyncLocalStorage state (user metadata scopes,\n // process-manager info, …) that the original attempt observed.\n const dispatchContext = AsyncLocalStorage.snapshot()\n let version = 0\n const snapshotApi = createSnapshotApi?.(\n state,\n createSnapshotGenerator() as any,\n { z },\n )\n const errorHandlers = new Map<\n Constructor<Error>,\n (error: CommandError<Error>) => Error\n >(config.errorHandlerEntries)\n const dispatchedCommands: RecordedCommand[] = []\n let downstreamSettledPromise = () => Promise.resolve()\n let releaseLock!: () => Promise<void>\n let extendLock!: EventHandlerOptions['extendLock']\n let lockTtl: number | undefined\n\n const warnReleaseLock = () => {\n if (releasedAfterChain) {\n console.warn(`aggregate root for ${type}:${streamId} was open too long`)\n }\n releaseLock()\n }\n\n const processEvents = async (events: BaseInputEvent[]) => {\n if (!appendEvents) {\n throw new Error(\n `aggregate root ${type} is not linked to an event store`,\n )\n }\n\n const persistedEvents = await appendEvents(\n { stream: type, id: streamId },\n events,\n version,\n )\n\n warnReleaseLock()\n\n for (const persistedEvent of persistedEvents) {\n const snapshot = await snapshotApi?.internalCapture(\n persistedEvent,\n persistedEvent.streamVersion,\n )\n\n if (snapshot) {\n await snapshots?.put({\n state: snapshot.state,\n lastEventPosition: persistedEvent.position,\n streamId,\n streamVersion: version,\n streamType: type,\n schemaVersion: snapshot.version,\n createdAt: new Date(),\n })\n }\n }\n\n version += events.length\n\n downstreamSettledPromise = await collectDownstreamRootPromise(() =>\n emitEvents(persistedEvents),\n )\n }\n\n let commandChain = createLock([type, streamId]).then((lock) => {\n releaseLock = lock.release\n extendLock = lock.extend\n lockTtl = lock.ttl\n return [] as Error | BaseInputEvent[]\n })\n\n // A replay is the library's own work and takes as long as the stream is\n // long, so unlike a slow command it must not cost the caller the lock.\n // Extended on a timer while it runs, and never past it: a lock nobody\n // releases still expires.\n const keepLockAlive = async <T>(work: () => Promise<T>) => {\n const timer = setInterval(\n () => void extendLock().catch(() => false),\n (lockTtl ?? DEFAULT_LOCK_TTL) / 4,\n )\n try {\n return await work()\n } finally {\n clearInterval(timer)\n }\n }\n let commandChainTouched = false\n let releasedAfterChain = false\n let transactionDelay: TransactionDelay | undefined\n\n const stateReady = Promise.withResolvers<Error | undefined>()\n\n const rawCommands = createCommands(state, wrappedEventBuilder, {\n streamId,\n extendLock,\n })\n\n const commands = Object.fromEntries(\n Object.entries(rawCommands).map(([commandName, commandFn]) => [\n commandName,\n (...args: any[]) => {\n // don't create new events when refreshing the process manager\n if (isRefreshing()) {\n return api.commands\n }\n\n // Record for a potential settle() retry (reload + re-apply).\n dispatchedCommands.push({ name: commandName, args })\n\n const commandId = crypto.randomUUID()\n transactionDelay ??= transaction.delay()\n commandChainTouched = true\n commandChain = commandChain\n .then(async (previousEvents) => {\n if (previousEvents instanceof Error) {\n return previousEvents\n }\n const events = (\n await normalizeArray(commandFn.apply(rawCommands, args), () =>\n extendLock(),\n )\n ).filter((event) => Boolean(event))\n\n const baseInputEvents = await Promise.all(\n events.map(async (event) => {\n event.withAdditionalMetadata({ commandName })\n event.withDefaultCausationId(commandId)\n\n const unwrappedEvent = unwrapEvent(event)\n\n const eventVersions = registeredEvents.get(\n unwrappedEvent.type,\n )\n if (!eventVersions) {\n throw new Error(\n `cannot append unknown event ${unwrappedEvent.type}`,\n )\n }\n const latestVersion = Math.max(\n ...Array.from(eventVersions.keys()),\n )\n const schema = eventVersions.get(latestVersion)!\n\n const result = schema.safeParse(unwrappedEvent.payload)\n if (!result.success) {\n const error = new EventValidationError(\n `payload does not comply with schema for event ${unwrappedEvent.type}@${latestVersion} at stream ${streamId}`,\n result.error,\n )\n\n await handleEventError(event, error)\n throw error\n }\n\n unwrappedEvent.payload = result.data\n\n return {\n ...unwrappedEvent,\n schemaVersion: latestVersion,\n }\n }),\n )\n\n const eventHandlers = createEventHandlers(state)\n for (const event of baseInputEvents) {\n const processManagerInfo = getProcessManagerInfo()\n if (processManagerInfo) {\n if (\n processManagerInfo.event.streamId === streamId &&\n processManagerInfo.event.streamType === type &&\n processManagerInfo.event.type === event.type &&\n deepEqual(processManagerInfo.event.payload, event.payload)\n ) {\n return new InfiniteLoopError(\n `Infinite loop detected. Process Manager \"${processManagerInfo.name}\" listens and emits same event \"${event.type}\" for stream ${type}:${streamId}, causing a recurring event cycle`,\n )\n }\n }\n\n await eventHandlers[`on${event.type}`]?.({\n ...event,\n streamId,\n streamType: type,\n })\n }\n\n return [...previousEvents, ...baseInputEvents]\n })\n .catch((error) => {\n if (!(error instanceof Error)) {\n throw error\n }\n\n const commandError = new CommandError(\n type,\n commandName,\n streamId,\n error,\n )\n for (const [ErrorType, handler] of errorHandlers) {\n if (error instanceof ErrorType) {\n return new CommandError(\n type,\n commandName,\n streamId,\n handler(commandError),\n )\n }\n }\n\n return commandError\n })\n\n const currentCommandChain = commandChain\n currentCommandChain.then(async (allEvents) => {\n if (\n // we are the last command\n currentCommandChain === commandChain\n ) {\n stateReady.resolve(\n allEvents instanceof Error ? allEvents : undefined,\n )\n\n commandChain = commandChain.then(async () => {\n // no Error in chain\n if (Array.isArray(allEvents)) {\n transactionDelay?.resolve()\n try {\n await transactionDelay?.commit()\n } catch (error) {\n if (error instanceof Error) {\n warnReleaseLock()\n return error\n }\n }\n\n await processEvents(allEvents)\n return []\n }\n\n warnReleaseLock()\n transactionDelay?.reject(allEvents)\n if (transaction.active) {\n return []\n }\n\n throw allEvents\n })\n }\n })\n\n return api.commands\n },\n ]),\n )\n\n setImmediate(() => {\n if (!commandChainTouched) {\n releasedAfterChain = true\n commandChain = commandChain.then((v) => {\n releaseLock()\n return v\n })\n }\n })\n\n const api = {\n load(filter?: (event: BaseOutputEvent) => MaybePromise<boolean>) {\n // ensure commands are executed after load is finished\n commandChain = commandChain\n .then(() =>\n keepLockAlive(() =>\n loadUntil(state, snapshotApi, streamId, undefined, filter),\n ),\n )\n .then((loadedVersion) => {\n version = loadedVersion\n return []\n })\n },\n commands: {\n ...commands,\n async state() {\n const maybeError = await Promise.race([\n stateReady.promise,\n awaitAll(() => commandChain),\n ])\n\n if (maybeError) {\n throw maybeError\n }\n\n return state\n },\n async settled(options?: SettledOptions): Promise<any> {\n const parentProcessManager = getProcessManagerInfo()\n if (parentProcessManager) {\n const error = new Error(\n `aggregateRoot.settled() cannot be called inside a process manager. Attempted on aggregate stream \"${type}\" within Process Manager ${parentProcessManager.name}. To configure how dispatched streams settle, pass options to createProcessManager(name, { settled }).`,\n )\n commandChain = commandChain.then(() => error)\n throw error\n }\n\n if (transaction.active) {\n const error = new Error(\n `aggregateRoot.settled() cannot be called inside a transaction. Attempted on aggregate stream \"${type}\". To configure how dispatched streams settle, pass options to transaction(handler, { settled }).`,\n )\n commandChain = commandChain.then(() => error)\n throw error\n }\n\n const maxRetries = options?.maxRetries ?? 0\n\n try {\n await awaitAll(() => commandChain)\n } catch (error) {\n // Optimistic-concurrency recovery: another writer advanced the\n // stream between load and append. Reload and re-apply the same\n // commands against the fresh version. A failed append leaves this\n // attempt's lock held (it never reached releaseLock), so release it\n // before the retry re-acquires — otherwise the retry blocks until\n // the lock's TTL lapses.\n if (maxRetries > 0 && error instanceof ConcurrencyError) {\n await releaseLock?.()\n\n // Re-create the stream within the async context captured at the\n // dispatch site, so the replayed commands and event\n // post-processing observe the same AsyncLocalStorage state as\n // the original attempt. Two scopes are explicitly exited: the\n // transaction (the first attempt already passed its commit gate;\n // re-entering the committed store would swallow errors and\n // register dead delays) and the upstream collection (this retry\n // is settled right here, not through another auto-settle\n // registration).\n const retryStream = dispatchContext(() =>\n transaction.exit(() =>\n downstreamRootsPromiseStore.exit(() =>\n createStream(clone(initialState), streamId, {\n load: true,\n filter: config.filter,\n replayCommands: dispatchedCommands,\n errorHandlerEntries: Array.from(errorHandlers),\n }),\n ),\n ),\n )\n\n return retryStream.commands.settled({\n ...options,\n maxRetries: maxRetries - 1,\n })\n }\n\n throw error\n }\n\n await downstreamSettledPromise()\n return api.commands\n },\n transformError(\n error: Constructor<Error>,\n handler: (error: Error) => never,\n ) {\n errorHandlers.set(error, handler)\n return api.commands\n },\n streamId,\n },\n }\n\n // Streams dispatched inside a process manager or a transaction cannot\n // call settled() themselves — the surrounding scope settles them when it\n // completes. Capture the defaults declared on that scope\n // (createProcessManager / transaction options) so the auto-settle\n // inherits them.\n const autoSettleOptions =\n getProcessManagerInfo()?.settledDefaults ?? transaction.settledDefaults\n\n registerRootPromiseToUpstream(() => api.commands.settled(autoSettleOptions))\n transaction.after(() => api.commands.settled(autoSettleOptions))\n\n // Fold existing events before commands run (loadStream, and every retry).\n if (config.load) {\n api.load(config.filter)\n }\n\n // Re-apply the caller's commands on a retry so the fresh, reloaded stream\n // reproduces the original intent against the current version.\n for (const { name, args } of config.replayCommands ?? []) {\n ;(api.commands as any)[name](...args)\n }\n\n return api\n }\n\n const api: AggregateRootApi<Name> & InternalAggregateRootApi = {\n type,\n withInitialState: (state) => {\n initialState = clone(state)\n return api as any\n },\n\n withCommands(handlers) {\n createCommands = (state, eventBuilder, options) => {\n if (state === null) {\n return (handlers as any)(eventBuilder, options)\n }\n\n return (handlers as any)(state, eventBuilder, options)\n }\n\n return api as any\n },\n\n withEvents(handler) {\n const eventMap: BaseEventMap =\n typeof handler === 'function'\n ? handler({ version: (version, schema) => ({ version, schema }), z })\n : handler\n\n for (const [type, config] of Object.entries(eventMap)) {\n const versions = Array.isArray(config) ? config : [config]\n for (const v of versions) {\n let schema: z.ZodType\n let version: number\n if (typeof v === 'object' && 'version' in v) {\n schema = v.schema\n version = v.version\n } else {\n schema = v\n version = 0\n }\n\n if (registeredEvents.get(type)?.has(version)) {\n throw new Error(\n `event ${type} is already registered in version ${version}`,\n )\n }\n\n if (!registeredEvents.has(type)) {\n registeredEvents.set(type, new Map())\n }\n registeredEvents.get(type)!.set(version, schema)\n }\n }\n return api as any\n },\n\n withEventHandlers(handler) {\n createEventHandlers = handler as any\n return api as any\n },\n\n withSnapshots: (handler) => {\n createSnapshotApi = handler as any\n return api as any\n },\n\n newStream(id) {\n if (!loadEvents) {\n throw new Error(\n `aggregate root ${type} is not linked to an event store`,\n )\n }\n\n const parentProjectionName = getProjectionInfo()?.name\n if (parentProjectionName) {\n throw new Error(\n `aggregateRoot.newStream() cannot be called inside a projection. Attempted on aggregate stream ${type} within Projection ${parentProjectionName}.`,\n )\n }\n return createStream(clone(initialState), id ?? crypto.randomUUID(), {\n load: false,\n }).commands as any\n },\n\n loadStream(id, filter) {\n if (!loadEvents) {\n throw new Error(\n `aggregate root ${type} is not linked to an event store`,\n )\n }\n\n const parentProjectionName = getProjectionInfo()?.name\n if (parentProjectionName) {\n throw new Error(\n `aggregateRoot.loadStream(\"${id}\") cannot be called inside a projection. Attempted on aggregate stream ${type} within Projection ${parentProjectionName}.`,\n )\n }\n return createStream(clone(initialState), id, {\n load: true,\n filter: filter as any,\n }).commands as any\n },\n\n linkEventStore(load, append, emit, trans, lock, snap) {\n loadEvents = load\n appendEvents = append\n emitEvents = emit\n transaction = trans\n createLock = lock\n snapshots = snap\n },\n get eventTypes() {\n return Array.from(registeredEvents.keys())\n },\n $inferEvents: null as never,\n $inferEvent: null as never,\n $inferState: null as never,\n $inferCommandParameters: null as never,\n }\n\n return api as Omit<\n AggregateRootApi<Name>,\n 'withCommands' | 'withEventHandlers'\n >\n}\n"
|
|
6
|
+
],
|
|
7
|
+
"mappings": "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",
|
|
8
|
+
"debugId": "3DB62A08BB7BF61F64756E2164756E21",
|
|
9
|
+
"names": []
|
|
10
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// src/superjson.ts
|
|
2
|
+
import SuperJSON from "superjson";
|
|
3
|
+
var superjson2 = new SuperJSON;
|
|
4
|
+
function extendTypes2(handler) {
|
|
5
|
+
handler(superjson2);
|
|
6
|
+
}
|
|
7
|
+
function clone2(obj) {
|
|
8
|
+
return superjson2.deserialize(superjson2.serialize(obj));
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export { superjson2, extendTypes2, clone2 };
|
|
12
|
+
|
|
13
|
+
//# debugId=3B62D845BB126E8B64756E2164756E21
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"sourcesContent": [
|
|
5
5
|
"import SuperJSON from 'superjson'\n\nexport const superjson = new SuperJSON()\n\nexport function extendTypes(handler: (superjson: SuperJSON) => void) {\n handler(superjson)\n}\n\nexport function clone<T>(obj: T): T {\n return superjson.deserialize(superjson.serialize(obj))\n}\n"
|
|
6
6
|
],
|
|
7
|
-
"mappings": ";AAAA;AAEO,IAAM,
|
|
8
|
-
"debugId": "
|
|
7
|
+
"mappings": ";AAAA;AAEO,IAAM,aAAY,IAAI;AAEtB,SAAS,YAAW,CAAC,SAAyC;AAAA,EACnE,QAAQ,UAAS;AAAA;AAGZ,SAAS,MAAQ,CAAC,KAAW;AAAA,EAClC,OAAO,WAAU,YAAY,WAAU,UAAU,GAAG,CAAC;AAAA;",
|
|
8
|
+
"debugId": "3B62D845BB126E8B64756E2164756E21",
|
|
9
9
|
"names": []
|
|
10
10
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
} from "./chunk-
|
|
2
|
+
ValidationError2
|
|
3
|
+
} from "./chunk-jw9e0fr0.js";
|
|
4
4
|
|
|
5
5
|
// src/snapshotGenerator.ts
|
|
6
6
|
import { z } from "zod/v4";
|
|
@@ -9,7 +9,7 @@ function createSnapshotGenerator(schemas = [], config = null, applier = null, ca
|
|
|
9
9
|
async internalApply(snapshot) {
|
|
10
10
|
const result = z.union(schemas.map(({ schema }) => schema)).safeParse(snapshot.state);
|
|
11
11
|
if (!result.success) {
|
|
12
|
-
throw new
|
|
12
|
+
throw new ValidationError2(`loaded snapshot version ${snapshot.schemaVersion} does not comply with registered schema`, result.error);
|
|
13
13
|
}
|
|
14
14
|
await applier(snapshot);
|
|
15
15
|
},
|
|
@@ -20,7 +20,7 @@ function createSnapshotGenerator(schemas = [], config = null, applier = null, ca
|
|
|
20
20
|
const latestSchema = schemas.slice(1).reduce((latest, schema) => schema.schemaVersion > latest.schemaVersion ? schema : latest, schemas[0]);
|
|
21
21
|
const result = latestSchema.schema.safeParse(await capturer(event));
|
|
22
22
|
if (!result.success) {
|
|
23
|
-
throw new
|
|
23
|
+
throw new ValidationError2(`generated snapshot does not comply with schema for version ${latestSchema.schemaVersion}`, result.error);
|
|
24
24
|
}
|
|
25
25
|
return {
|
|
26
26
|
state: result.data,
|
|
@@ -34,11 +34,11 @@ function createSnapshotGenerator(schemas = [], config = null, applier = null, ca
|
|
|
34
34
|
schemas.push({ schemaVersion: schemaVersion ?? 0, schema });
|
|
35
35
|
return createSnapshotGenerator(schemas, config, null, null);
|
|
36
36
|
},
|
|
37
|
-
apply(
|
|
38
|
-
return createSnapshotGenerator(schemas, config,
|
|
37
|
+
apply(applier) {
|
|
38
|
+
return createSnapshotGenerator(schemas, config, applier, capturer);
|
|
39
39
|
},
|
|
40
|
-
capture(
|
|
41
|
-
return createSnapshotGenerator(schemas, config, applier,
|
|
40
|
+
capture(capturer) {
|
|
41
|
+
return createSnapshotGenerator(schemas, config, applier, capturer);
|
|
42
42
|
},
|
|
43
43
|
complete: true
|
|
44
44
|
};
|
|
@@ -46,4 +46,4 @@ function createSnapshotGenerator(schemas = [], config = null, applier = null, ca
|
|
|
46
46
|
|
|
47
47
|
export { createSnapshotGenerator };
|
|
48
48
|
|
|
49
|
-
//# debugId=
|
|
49
|
+
//# debugId=CB4E2325706333DE64756E2164756E21
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"sourcesContent": [
|
|
5
5
|
"import { z } from 'zod/v4'\n\nimport { ValidationError } from './errors.ts'\nimport type {\n BaseOutputEvent,\n Keys,\n Max,\n MaybePromise,\n Merge,\n} from './utilityTypes.js'\n\ntype RegisteredSnapshotSchemas = { schemaVersion: number; schema: z.ZodType }\n\ntype LatestSnapshotSchemaInput<\n T extends RegisteredSnapshotSchemas,\n M = Max<T['schemaVersion']>,\n> = T extends { schemaVersion: M } ? z.input<T['schema']> : never\n\ntype OutputSnapshot<T extends RegisteredSnapshotSchemas> = T extends {\n schemaVersion: infer V\n schema: infer S\n}\n ? {\n schemaVersion: V\n state: z.output<S>\n createdAt: Date\n }\n : never\n\ntype SnapshotApplier<Base, T extends RegisteredSnapshotSchemas> = (\n snapshot: OutputSnapshot<T> & Base,\n) => MaybePromise<void>\ntype SnapshotCapturer<T extends RegisteredSnapshotSchemas> = (\n event: BaseOutputEvent,\n) => MaybePromise<LatestSnapshotSchemaInput<T> | undefined | null | void>\n\nexport type SnapshotGenerator<\n Base,\n Schemas extends RegisteredSnapshotSchemas = never,\n Flags extends {\n every: boolean\n apply: boolean\n capture: boolean\n schema: boolean\n } = {\n every: false\n apply: true\n capture: true\n schema: false\n },\n> = {\n every(\n count: number,\n ): Omit<\n SnapshotGenerator<Base, Schemas, Merge<Flags, { every: true }>>,\n Keys<Merge<Flags, { every: true }>>\n >\n schema<Schema extends z.ZodType, V extends number = 0>(\n schema: Schema,\n schemaVersion?: V,\n ): Omit<\n SnapshotGenerator<\n Base,\n Schemas | { schemaVersion: V; schema: Schema },\n Merge<Flags, { apply: false; capture: false }>\n >,\n Keys<Merge<Flags, { apply: false; capture: false }>>\n >\n apply(\n applier: SnapshotApplier<Base, Schemas>,\n ): Omit<\n SnapshotGenerator<\n Base,\n Schemas,\n Merge<Flags, { apply: true; schema: true }>\n >,\n Keys<Merge<Flags, { apply: true; schema: true }>>\n >\n capture(\n capturer: SnapshotCapturer<Schemas>,\n ): Omit<\n SnapshotGenerator<\n Base,\n Schemas,\n Merge<Flags, { capture: true; schema: true }>\n >,\n Keys<Merge<Flags, { capture: true; schema: true }>>\n >\n readonly complete: Flags['schema'] extends true\n ? Flags['capture'] extends true\n ? Flags['apply'] extends true\n ? true\n : false\n : false\n : false\n}\n\nexport type InternalSnapshotGenerator = {\n internalApply: (snapshot: OutputSnapshot<any>) => Promise<void>\n internalCapture: (\n event: BaseOutputEvent,\n applied: number,\n ) => Promise<null | { state: any; version: number }>\n}\n\nexport type CompleteSnapshotGenerator = Omit<\n SnapshotGenerator<\n any,\n RegisteredSnapshotSchemas,\n { every: true; apply: true; capture: true; schema: true }\n >,\n 'schema' | 'capture' | 'apply' | 'every'\n>\n\nexport default function createSnapshotGenerator<Base>(\n schemas: Array<RegisteredSnapshotSchemas> = [],\n config: { every: number } | null = null,\n applier:\n | ((snapshot: OutputSnapshot<any>) => MaybePromise<void>)\n | null = null,\n capturer: ((event: BaseOutputEvent) => any) | null = null,\n): CompleteSnapshotGenerator {\n return {\n async internalApply(snapshot) {\n const result = z\n .union(schemas.map(({ schema }) => schema))\n .safeParse(snapshot.state)\n\n if (!result.success) {\n throw new ValidationError(\n `loaded snapshot version ${snapshot.schemaVersion} does not comply with registered schema`,\n result.error,\n )\n }\n\n await applier!(snapshot)\n },\n async internalCapture(event, applied) {\n if (!config || applied % config.every !== 0) {\n return null\n }\n\n const latestSchema = schemas\n .slice(1)\n .reduce(\n (latest, schema) =>\n schema.schemaVersion > latest.schemaVersion ? schema : latest,\n schemas[0],\n )\n\n const result = latestSchema.schema.safeParse(await capturer!(event))\n\n if (!result.success) {\n throw new ValidationError(\n `generated snapshot does not comply with schema for version ${latestSchema.schemaVersion}`,\n result.error,\n )\n }\n\n return {\n state: result.data,\n version: latestSchema.schemaVersion,\n }\n },\n every(count) {\n return createSnapshotGenerator(\n schemas,\n { every: count },\n applier,\n capturer,\n )\n },\n schema(schema, schemaVersion) {\n schemas.push({ schemaVersion: schemaVersion ?? 0, schema })\n return createSnapshotGenerator(schemas, config, null, null) as any\n },\n apply(applier) {\n return createSnapshotGenerator(schemas, config, applier as any, capturer)\n },\n capture(capturer) {\n return createSnapshotGenerator(schemas, config, applier, capturer as any)\n },\n complete: true,\n } as SnapshotGenerator<\n Base,\n RegisteredSnapshotSchemas,\n { capture: true; apply: true; every: true; schema: true }\n > &\n InternalSnapshotGenerator\n}\n"
|
|
6
6
|
],
|
|
7
|
-
"mappings": ";;;;;AAAA;AAkHA,SAAwB,uBAA6B,CACnD,UAA4C,CAAC,GAC7C,SAAmC,MACnC,UAEW,MACX,WAAqD,MAC1B;AAAA,EAC3B,OAAO;AAAA,SACC,cAAa,CAAC,UAAU;AAAA,MAC5B,MAAM,SAAS,EACZ,MAAM,QAAQ,IAAI,GAAG,aAAa,MAAM,CAAC,EACzC,UAAU,SAAS,KAAK;AAAA,MAE3B,IAAI,CAAC,OAAO,SAAS;AAAA,QACnB,MAAM,IAAI,
|
|
8
|
-
"debugId": "
|
|
7
|
+
"mappings": ";;;;;AAAA;AAkHA,SAAwB,uBAA6B,CACnD,UAA4C,CAAC,GAC7C,SAAmC,MACnC,UAEW,MACX,WAAqD,MAC1B;AAAA,EAC3B,OAAO;AAAA,SACC,cAAa,CAAC,UAAU;AAAA,MAC5B,MAAM,SAAS,EACZ,MAAM,QAAQ,IAAI,GAAG,aAAa,MAAM,CAAC,EACzC,UAAU,SAAS,KAAK;AAAA,MAE3B,IAAI,CAAC,OAAO,SAAS;AAAA,QACnB,MAAM,IAAI,iBACR,2BAA2B,SAAS,wDACpC,OAAO,KACT;AAAA,MACF;AAAA,MAEA,MAAM,QAAS,QAAQ;AAAA;AAAA,SAEnB,gBAAe,CAAC,OAAO,SAAS;AAAA,MACpC,IAAI,CAAC,UAAU,UAAU,OAAO,UAAU,GAAG;AAAA,QAC3C,OAAO;AAAA,MACT;AAAA,MAEA,MAAM,eAAe,QAClB,MAAM,CAAC,EACP,OACC,CAAC,QAAQ,WACP,OAAO,gBAAgB,OAAO,gBAAgB,SAAS,QACzD,QAAQ,EACV;AAAA,MAEF,MAAM,SAAS,aAAa,OAAO,UAAU,MAAM,SAAU,KAAK,CAAC;AAAA,MAEnE,IAAI,CAAC,OAAO,SAAS;AAAA,QACnB,MAAM,IAAI,iBACR,8DAA8D,aAAa,iBAC3E,OAAO,KACT;AAAA,MACF;AAAA,MAEA,OAAO;AAAA,QACL,OAAO,OAAO;AAAA,QACd,SAAS,aAAa;AAAA,MACxB;AAAA;AAAA,IAEF,KAAK,CAAC,OAAO;AAAA,MACX,OAAO,wBACL,SACA,EAAE,OAAO,MAAM,GACf,SACA,QACF;AAAA;AAAA,IAEF,MAAM,CAAC,QAAQ,eAAe;AAAA,MAC5B,QAAQ,KAAK,EAAE,eAAe,iBAAiB,GAAG,OAAO,CAAC;AAAA,MAC1D,OAAO,wBAAwB,SAAS,QAAQ,MAAM,IAAI;AAAA;AAAA,IAE5D,KAAK,CAAC,SAAS;AAAA,MACb,OAAO,wBAAwB,SAAS,QAAQ,SAAgB,QAAQ;AAAA;AAAA,IAE1E,OAAO,CAAC,UAAU;AAAA,MAChB,OAAO,wBAAwB,SAAS,QAAQ,SAAS,QAAe;AAAA;AAAA,IAE1E,UAAU;AAAA,EACZ;AAAA;",
|
|
8
|
+
"debugId": "CB4E2325706333DE64756E2164756E21",
|
|
9
9
|
"names": []
|
|
10
10
|
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import {
|
|
2
|
+
RefreshingSkipError2
|
|
3
|
+
} from "./chunk-jw9e0fr0.js";
|
|
4
|
+
|
|
5
|
+
// src/refresh.ts
|
|
6
|
+
import { AsyncLocalStorage } from "node:async_hooks";
|
|
7
|
+
var refreshStore = new AsyncLocalStorage;
|
|
8
|
+
function isRefreshing2() {
|
|
9
|
+
return refreshStore.getStore() ?? false;
|
|
10
|
+
}
|
|
11
|
+
function withRefreshing2(handler) {
|
|
12
|
+
return refreshStore.run(true, handler);
|
|
13
|
+
}
|
|
14
|
+
function skipRefreshing2() {
|
|
15
|
+
if (isRefreshing2()) {
|
|
16
|
+
throw new RefreshingSkipError2;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export { isRefreshing2, withRefreshing2, skipRefreshing2 };
|
|
21
|
+
|
|
22
|
+
//# debugId=67A7F9DE7EDBBD8C64756E2164756E21
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"sourcesContent": [
|
|
5
5
|
"import { AsyncLocalStorage } from 'node:async_hooks'\n\nimport { RefreshingSkipError } from './errors.ts'\n\nconst refreshStore = new AsyncLocalStorage<boolean>()\n\nexport function isRefreshing() {\n return refreshStore.getStore() ?? false\n}\n\nexport function withRefreshing<T extends () => any>(handler: T) {\n return refreshStore.run(true, handler)\n}\n\nexport function skipRefreshing() {\n if (isRefreshing()) {\n throw new RefreshingSkipError()\n }\n}\n"
|
|
6
6
|
],
|
|
7
|
-
"mappings": ";;;;;AAAA;AAIA,IAAM,eAAe,IAAI;AAElB,SAAS,
|
|
8
|
-
"debugId": "
|
|
7
|
+
"mappings": ";;;;;AAAA;AAIA,IAAM,eAAe,IAAI;AAElB,SAAS,aAAY,GAAG;AAAA,EAC7B,OAAO,aAAa,SAAS,KAAK;AAAA;AAG7B,SAAS,eAAmC,CAAC,SAAY;AAAA,EAC9D,OAAO,aAAa,IAAI,MAAM,OAAO;AAAA;AAGhC,SAAS,eAAc,GAAG;AAAA,EAC/B,IAAI,cAAa,GAAG;AAAA,IAClB,MAAM,IAAI;AAAA,EACZ;AAAA;",
|
|
8
|
+
"debugId": "67A7F9DE7EDBBD8C64756E2164756E21",
|
|
9
9
|
"names": []
|
|
10
10
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// src/lock.ts
|
|
2
2
|
import { Mutex } from "async-mutex";
|
|
3
|
-
|
|
3
|
+
var DEFAULT_LOCK_TTL2 = 5000;
|
|
4
|
+
function lock(defaultTtl = DEFAULT_LOCK_TTL2) {
|
|
4
5
|
const locks = new Map;
|
|
5
6
|
return async (key) => {
|
|
6
7
|
const k = Array.isArray(key) ? key.join(":") : key;
|
|
@@ -25,6 +26,7 @@ function lock(defaultTtl = 5000) {
|
|
|
25
26
|
};
|
|
26
27
|
startTimer(defaultTtl);
|
|
27
28
|
return {
|
|
29
|
+
ttl: defaultTtl,
|
|
28
30
|
async extend(ttl) {
|
|
29
31
|
if (isReleased) {
|
|
30
32
|
return false;
|
|
@@ -48,6 +50,6 @@ function lock(defaultTtl = 5000) {
|
|
|
48
50
|
};
|
|
49
51
|
}
|
|
50
52
|
|
|
51
|
-
export { lock };
|
|
53
|
+
export { DEFAULT_LOCK_TTL2, lock };
|
|
52
54
|
|
|
53
|
-
//# debugId=
|
|
55
|
+
//# debugId=769065B9E0FF5E8F64756E2164756E21
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/lock.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"import { Mutex } from 'async-mutex'\n\nexport const DEFAULT_LOCK_TTL = 5000\n\nexport type Lock = {\n /** Moves the expiry to `ttl` from now (default: half the lock's TTL). */\n extend(ttl?: number): Promise<boolean>\n release(): Promise<void>\n /**\n * The TTL the lock was taken with. The aggregate root keeps a replay's lock\n * alive at a quarter of it, and assumes {@link DEFAULT_LOCK_TTL} without it.\n */\n ttl?: number\n}\n\nexport type LockCreator = (key: string | string[]) => Promise<Lock>\n\nexport default function lock(defaultTtl = DEFAULT_LOCK_TTL): LockCreator {\n const locks = new Map<string, Mutex>()\n return async (key: string | string[]) => {\n const k = Array.isArray(key) ? key.join(':') : key\n if (!locks.has(k)) {\n locks.set(k, new Mutex())\n }\n\n const mutex = locks.get(k)!\n\n const releaseMutex = await mutex.acquire()\n let isReleased = false\n\n let timer: ReturnType<typeof setTimeout>\n const startTimer = (ttl: number) => {\n timer = setTimeout(() => {\n if (!isReleased) {\n console.warn('lock ttl expired for key', k)\n isReleased = true\n releaseMutex()\n if (!mutex.isLocked()) {\n locks.delete(k)\n }\n }\n }, ttl)\n }\n\n startTimer(defaultTtl)\n\n return {\n ttl: defaultTtl,\n async extend(ttl?: number) {\n if (isReleased) {\n return false\n }\n clearTimeout(timer)\n startTimer(ttl ?? defaultTtl / 2)\n return true\n },\n async release() {\n if (isReleased) {\n return\n }\n\n isReleased = true\n clearTimeout(timer)\n releaseMutex()\n\n if (!mutex.isLocked()) {\n locks.delete(k)\n }\n },\n }\n }\n}\n"
|
|
6
|
+
],
|
|
7
|
+
"mappings": ";AAAA;AAEO,IAAM,oBAAmB;AAehC,SAAwB,IAAI,CAAC,aAAa,mBAA+B;AAAA,EACvE,MAAM,QAAQ,IAAI;AAAA,EAClB,OAAO,OAAO,QAA2B;AAAA,IACvC,MAAM,IAAI,MAAM,QAAQ,GAAG,IAAI,IAAI,KAAK,GAAG,IAAI;AAAA,IAC/C,IAAI,CAAC,MAAM,IAAI,CAAC,GAAG;AAAA,MACjB,MAAM,IAAI,GAAG,IAAI,KAAO;AAAA,IAC1B;AAAA,IAEA,MAAM,QAAQ,MAAM,IAAI,CAAC;AAAA,IAEzB,MAAM,eAAe,MAAM,MAAM,QAAQ;AAAA,IACzC,IAAI,aAAa;AAAA,IAEjB,IAAI;AAAA,IACJ,MAAM,aAAa,CAAC,QAAgB;AAAA,MAClC,QAAQ,WAAW,MAAM;AAAA,QACvB,IAAI,CAAC,YAAY;AAAA,UACf,QAAQ,KAAK,4BAA4B,CAAC;AAAA,UAC1C,aAAa;AAAA,UACb,aAAa;AAAA,UACb,IAAI,CAAC,MAAM,SAAS,GAAG;AAAA,YACrB,MAAM,OAAO,CAAC;AAAA,UAChB;AAAA,QACF;AAAA,SACC,GAAG;AAAA;AAAA,IAGR,WAAW,UAAU;AAAA,IAErB,OAAO;AAAA,MACL,KAAK;AAAA,WACC,OAAM,CAAC,KAAc;AAAA,QACzB,IAAI,YAAY;AAAA,UACd,OAAO;AAAA,QACT;AAAA,QACA,aAAa,KAAK;AAAA,QAClB,WAAW,OAAO,aAAa,CAAC;AAAA,QAChC,OAAO;AAAA;AAAA,WAEH,QAAO,GAAG;AAAA,QACd,IAAI,YAAY;AAAA,UACd;AAAA,QACF;AAAA,QAEA,aAAa;AAAA,QACb,aAAa,KAAK;AAAA,QAClB,aAAa;AAAA,QAEb,IAAI,CAAC,MAAM,SAAS,GAAG;AAAA,UACrB,MAAM,OAAO,CAAC;AAAA,QAChB;AAAA;AAAA,IAEJ;AAAA;AAAA;",
|
|
8
|
+
"debugId": "769065B9E0FF5E8F64756E2164756E21",
|
|
9
|
+
"names": []
|
|
10
|
+
}
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
// src/errors.ts
|
|
2
2
|
import z from "zod/v4";
|
|
3
3
|
|
|
4
|
-
class
|
|
4
|
+
class ConcurrencyError2 extends Error {
|
|
5
5
|
constructor(streamId, expectedVersion, actualVersion) {
|
|
6
6
|
super(`Concurrency error on ${streamId.stream}(${streamId.id}): expected v${expectedVersion}, actual v${actualVersion}`);
|
|
7
7
|
}
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
-
class
|
|
10
|
+
class CheckpointConcurrencyError2 extends Error {
|
|
11
11
|
checkpointType;
|
|
12
12
|
name;
|
|
13
13
|
expectedVersion;
|
|
@@ -19,7 +19,7 @@ class CheckpointConcurrencyError extends Error {
|
|
|
19
19
|
}
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
class
|
|
22
|
+
class ValidationError2 extends Error {
|
|
23
23
|
zodError;
|
|
24
24
|
constructor(message, zodError) {
|
|
25
25
|
super(`${message}: ${z.prettifyError(zodError)}`);
|
|
@@ -27,13 +27,13 @@ class ValidationError extends Error {
|
|
|
27
27
|
}
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
class
|
|
30
|
+
class EventValidationError2 extends ValidationError2 {
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
-
class
|
|
33
|
+
class InfiniteLoopError2 extends Error {
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
-
class
|
|
36
|
+
class CommandError2 extends Error {
|
|
37
37
|
aggregateRootType;
|
|
38
38
|
commandName;
|
|
39
39
|
streamId;
|
|
@@ -47,7 +47,7 @@ class CommandError extends Error {
|
|
|
47
47
|
}
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
-
class
|
|
50
|
+
class ProjectionReplayLoopError2 extends Error {
|
|
51
51
|
projection;
|
|
52
52
|
event;
|
|
53
53
|
constructor(message, projection, event) {
|
|
@@ -57,13 +57,13 @@ class ProjectionReplayLoopError extends Error {
|
|
|
57
57
|
}
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
-
class
|
|
60
|
+
class RefreshingSkipError2 extends Error {
|
|
61
61
|
}
|
|
62
62
|
|
|
63
|
-
class
|
|
63
|
+
class ReplaySkipError2 extends Error {
|
|
64
64
|
}
|
|
65
65
|
|
|
66
|
-
class
|
|
66
|
+
class ProjectionEventHandlerExecutionError2 extends Error {
|
|
67
67
|
projection;
|
|
68
68
|
eventHandler;
|
|
69
69
|
event;
|
|
@@ -77,7 +77,7 @@ class ProjectionEventHandlerExecutionError extends Error {
|
|
|
77
77
|
}
|
|
78
78
|
}
|
|
79
79
|
|
|
80
|
-
class
|
|
80
|
+
class ProcessManagerEventHandlerExecutionError2 extends Error {
|
|
81
81
|
processManager;
|
|
82
82
|
eventHandler;
|
|
83
83
|
event;
|
|
@@ -91,6 +91,6 @@ class ProcessManagerEventHandlerExecutionError extends Error {
|
|
|
91
91
|
}
|
|
92
92
|
}
|
|
93
93
|
|
|
94
|
-
export {
|
|
94
|
+
export { ConcurrencyError2, CheckpointConcurrencyError2, ValidationError2, EventValidationError2, InfiniteLoopError2, CommandError2, ProjectionReplayLoopError2, RefreshingSkipError2, ReplaySkipError2, ProjectionEventHandlerExecutionError2, ProcessManagerEventHandlerExecutionError2 };
|
|
95
95
|
|
|
96
|
-
//# debugId=
|
|
96
|
+
//# debugId=42304B5DFE82D88064756E2164756E21
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"sourcesContent": [
|
|
5
5
|
"import z from 'zod/v4'\n\nimport type { BaseOutputEvent, OutputEvent } from './utilityTypes.js'\n\nexport class ConcurrencyError extends Error {\n constructor(\n streamId: { stream: string; id: string },\n expectedVersion: number,\n actualVersion: number,\n ) {\n super(\n `Concurrency error on ${streamId.stream}(${streamId.id}): expected v${expectedVersion}, actual v${actualVersion}`,\n )\n }\n}\n\nexport class CheckpointConcurrencyError extends Error {\n constructor(\n public readonly checkpointType: 'projection' | 'processManager',\n public readonly name: string,\n public readonly expectedVersion: number | null,\n ) {\n super(\n `Concurrency error on ${checkpointType} checkpoint \"${name}\": expected version ${expectedVersion}, but it was modified by another writer`,\n )\n }\n}\n\nexport class ValidationError extends Error {\n constructor(\n message: string,\n public readonly zodError: z.ZodError,\n ) {\n super(`${message}: ${z.prettifyError(zodError)}`)\n }\n}\n\nexport class EventValidationError extends ValidationError {}\n\nexport class InfiniteLoopError extends Error {}\n\nexport class CommandError<T extends Error> extends Error {\n constructor(\n public readonly aggregateRootType: string,\n public readonly commandName: string,\n public readonly streamId: string,\n public readonly originalError: T,\n ) {\n super(\n `Error executing command \"${commandName}\" on aggregate root \"${aggregateRootType}\" for stream id \"${streamId}\": ${originalError.message}`,\n )\n }\n}\n\nexport class ProjectionReplayLoopError extends Error {\n constructor(\n message: string,\n public readonly projection: { name: string; eventHandler: string },\n public readonly event: OutputEvent<any>,\n ) {\n super(message)\n }\n}\n\nexport class RefreshingSkipError extends Error {}\n\nexport class ReplaySkipError extends Error {}\n\nexport class ProjectionEventHandlerExecutionError<\n T extends Error,\n> extends Error {\n constructor(\n public readonly projection: string,\n public readonly eventHandler: string,\n public readonly event: BaseOutputEvent,\n public readonly originalError: T,\n ) {\n super(\n `Error execution event handler \"${eventHandler}\" in projection \"${projection}\": ${originalError.message}`,\n )\n }\n}\n\nexport class ProcessManagerEventHandlerExecutionError<\n T extends Error,\n> extends Error {\n constructor(\n public readonly processManager: string,\n public readonly eventHandler: string,\n public readonly event: BaseOutputEvent,\n public readonly originalError: T,\n ) {\n super(\n `Error execution event handler \"${eventHandler}\" in process manager \"${processManager}\": ${originalError.message}`,\n )\n }\n}\n"
|
|
6
6
|
],
|
|
7
|
-
"mappings": ";AAAA;AAAA;AAIO,MAAM,
|
|
8
|
-
"debugId": "
|
|
7
|
+
"mappings": ";AAAA;AAAA;AAIO,MAAM,0BAAyB,MAAM;AAAA,EAC1C,WAAW,CACT,UACA,iBACA,eACA;AAAA,IACA,MACE,wBAAwB,SAAS,UAAU,SAAS,kBAAkB,4BAA4B,eACpG;AAAA;AAEJ;AAAA;AAEO,MAAM,oCAAmC,MAAM;AAAA,EAElC;AAAA,EACA;AAAA,EACA;AAAA,EAHlB,WAAW,CACO,gBACA,MACA,iBAChB;AAAA,IACA,MACE,wBAAwB,8BAA8B,2BAA2B,wDACnF;AAAA,IANgB;AAAA,IACA;AAAA,IACA;AAAA;AAMpB;AAAA;AAEO,MAAM,yBAAwB,MAAM;AAAA,EAGvB;AAAA,EAFlB,WAAW,CACT,SACgB,UAChB;AAAA,IACA,MAAM,GAAG,YAAY,EAAE,cAAc,QAAQ,GAAG;AAAA,IAFhC;AAAA;AAIpB;AAAA;AAEO,MAAM,8BAA6B,iBAAgB;AAAC;AAAA;AAEpD,MAAM,2BAA0B,MAAM;AAAC;AAAA;AAEvC,MAAM,sBAAsC,MAAM;AAAA,EAErC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAJlB,WAAW,CACO,mBACA,aACA,UACA,eAChB;AAAA,IACA,MACE,4BAA4B,mCAAmC,qCAAqC,cAAc,cAAc,SAClI;AAAA,IAPgB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA;AAMpB;AAAA;AAEO,MAAM,mCAAkC,MAAM;AAAA,EAGjC;AAAA,EACA;AAAA,EAHlB,WAAW,CACT,SACgB,YACA,OAChB;AAAA,IACA,MAAM,OAAO;AAAA,IAHG;AAAA,IACA;AAAA;AAIpB;AAAA;AAEO,MAAM,6BAA4B,MAAM;AAAC;AAAA;AAEzC,MAAM,yBAAwB,MAAM;AAAC;AAAA;AAErC,MAAM,8CAEH,MAAM;AAAA,EAEI;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAJlB,WAAW,CACO,YACA,cACA,OACA,eAChB;AAAA,IACA,MACE,kCAAkC,gCAAgC,gBAAgB,cAAc,SAClG;AAAA,IAPgB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA;AAMpB;AAAA;AAEO,MAAM,kDAEH,MAAM;AAAA,EAEI;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAJlB,WAAW,CACO,gBACA,cACA,OACA,eAChB;AAAA,IACA,MACE,kCAAkC,qCAAqC,oBAAoB,cAAc,SAC3G;AAAA,IAPgB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA;AAMpB;",
|
|
8
|
+
"debugId": "42304B5DFE82D88064756E2164756E21",
|
|
9
9
|
"names": []
|
|
10
10
|
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
// src/surreal/schema.ts
|
|
2
|
+
var TABLES2 = {
|
|
3
|
+
events: "events",
|
|
4
|
+
counters: "event_sourcing_counters",
|
|
5
|
+
checkpoints: "checkpoints",
|
|
6
|
+
aggregateRootSnapshots: "aggregate_root_snapshots",
|
|
7
|
+
projectionSnapshots: "projection_snapshots",
|
|
8
|
+
projectionAppliedEvents: "projection_applied_events"
|
|
9
|
+
};
|
|
10
|
+
var SCHEMA_STATEMENTS2 = `
|
|
11
|
+
DEFINE TABLE IF NOT EXISTS ${TABLES2.events} SCHEMAFULL;
|
|
12
|
+
DEFINE FIELD IF NOT EXISTS position ON ${TABLES2.events} TYPE int;
|
|
13
|
+
DEFINE FIELD IF NOT EXISTS streamId ON ${TABLES2.events} TYPE string;
|
|
14
|
+
DEFINE FIELD IF NOT EXISTS streamType ON ${TABLES2.events} TYPE string;
|
|
15
|
+
DEFINE FIELD IF NOT EXISTS streamVersion ON ${TABLES2.events} TYPE int;
|
|
16
|
+
DEFINE FIELD IF NOT EXISTS type ON ${TABLES2.events} TYPE string;
|
|
17
|
+
DEFINE FIELD IF NOT EXISTS createdAt ON ${TABLES2.events} TYPE datetime DEFAULT time::now();
|
|
18
|
+
DEFINE FIELD IF NOT EXISTS payload ON ${TABLES2.events} TYPE string;
|
|
19
|
+
DEFINE FIELD IF NOT EXISTS metadata ON ${TABLES2.events} TYPE object FLEXIBLE;
|
|
20
|
+
DEFINE FIELD IF NOT EXISTS causationId ON ${TABLES2.events} TYPE option<string>;
|
|
21
|
+
DEFINE FIELD IF NOT EXISTS correlationId ON ${TABLES2.events} TYPE option<string>;
|
|
22
|
+
DEFINE FIELD IF NOT EXISTS actorId ON ${TABLES2.events} TYPE option<string>;
|
|
23
|
+
DEFINE FIELD IF NOT EXISTS schemaVersion ON ${TABLES2.events} TYPE int;
|
|
24
|
+
DEFINE INDEX IF NOT EXISTS events_stream_unique ON ${TABLES2.events} FIELDS streamId, streamType, streamVersion UNIQUE;
|
|
25
|
+
DEFINE INDEX IF NOT EXISTS events_position ON ${TABLES2.events} FIELDS position UNIQUE;
|
|
26
|
+
|
|
27
|
+
DEFINE TABLE IF NOT EXISTS ${TABLES2.counters} SCHEMAFULL;
|
|
28
|
+
DEFINE FIELD IF NOT EXISTS value ON ${TABLES2.counters} TYPE int;
|
|
29
|
+
|
|
30
|
+
DEFINE TABLE IF NOT EXISTS ${TABLES2.checkpoints} SCHEMAFULL;
|
|
31
|
+
DEFINE FIELD IF NOT EXISTS type ON ${TABLES2.checkpoints} TYPE string;
|
|
32
|
+
DEFINE FIELD IF NOT EXISTS name ON ${TABLES2.checkpoints} TYPE string;
|
|
33
|
+
DEFINE FIELD IF NOT EXISTS lastEventPosition ON ${TABLES2.checkpoints} TYPE int;
|
|
34
|
+
DEFINE FIELD IF NOT EXISTS metadata ON ${TABLES2.checkpoints} TYPE string;
|
|
35
|
+
DEFINE FIELD IF NOT EXISTS version ON ${TABLES2.checkpoints} TYPE int DEFAULT 0;
|
|
36
|
+
|
|
37
|
+
DEFINE TABLE IF NOT EXISTS ${TABLES2.aggregateRootSnapshots} SCHEMAFULL;
|
|
38
|
+
DEFINE FIELD IF NOT EXISTS streamId ON ${TABLES2.aggregateRootSnapshots} TYPE string;
|
|
39
|
+
DEFINE FIELD IF NOT EXISTS streamType ON ${TABLES2.aggregateRootSnapshots} TYPE string;
|
|
40
|
+
DEFINE FIELD IF NOT EXISTS streamVersion ON ${TABLES2.aggregateRootSnapshots} TYPE int;
|
|
41
|
+
DEFINE FIELD IF NOT EXISTS state ON ${TABLES2.aggregateRootSnapshots} TYPE string;
|
|
42
|
+
DEFINE FIELD IF NOT EXISTS metadata ON ${TABLES2.aggregateRootSnapshots} TYPE string;
|
|
43
|
+
DEFINE FIELD IF NOT EXISTS createdAt ON ${TABLES2.aggregateRootSnapshots} TYPE datetime DEFAULT time::now();
|
|
44
|
+
DEFINE FIELD IF NOT EXISTS lastEventPosition ON ${TABLES2.aggregateRootSnapshots} TYPE int;
|
|
45
|
+
DEFINE FIELD IF NOT EXISTS schemaVersion ON ${TABLES2.aggregateRootSnapshots} TYPE int;
|
|
46
|
+
DEFINE INDEX IF NOT EXISTS aggregate_root_snapshots_unique ON ${TABLES2.aggregateRootSnapshots} FIELDS streamType, streamId, streamVersion UNIQUE;
|
|
47
|
+
|
|
48
|
+
DEFINE TABLE IF NOT EXISTS ${TABLES2.projectionSnapshots} SCHEMAFULL;
|
|
49
|
+
DEFINE FIELD IF NOT EXISTS projectionId ON ${TABLES2.projectionSnapshots} TYPE string;
|
|
50
|
+
DEFINE FIELD IF NOT EXISTS projectionType ON ${TABLES2.projectionSnapshots} TYPE string;
|
|
51
|
+
DEFINE FIELD IF NOT EXISTS state ON ${TABLES2.projectionSnapshots} TYPE string;
|
|
52
|
+
DEFINE FIELD IF NOT EXISTS metadata ON ${TABLES2.projectionSnapshots} TYPE string;
|
|
53
|
+
DEFINE FIELD IF NOT EXISTS createdAt ON ${TABLES2.projectionSnapshots} TYPE datetime DEFAULT time::now();
|
|
54
|
+
DEFINE FIELD IF NOT EXISTS lastEventPosition ON ${TABLES2.projectionSnapshots} TYPE int;
|
|
55
|
+
DEFINE FIELD IF NOT EXISTS schemaVersion ON ${TABLES2.projectionSnapshots} TYPE int;
|
|
56
|
+
DEFINE INDEX IF NOT EXISTS projection_snapshots_unique ON ${TABLES2.projectionSnapshots} FIELDS projectionId, projectionType, lastEventPosition UNIQUE;
|
|
57
|
+
|
|
58
|
+
DEFINE TABLE IF NOT EXISTS ${TABLES2.projectionAppliedEvents} SCHEMAFULL;
|
|
59
|
+
DEFINE FIELD IF NOT EXISTS appliedEvents ON ${TABLES2.projectionAppliedEvents} TYPE int;
|
|
60
|
+
`;
|
|
61
|
+
async function initSchema2(database) {
|
|
62
|
+
await database.query(SCHEMA_STATEMENTS2);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export { TABLES2, SCHEMA_STATEMENTS2, initSchema2 };
|
|
66
|
+
|
|
67
|
+
//# debugId=D36A3ED0D642495B64756E2164756E21
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/surreal/schema.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"import type { Surreal } from 'surrealdb'\n\nexport const TABLES = {\n events: 'events',\n counters: 'event_sourcing_counters',\n checkpoints: 'checkpoints',\n aggregateRootSnapshots: 'aggregate_root_snapshots',\n projectionSnapshots: 'projection_snapshots',\n projectionAppliedEvents: 'projection_applied_events',\n} as const\n\n// Idempotent DDL — safe to run on every boot. All tables are SCHEMAFULL, so\n// SurrealDB rejects writes carrying fields that are not defined here.\nexport const SCHEMA_STATEMENTS = `\nDEFINE TABLE IF NOT EXISTS ${TABLES.events} SCHEMAFULL;\nDEFINE FIELD IF NOT EXISTS position ON ${TABLES.events} TYPE int;\nDEFINE FIELD IF NOT EXISTS streamId ON ${TABLES.events} TYPE string;\nDEFINE FIELD IF NOT EXISTS streamType ON ${TABLES.events} TYPE string;\nDEFINE FIELD IF NOT EXISTS streamVersion ON ${TABLES.events} TYPE int;\nDEFINE FIELD IF NOT EXISTS type ON ${TABLES.events} TYPE string;\nDEFINE FIELD IF NOT EXISTS createdAt ON ${TABLES.events} TYPE datetime DEFAULT time::now();\nDEFINE FIELD IF NOT EXISTS payload ON ${TABLES.events} TYPE string;\nDEFINE FIELD IF NOT EXISTS metadata ON ${TABLES.events} TYPE object FLEXIBLE;\nDEFINE FIELD IF NOT EXISTS causationId ON ${TABLES.events} TYPE option<string>;\nDEFINE FIELD IF NOT EXISTS correlationId ON ${TABLES.events} TYPE option<string>;\nDEFINE FIELD IF NOT EXISTS actorId ON ${TABLES.events} TYPE option<string>;\nDEFINE FIELD IF NOT EXISTS schemaVersion ON ${TABLES.events} TYPE int;\nDEFINE INDEX IF NOT EXISTS events_stream_unique ON ${TABLES.events} FIELDS streamId, streamType, streamVersion UNIQUE;\nDEFINE INDEX IF NOT EXISTS events_position ON ${TABLES.events} FIELDS position UNIQUE;\n\nDEFINE TABLE IF NOT EXISTS ${TABLES.counters} SCHEMAFULL;\nDEFINE FIELD IF NOT EXISTS value ON ${TABLES.counters} TYPE int;\n\nDEFINE TABLE IF NOT EXISTS ${TABLES.checkpoints} SCHEMAFULL;\nDEFINE FIELD IF NOT EXISTS type ON ${TABLES.checkpoints} TYPE string;\nDEFINE FIELD IF NOT EXISTS name ON ${TABLES.checkpoints} TYPE string;\nDEFINE FIELD IF NOT EXISTS lastEventPosition ON ${TABLES.checkpoints} TYPE int;\nDEFINE FIELD IF NOT EXISTS metadata ON ${TABLES.checkpoints} TYPE string;\nDEFINE FIELD IF NOT EXISTS version ON ${TABLES.checkpoints} TYPE int DEFAULT 0;\n\nDEFINE TABLE IF NOT EXISTS ${TABLES.aggregateRootSnapshots} SCHEMAFULL;\nDEFINE FIELD IF NOT EXISTS streamId ON ${TABLES.aggregateRootSnapshots} TYPE string;\nDEFINE FIELD IF NOT EXISTS streamType ON ${TABLES.aggregateRootSnapshots} TYPE string;\nDEFINE FIELD IF NOT EXISTS streamVersion ON ${TABLES.aggregateRootSnapshots} TYPE int;\nDEFINE FIELD IF NOT EXISTS state ON ${TABLES.aggregateRootSnapshots} TYPE string;\nDEFINE FIELD IF NOT EXISTS metadata ON ${TABLES.aggregateRootSnapshots} TYPE string;\nDEFINE FIELD IF NOT EXISTS createdAt ON ${TABLES.aggregateRootSnapshots} TYPE datetime DEFAULT time::now();\nDEFINE FIELD IF NOT EXISTS lastEventPosition ON ${TABLES.aggregateRootSnapshots} TYPE int;\nDEFINE FIELD IF NOT EXISTS schemaVersion ON ${TABLES.aggregateRootSnapshots} TYPE int;\nDEFINE INDEX IF NOT EXISTS aggregate_root_snapshots_unique ON ${TABLES.aggregateRootSnapshots} FIELDS streamType, streamId, streamVersion UNIQUE;\n\nDEFINE TABLE IF NOT EXISTS ${TABLES.projectionSnapshots} SCHEMAFULL;\nDEFINE FIELD IF NOT EXISTS projectionId ON ${TABLES.projectionSnapshots} TYPE string;\nDEFINE FIELD IF NOT EXISTS projectionType ON ${TABLES.projectionSnapshots} TYPE string;\nDEFINE FIELD IF NOT EXISTS state ON ${TABLES.projectionSnapshots} TYPE string;\nDEFINE FIELD IF NOT EXISTS metadata ON ${TABLES.projectionSnapshots} TYPE string;\nDEFINE FIELD IF NOT EXISTS createdAt ON ${TABLES.projectionSnapshots} TYPE datetime DEFAULT time::now();\nDEFINE FIELD IF NOT EXISTS lastEventPosition ON ${TABLES.projectionSnapshots} TYPE int;\nDEFINE FIELD IF NOT EXISTS schemaVersion ON ${TABLES.projectionSnapshots} TYPE int;\nDEFINE INDEX IF NOT EXISTS projection_snapshots_unique ON ${TABLES.projectionSnapshots} FIELDS projectionId, projectionType, lastEventPosition UNIQUE;\n\nDEFINE TABLE IF NOT EXISTS ${TABLES.projectionAppliedEvents} SCHEMAFULL;\nDEFINE FIELD IF NOT EXISTS appliedEvents ON ${TABLES.projectionAppliedEvents} TYPE int;\n`\n\nexport async function initSchema(database: Surreal): Promise<void> {\n await database.query(SCHEMA_STATEMENTS)\n}\n"
|
|
6
|
+
],
|
|
7
|
+
"mappings": ";AAEO,IAAM,UAAS;AAAA,EACpB,QAAQ;AAAA,EACR,UAAU;AAAA,EACV,aAAa;AAAA,EACb,wBAAwB;AAAA,EACxB,qBAAqB;AAAA,EACrB,yBAAyB;AAC3B;AAIO,IAAM,qBAAoB;AAAA,6BACJ,QAAO;AAAA,yCACK,QAAO;AAAA,yCACP,QAAO;AAAA,2CACL,QAAO;AAAA,8CACJ,QAAO;AAAA,qCAChB,QAAO;AAAA,0CACF,QAAO;AAAA,wCACT,QAAO;AAAA,yCACN,QAAO;AAAA,4CACJ,QAAO;AAAA,8CACL,QAAO;AAAA,wCACb,QAAO;AAAA,8CACD,QAAO;AAAA,qDACA,QAAO;AAAA,gDACZ,QAAO;AAAA;AAAA,6BAE1B,QAAO;AAAA,sCACE,QAAO;AAAA;AAAA,6BAEhB,QAAO;AAAA,qCACC,QAAO;AAAA,qCACP,QAAO;AAAA,kDACM,QAAO;AAAA,yCAChB,QAAO;AAAA,wCACR,QAAO;AAAA;AAAA,6BAElB,QAAO;AAAA,yCACK,QAAO;AAAA,2CACL,QAAO;AAAA,8CACJ,QAAO;AAAA,sCACf,QAAO;AAAA,yCACJ,QAAO;AAAA,0CACN,QAAO;AAAA,kDACC,QAAO;AAAA,8CACX,QAAO;AAAA,gEACW,QAAO;AAAA;AAAA,6BAE1C,QAAO;AAAA,6CACS,QAAO;AAAA,+CACL,QAAO;AAAA,sCAChB,QAAO;AAAA,yCACJ,QAAO;AAAA,0CACN,QAAO;AAAA,kDACC,QAAO;AAAA,8CACX,QAAO;AAAA,4DACO,QAAO;AAAA;AAAA,6BAEtC,QAAO;AAAA,8CACU,QAAO;AAAA;AAGrD,eAAsB,WAAU,CAAC,UAAkC;AAAA,EACjE,MAAM,SAAS,MAAM,kBAAiB;AAAA;",
|
|
8
|
+
"debugId": "D36A3ED0D642495B64756E2164756E21",
|
|
9
|
+
"names": []
|
|
10
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
} from "./chunk-
|
|
2
|
+
CheckpointConcurrencyError2,
|
|
3
|
+
ValidationError2
|
|
4
|
+
} from "./chunk-jw9e0fr0.js";
|
|
5
5
|
|
|
6
6
|
// src/createCheckpointApi.ts
|
|
7
7
|
import z from "zod/v4";
|
|
@@ -12,19 +12,67 @@ var checkpointSchema = z.object({
|
|
|
12
12
|
metadata: z.record(z.string(), z.any()),
|
|
13
13
|
version: z.int()
|
|
14
14
|
});
|
|
15
|
-
function
|
|
15
|
+
function createCheckpointApi2(params) {
|
|
16
16
|
let version = null;
|
|
17
|
+
let position = null;
|
|
17
18
|
const api = {
|
|
18
19
|
relatedStreamEvents: params.relatedStreamEvents,
|
|
19
20
|
async clear() {
|
|
20
21
|
await params.delete(params.type, params.name);
|
|
21
22
|
version = null;
|
|
23
|
+
position = null;
|
|
22
24
|
},
|
|
23
25
|
async load() {
|
|
24
26
|
const checkpoint = await params.get(params.type, params.name);
|
|
25
27
|
version = checkpoint?.version ?? null;
|
|
28
|
+
position = checkpoint?.lastEventPosition ?? null;
|
|
26
29
|
return checkpoint ?? null;
|
|
27
30
|
},
|
|
31
|
+
async claim(event, metadata = {}) {
|
|
32
|
+
while (true) {
|
|
33
|
+
const expectedVersion = version;
|
|
34
|
+
const previousPosition = position;
|
|
35
|
+
const nextVersion = (expectedVersion ?? -1) + 1;
|
|
36
|
+
const committed = await params.upsert({
|
|
37
|
+
lastEventPosition: event.position,
|
|
38
|
+
type: params.type,
|
|
39
|
+
name: params.name,
|
|
40
|
+
metadata,
|
|
41
|
+
version: nextVersion
|
|
42
|
+
}, expectedVersion);
|
|
43
|
+
if (committed) {
|
|
44
|
+
version = nextVersion;
|
|
45
|
+
position = event.position;
|
|
46
|
+
return {
|
|
47
|
+
claimed: true,
|
|
48
|
+
async release() {
|
|
49
|
+
if (version !== nextVersion) {
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
if (previousPosition === null) {
|
|
53
|
+
await api.clear();
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
const restored = await params.upsert({
|
|
57
|
+
lastEventPosition: previousPosition,
|
|
58
|
+
type: params.type,
|
|
59
|
+
name: params.name,
|
|
60
|
+
metadata,
|
|
61
|
+
version: nextVersion + 1
|
|
62
|
+
}, nextVersion);
|
|
63
|
+
if (restored) {
|
|
64
|
+
version = nextVersion + 1;
|
|
65
|
+
position = previousPosition;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
const current = await api.load();
|
|
71
|
+
if (current && current.lastEventPosition >= event.position) {
|
|
72
|
+
return { claimed: false };
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
},
|
|
28
76
|
async upsert(event, metadata = {}, mode = "monotonic") {
|
|
29
77
|
while (true) {
|
|
30
78
|
const expectedVersion = version;
|
|
@@ -38,11 +86,12 @@ function createCheckpointApi(params) {
|
|
|
38
86
|
}, expectedVersion);
|
|
39
87
|
if (committed) {
|
|
40
88
|
version = nextVersion;
|
|
89
|
+
position = event.position;
|
|
41
90
|
return;
|
|
42
91
|
}
|
|
43
92
|
const current = await api.load();
|
|
44
93
|
if (mode === "cas") {
|
|
45
|
-
throw new
|
|
94
|
+
throw new CheckpointConcurrencyError2(params.type, params.name, expectedVersion);
|
|
46
95
|
}
|
|
47
96
|
if (current && current.lastEventPosition >= event.position) {
|
|
48
97
|
return;
|
|
@@ -55,7 +104,7 @@ function createCheckpointApi(params) {
|
|
|
55
104
|
if (checkpoint) {
|
|
56
105
|
const result = checkpointSchema.safeParse(checkpoint);
|
|
57
106
|
if (!result.success) {
|
|
58
|
-
throw new
|
|
107
|
+
throw new ValidationError2(`loaded checkpoint for ${params.type} ${params.name} does not comply with schema`, result.error);
|
|
59
108
|
}
|
|
60
109
|
startPosition = checkpoint.lastEventPosition + 1;
|
|
61
110
|
options.onMetadata?.(checkpoint.metadata);
|
|
@@ -85,6 +134,6 @@ function createCheckpointApi(params) {
|
|
|
85
134
|
return api;
|
|
86
135
|
}
|
|
87
136
|
|
|
88
|
-
export {
|
|
137
|
+
export { createCheckpointApi2 };
|
|
89
138
|
|
|
90
|
-
//# debugId=
|
|
139
|
+
//# debugId=48393861CC2E414464756E2164756E21
|