@requence/event-sourcing 1.3.0 → 1.4.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 +1 -1
- package/dist/{chunk-z2yp4rve.js → chunk-57b88rt5.js} +7 -7
- package/dist/chunk-57b88rt5.js.map +10 -0
- package/dist/chunk-jd4q8fcf.js.map +2 -2
- package/dist/{chunk-gq80tgvf.js → chunk-pc1q4se9.js} +14 -3
- package/dist/chunk-pc1q4se9.js.map +10 -0
- package/dist/{chunk-wzw95hzk.js → chunk-vep2byx4.js} +10 -8
- package/dist/chunk-vep2byx4.js.map +10 -0
- package/dist/{chunk-fkzd741s.js → chunk-vvv14qxy.js} +4 -3
- package/dist/chunk-vvv14qxy.js.map +10 -0
- package/dist/createAggregateRoot.d.ts.map +1 -1
- package/dist/createAggregateRoot.js +2 -2
- package/dist/createEventStore.d.ts +4 -3
- package/dist/createEventStore.d.ts.map +1 -1
- package/dist/createEventStore.js +3 -3
- package/dist/createProcessManager.d.ts +13 -1
- package/dist/createProcessManager.d.ts.map +1 -1
- package/dist/createProcessManager.js +1 -1
- package/dist/drizzle/index.js +6 -6
- package/dist/drizzle/index.js.map +3 -3
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -4
- package/dist/memory/index.js +4 -4
- package/dist/transaction.d.ts +19 -1
- package/dist/transaction.d.ts.map +1 -1
- package/dist/transaction.js +1 -1
- package/package.json +1 -1
- package/src/createAggregateRoot.ts +37 -10
- package/src/createEventStore.ts +14 -7
- package/src/createProcessManager.ts +15 -1
- package/src/drizzle/index.ts +1 -1
- package/src/index.ts +2 -0
- package/src/tests/processManager.spec.ts +70 -0
- package/src/tests/transaction.spec.ts +53 -0
- package/src/transaction.ts +34 -2
- package/dist/chunk-fkzd741s.js.map +0 -10
- package/dist/chunk-gq80tgvf.js.map +0 -10
- package/dist/chunk-wzw95hzk.js.map +0 -10
- package/dist/chunk-z2yp4rve.js.map +0 -10
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { AsyncLocalStorage } from 'node:async_hooks'
|
|
1
2
|
import { setTimeout } from 'node:timers/promises'
|
|
2
3
|
|
|
3
4
|
import { describe, expect, it } from 'bun:test'
|
|
@@ -6,6 +7,7 @@ import { z } from 'zod/v4'
|
|
|
6
7
|
import { createAggregateRoot } from '../createAggregateRoot.ts'
|
|
7
8
|
import { createUserAggregate, setupEventStore } from './setup.ts'
|
|
8
9
|
import { CommandError } from '../errors.ts'
|
|
10
|
+
import lock from '../lock.ts'
|
|
9
11
|
|
|
10
12
|
describe('transaction', () => {
|
|
11
13
|
const createAggregateRoots = () => {
|
|
@@ -182,4 +184,55 @@ describe('transaction', () => {
|
|
|
182
184
|
expect(state.created).toBeTrue()
|
|
183
185
|
})
|
|
184
186
|
})
|
|
187
|
+
|
|
188
|
+
it('applies settled defaults from options to dispatched streams', async () => {
|
|
189
|
+
const context = new AsyncLocalStorage<string>()
|
|
190
|
+
|
|
191
|
+
const slowAggregate = createAggregateRoot('slow')
|
|
192
|
+
.withEvents({
|
|
193
|
+
Written: z.string(),
|
|
194
|
+
})
|
|
195
|
+
.withCommands((event) => ({
|
|
196
|
+
async write(delay: number, name: string) {
|
|
197
|
+
await setTimeout(delay)
|
|
198
|
+
return event('Written', `${name}:${context.getStore() ?? 'none'}`)
|
|
199
|
+
},
|
|
200
|
+
}))
|
|
201
|
+
|
|
202
|
+
const { eventStore, pseudoEventStore } = setupEventStore(slowAggregate, {
|
|
203
|
+
lock: lock(40), // 40ms
|
|
204
|
+
})
|
|
205
|
+
|
|
206
|
+
// The transaction's write holds the lock on slow:a, but its 100ms command
|
|
207
|
+
// outlives the 40ms lock TTL, so the direct write slips in and advances
|
|
208
|
+
// the stream to v1. The transaction's append then loses the race — without
|
|
209
|
+
// the settled defaults declared below the ConcurrencyError would surface
|
|
210
|
+
// from the transaction; with them the auto-settle reloads and re-applies
|
|
211
|
+
// the command.
|
|
212
|
+
await Promise.all([
|
|
213
|
+
eventStore.transaction(
|
|
214
|
+
async () => {
|
|
215
|
+
context.run('tx', () => {
|
|
216
|
+
slowAggregate.loadStream('a').write(100, 'TX')
|
|
217
|
+
})
|
|
218
|
+
},
|
|
219
|
+
{ settled: { maxRetries: 3 } },
|
|
220
|
+
),
|
|
221
|
+
(async () => {
|
|
222
|
+
await setTimeout(30)
|
|
223
|
+
await slowAggregate.loadStream('a').write(5, 'direct').settled()
|
|
224
|
+
})(),
|
|
225
|
+
])
|
|
226
|
+
|
|
227
|
+
const persisted = pseudoEventStore.filter(
|
|
228
|
+
(event) => event.streamType === 'slow',
|
|
229
|
+
)
|
|
230
|
+
// 'TX:tx' also proves the retry re-ran the command inside the dispatch
|
|
231
|
+
// site's async context — the AsyncLocalStorage value survived the retry.
|
|
232
|
+
expect(persisted.map((event) => event.payload)).toEqual([
|
|
233
|
+
'direct:none',
|
|
234
|
+
'TX:tx',
|
|
235
|
+
])
|
|
236
|
+
expect(persisted.map((event) => event.streamVersion)).toEqual([1, 2])
|
|
237
|
+
})
|
|
185
238
|
})
|
package/src/transaction.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { AsyncLocalStorage } from 'node:async_hooks'
|
|
2
2
|
|
|
3
|
+
import type { SettledOptions } from './createAggregateRoot.ts'
|
|
4
|
+
|
|
3
5
|
async function awaitAll(getPromises: () => Promise<any>[]) {
|
|
4
6
|
let promises = getPromises()
|
|
5
7
|
|
|
@@ -20,11 +22,23 @@ export type TransactionDelay = {
|
|
|
20
22
|
commit: () => Promise<void>
|
|
21
23
|
}
|
|
22
24
|
|
|
25
|
+
/**
|
|
26
|
+
* Options for a transaction run.
|
|
27
|
+
*
|
|
28
|
+
* `settled` — default {@link SettledOptions} applied when the transaction
|
|
29
|
+
* auto-settles the streams whose commands were dispatched inside the handler
|
|
30
|
+
* (explicit `settled()` calls are not allowed there).
|
|
31
|
+
*/
|
|
32
|
+
export type TransactionOptions = {
|
|
33
|
+
settled?: SettledOptions
|
|
34
|
+
}
|
|
35
|
+
|
|
23
36
|
export default function createTransaction() {
|
|
24
37
|
const transactionStore = new AsyncLocalStorage<{
|
|
25
38
|
delayPromises: Promise<void>[]
|
|
26
39
|
commitPromises: Promise<void>[]
|
|
27
40
|
afterHandlers: Array<() => Promise<any>>
|
|
41
|
+
settledDefaults?: SettledOptions
|
|
28
42
|
}>()
|
|
29
43
|
|
|
30
44
|
return {
|
|
@@ -32,6 +46,19 @@ export default function createTransaction() {
|
|
|
32
46
|
return Boolean(transactionStore.getStore())
|
|
33
47
|
},
|
|
34
48
|
|
|
49
|
+
get settledDefaults() {
|
|
50
|
+
return transactionStore.getStore()?.settledDefaults
|
|
51
|
+
},
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Runs the handler outside the transaction scope. Used by the settle
|
|
55
|
+
* retry: a retried append already passed the transaction gate on its
|
|
56
|
+
* first attempt and must not re-enter the (committed) transaction.
|
|
57
|
+
*/
|
|
58
|
+
exit<T>(handler: () => T): T {
|
|
59
|
+
return transactionStore.exit(handler)
|
|
60
|
+
},
|
|
61
|
+
|
|
35
62
|
delay(): TransactionDelay {
|
|
36
63
|
const store = transactionStore.getStore()
|
|
37
64
|
if (!store) {
|
|
@@ -68,14 +95,19 @@ export default function createTransaction() {
|
|
|
68
95
|
transactionStore.getStore()?.afterHandlers.push(onAfter)
|
|
69
96
|
},
|
|
70
97
|
|
|
71
|
-
async run<T extends () => any>(handler: T) {
|
|
98
|
+
async run<T extends () => any>(handler: T, options?: TransactionOptions) {
|
|
72
99
|
const { resolve, reject, promise } = Promise.withResolvers<void>()
|
|
73
100
|
const delayPromises = [promise]
|
|
74
101
|
const afterHandlers: Array<() => Promise<any>> = []
|
|
75
102
|
let result
|
|
76
103
|
try {
|
|
77
104
|
result = await transactionStore.run(
|
|
78
|
-
{
|
|
105
|
+
{
|
|
106
|
+
delayPromises,
|
|
107
|
+
afterHandlers,
|
|
108
|
+
commitPromises: [],
|
|
109
|
+
settledDefaults: options?.settled,
|
|
110
|
+
},
|
|
79
111
|
handler,
|
|
80
112
|
)
|
|
81
113
|
resolve()
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../src/createProcessManager.ts"],
|
|
4
|
-
"sourcesContent": [
|
|
5
|
-
"import { AsyncLocalStorage } from 'node:async_hooks'\n\nimport {\n type CheckpointApi,\n type CheckpointMethods,\n createCheckpointApi,\n} from './createCheckpointApi.ts'\nimport type { LoadEvents, OnProgress } from './createEventStore.ts'\nimport {\n CheckpointConcurrencyError,\n ProcessManagerEventHandlerExecutionError,\n RefreshingSkipError,\n} from './errors.ts'\nimport { isRefreshing, withRefreshing } from './refresh.ts'\nimport { clone } from './superjson.ts'\nimport type {\n AfterEffectHandlers,\n BaseOutputEvent,\n EventHandlers,\n EventTemplate,\n Keys,\n Merge,\n StreamEvents,\n} from './utilityTypes.js'\n\ntype ProcessManagerInfo = {\n name: string\n event: BaseOutputEvent\n}\nconst processManagerInfoStore = new AsyncLocalStorage<ProcessManagerInfo>()\n\nfunction withProcessManagerInfo(\n info: ProcessManagerInfo,\n handler: () => Promise<void>,\n) {\n return processManagerInfoStore.run(info, handler)\n}\n\nexport function getProcessManagerInfo() {\n return processManagerInfoStore.getStore()\n}\n\nexport function isInsideProcessManager() {\n return Boolean(getProcessManagerInfo())\n}\n\ntype ProcessManagerEventHandlers<Events extends EventTemplate> = EventHandlers<\n Events,\n { refreshing: boolean }\n>\n\ntype ProcessManagerAfterEffectHandlers<Events extends EventTemplate> =\n AfterEffectHandlers<Events, { refreshing: boolean }>\n\nexport type InternalProcessManager = {\n apply: (event: BaseOutputEvent) => Promise<void>\n applyAfter: (event: BaseOutputEvent) => Promise<void>\n beginSession: () => Promise<void>\n endSession: () => void\n setRelatedStreamEvents: (\n generateRelatedStreamEvents: (\n eventHandlers: EventHandlers<EventTemplate>,\n ) => StreamEvents[],\n ) => void\n isReady(): Promise<void>\n beginRefresh(): Promise<void>\n progressRefresh(\n index: number,\n event: BaseOutputEvent,\n after: boolean,\n ): Promise<void>\n endRefresh(): void\n init(catchUp: boolean): Promise<void>\n hasState(): boolean\n}\n\nexport type ProcessManagerApi<\n State = never,\n Events extends EventTemplate = never,\n Flags extends {\n withState: boolean\n withEventHandlers: boolean\n concurrent: boolean\n withAfterEffects: boolean\n } = {\n withState: false\n withEventHandlers: false\n concurrent: false\n withAfterEffects: false\n },\n> = {\n withState: <NextState>(\n state: NextState,\n ) => Omit<\n ProcessManagerApi<NextState, Events, Merge<Flags, { withState: true }>>,\n Keys<Merge<Flags, { withState: true }>>\n >\n withEventHandlers: (\n handlers: [State] extends [never]\n ? ProcessManagerEventHandlers<Events>\n : (state: State) => ProcessManagerEventHandlers<Events>,\n ) => Omit<\n ProcessManagerApi<State, Events, Merge<Flags, { withEventHandlers: true }>>,\n Keys<Merge<Flags, { withEventHandlers: true }>>\n >\n withAfterEffects: (\n handlers: [State] extends [never]\n ? ProcessManagerAfterEffectHandlers<Events>\n : (state: State) => ProcessManagerAfterEffectHandlers<Events>,\n ) => Omit<\n ProcessManagerApi<State, Events, Merge<Flags, { withAfterEffects: true }>>,\n Keys<Merge<Flags, { withAfterEffects: true }>>\n >\n concurrent: () => Omit<\n ProcessManagerApi<State, Events, Merge<Flags, { concurrent: true }>>,\n Keys<Merge<Flags, { concurrent: true }>>\n >\n isReady(): Promise<void>\n $inferState: State\n} & (Flags['withState'] extends true\n ? {\n refreshState: () => Promise<void>\n state: () => Promise<State>\n }\n : {})\n\nexport function buildProcessManagerCreator(params: {\n loadEvents: LoadEvents\n checkpoint: CheckpointMethods\n onRefresh?: OnProgress\n}) {\n return (name: string): ProcessManagerApi => {\n let idle = true\n let createEventHandlers: (\n state: any,\n ) => ProcessManagerEventHandlers<any> = () => ({})\n let createAfterEffects: (\n state: any,\n ) => ProcessManagerAfterEffectHandlers<any> = () => ({})\n\n let hasState = false\n let state: any = null\n let initialState: any = null\n let exclusive = true\n let sessionActive = false\n let generateRelatedStreamEvents: (\n eventHandlers: EventHandlers<any>,\n ) => StreamEvents[]\n let checkpointApi: CheckpointApi\n let lastEventPosition = -1\n const { promise: hydrated, resolve: resolveHydrated } =\n Promise.withResolvers<void>()\n\n const locks = new Map<string, Promise<void>>()\n const apply = async (\n event: BaseOutputEvent,\n after: boolean,\n hydrating = false,\n ) => {\n const handler = after\n ? createAfterEffects(state)[`after${event.type}`]\n : createEventHandlers(state)[`on${event.type}`]\n\n if (!handler) {\n return Promise.resolve()\n }\n\n if (hydrating) {\n lastEventPosition = event.position\n } else {\n await hydrated\n // event was already applied through hydration\n if (event.position <= lastEventPosition) {\n return\n }\n }\n const unlocked = !exclusive\n ? Promise.resolve()\n : (locks.get(event.streamId)?.catch(() => {}) ?? Promise.resolve())\n\n const runner = (async () => {\n await unlocked\n const refreshing = isRefreshing()\n // Fold state into the process-manager checkpoint with optimistic\n // concurrency control. Only the stateful `on<Event>` fold needs\n // compare-and-swap — after-effects and stateless managers persist a\n // plain cursor, which is safe to write monotonically. When a concurrent\n // instance advances the checkpoint between our read and write, reload\n // the latest state and re-apply this event on top of it.\n const useCas = hasState && !after && !hydrating && !refreshing\n while (true) {\n const currentHandler = after\n ? createAfterEffects(state)[`after${event.type}`]\n : createEventHandlers(state)[`on${event.type}`]\n await withProcessManagerInfo(\n {\n name,\n event,\n },\n async () => {\n try {\n await currentHandler!(event, { refreshing })\n } catch (error) {\n if (error instanceof RefreshingSkipError) {\n if (refreshing) {\n return\n }\n\n throw new Error(\n 'RefreshingSkipError should never be thrown outside refresh',\n )\n }\n\n if (!(error instanceof Error)) {\n throw error\n }\n\n throw new ProcessManagerEventHandlerExecutionError(\n name,\n after ? `after${event.type}` : `on${event.type}`,\n event,\n error,\n )\n }\n },\n )\n\n try {\n await checkpointApi.upsert(\n event,\n { state },\n useCas ? 'cas' : 'monotonic',\n )\n break\n } catch (error) {\n if (!(error instanceof CheckpointConcurrencyError)) {\n throw error\n }\n\n // A concurrent writer advanced the checkpoint. Reload the latest\n // folded state (and version) and re-apply this event on top of it.\n // This event is emitted only by this instance, so it is never\n // already part of the reloaded state — we must always re-fold it\n // (do not skip on position: events are processed out of global\n // order across instances).\n const checkpoint = await checkpointApi.load()\n state =\n checkpoint?.metadata?.state != null\n ? clone(checkpoint.metadata.state)\n : clone(initialState)\n }\n }\n })()\n\n if (exclusive) {\n locks.set(event.streamId, runner)\n\n runner\n .finally(() => {\n if (locks.get(event.streamId) === runner) {\n locks.delete(event.streamId)\n }\n })\n .catch(() => {})\n return runner\n }\n\n return Promise.resolve()\n }\n\n let resolveRefresh: null | (() => void) = null\n\n const api = {\n name,\n hasState() {\n return hasState\n },\n async isReady() {\n await hydrated\n },\n async beginSession() {\n if (!hasState) return\n // Load through the checkpoint API so the local version is synced with\n // the store; the subsequent fold relies on it for compare-and-swap.\n const checkpoint = await checkpointApi.load()\n if (checkpoint) {\n state =\n checkpoint.metadata?.state != null\n ? clone(checkpoint.metadata.state)\n : clone(initialState)\n lastEventPosition = checkpoint.lastEventPosition\n } else {\n state = clone(initialState)\n lastEventPosition = -1\n }\n sessionActive = true\n },\n endSession() {\n if (!hasState) return\n state = null\n sessionActive = false\n },\n async apply(event) {\n await apply(event, false)\n },\n async applyAfter(event) {\n await apply(event, true)\n },\n withState(nextState) {\n state = clone(nextState)\n initialState = clone(nextState)\n hasState = true\n return api as any\n },\n concurrent() {\n exclusive = false\n return api\n },\n withEventHandlers(handlers) {\n createEventHandlers =\n typeof handlers === 'function' ? (handlers as any) : () => handlers\n\n return api\n },\n withAfterEffects(handlers) {\n createAfterEffects =\n typeof handlers === 'function' ? (handlers as any) : () => handlers\n\n return api\n },\n setRelatedStreamEvents(generate) {\n generateRelatedStreamEvents = generate\n },\n async beginRefresh() {\n params.onRefresh?.begin?.(name)\n await checkpointApi.clear()\n lastEventPosition = -1\n state = initialState\n },\n async progressRefresh(index, event, after) {\n await apply(event, after, true)\n\n if (\n !checkpointApi.relatedStreamEvents ||\n checkpointApi.relatedStreamEvents.some((streamEvent) =>\n streamEvent.events.includes(event.type),\n )\n ) {\n params.onRefresh?.progress?.(name, index, event)\n }\n },\n endRefresh() {\n params.onRefresh?.end?.(name)\n resolveHydrated()\n },\n async refreshState() {\n if (!idle) {\n await refresh()\n return\n }\n const { promise, resolve } = Promise.withResolvers<void>()\n resolveRefresh = resolve\n return promise\n },\n async state() {\n await hydrated\n if (!sessionActive && hasState) {\n const checkpoint = await params.checkpoint.get(\n 'processManager',\n name,\n )\n return checkpoint?.metadata?.state ?? clone(initialState)\n }\n return state\n },\n async init(catchUp) {\n idle = false\n const relatedStreamEvents = generateRelatedStreamEvents({\n ...createEventHandlers(null),\n ...createAfterEffects(null),\n })\n\n checkpointApi = createCheckpointApi({\n ...params.checkpoint,\n name,\n relatedStreamEvents,\n type: 'processManager',\n loadEvents: params.loadEvents,\n apply: (event) => apply(event, false, true),\n applyAfter: (event) => apply(event, true, true),\n })\n\n if (resolveRefresh) {\n await refresh()\n return\n }\n if (!catchUp) {\n return\n }\n\n await checkpointApi.rehydrated({\n getMetadata() {\n return { state }\n },\n onMetadata(metadata) {\n state = metadata.state ?? state\n },\n })\n\n // Release state after hydration — it will be loaded\n // from the checkpoint on the next beginSession call\n state = null\n\n resolveHydrated()\n },\n $inferState: null as never,\n } as ProcessManagerApi & InternalProcessManager\n\n async function refresh() {\n await withRefreshing(async () => {\n await api.beginRefresh()\n await checkpointApi.rehydrated({\n getMetadata() {\n return { state }\n },\n onProgress(index, event) {\n params.onRefresh?.progress?.(name, index, event)\n },\n })\n })\n api.endRefresh()\n }\n\n return api\n }\n}\n"
|
|
6
|
-
],
|
|
7
|
-
"mappings": "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",
|
|
8
|
-
"debugId": "01E888069A79D9EF64756E2164756E21",
|
|
9
|
-
"names": []
|
|
10
|
-
}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../src/transaction.ts"],
|
|
4
|
-
"sourcesContent": [
|
|
5
|
-
"import { AsyncLocalStorage } from 'node:async_hooks'\n\nasync function awaitAll(getPromises: () => Promise<any>[]) {\n let promises = getPromises()\n\n while (true) {\n await Promise.all(promises)\n const nextPromises = getPromises()\n if (nextPromises.length > promises.length) {\n promises = nextPromises\n } else {\n break\n }\n }\n}\n\nexport type TransactionDelay = {\n resolve: () => void\n reject: (error: Error) => void\n commit: () => Promise<void>\n}\n\nexport default function createTransaction() {\n const transactionStore = new AsyncLocalStorage<{\n delayPromises: Promise<void>[]\n commitPromises: Promise<void>[]\n afterHandlers: Array<() => Promise<any>>\n }>()\n\n return {\n get active() {\n return Boolean(transactionStore.getStore())\n },\n\n delay(): TransactionDelay {\n const store = transactionStore.getStore()\n if (!store) {\n return {\n resolve: () => {},\n reject: () => {},\n commit: () => Promise.resolve(),\n }\n }\n\n const idx = store.commitPromises.length\n const { resolve, reject, promise } = Promise.withResolvers<void>()\n store.delayPromises.push(promise)\n\n const { promise: commitPromise, resolve: resolveCommitPromise } =\n Promise.withResolvers<void>()\n store.commitPromises.push(commitPromise)\n\n return {\n resolve,\n reject,\n async commit() {\n if (idx > 0) {\n await store.commitPromises.at(idx - 1)\n }\n\n resolveCommitPromise()\n await awaitAll(() => store.delayPromises)\n },\n }\n },\n\n after(onAfter: () => Promise<any>) {\n transactionStore.getStore()?.afterHandlers.push(onAfter)\n },\n\n async run<T extends () => any>(handler: T) {\n const { resolve, reject, promise } = Promise.withResolvers<void>()\n const delayPromises = [promise]\n const afterHandlers: Array<() => Promise<any>> = []\n let result\n try {\n result = await transactionStore.run(\n { delayPromises, afterHandlers, commitPromises: [] },\n handler,\n )\n resolve()\n } catch (error) {\n reject(error)\n }\n await awaitAll(() => delayPromises)\n await Promise.all(afterHandlers.map((handler) => handler()))\n\n return result\n },\n }\n}\n\nexport type Transaction = ReturnType<typeof createTransaction>\n"
|
|
6
|
-
],
|
|
7
|
-
"mappings": ";AAAA;AAEA,eAAe,QAAQ,CAAC,aAAmC;AAAA,EACzD,IAAI,WAAW,YAAY;AAAA,EAE3B,OAAO,MAAM;AAAA,IACX,MAAM,QAAQ,IAAI,QAAQ;AAAA,IAC1B,MAAM,eAAe,YAAY;AAAA,IACjC,IAAI,aAAa,SAAS,SAAS,QAAQ;AAAA,MACzC,WAAW;AAAA,IACb,EAAO;AAAA,MACL;AAAA;AAAA,EAEJ;AAAA;AASF,SAAwB,iBAAiB,GAAG;AAAA,EAC1C,MAAM,mBAAmB,IAAI;AAAA,EAM7B,OAAO;AAAA,QACD,MAAM,GAAG;AAAA,MACX,OAAO,QAAQ,iBAAiB,SAAS,CAAC;AAAA;AAAA,IAG5C,KAAK,GAAqB;AAAA,MACxB,MAAM,QAAQ,iBAAiB,SAAS;AAAA,MACxC,IAAI,CAAC,OAAO;AAAA,QACV,OAAO;AAAA,UACL,SAAS,MAAM;AAAA,UACf,QAAQ,MAAM;AAAA,UACd,QAAQ,MAAM,QAAQ,QAAQ;AAAA,QAChC;AAAA,MACF;AAAA,MAEA,MAAM,MAAM,MAAM,eAAe;AAAA,MACjC,QAAQ,SAAS,QAAQ,YAAY,QAAQ,cAAoB;AAAA,MACjE,MAAM,cAAc,KAAK,OAAO;AAAA,MAEhC,QAAQ,SAAS,eAAe,SAAS,yBACvC,QAAQ,cAAoB;AAAA,MAC9B,MAAM,eAAe,KAAK,aAAa;AAAA,MAEvC,OAAO;AAAA,QACL;AAAA,QACA;AAAA,aACM,OAAM,GAAG;AAAA,UACb,IAAI,MAAM,GAAG;AAAA,YACX,MAAM,MAAM,eAAe,GAAG,MAAM,CAAC;AAAA,UACvC;AAAA,UAEA,qBAAqB;AAAA,UACrB,MAAM,SAAS,MAAM,MAAM,aAAa;AAAA;AAAA,MAE5C;AAAA;AAAA,IAGF,KAAK,CAAC,SAA6B;AAAA,MACjC,iBAAiB,SAAS,GAAG,cAAc,KAAK,OAAO;AAAA;AAAA,SAGnD,IAAwB,CAAC,SAAY;AAAA,MACzC,QAAQ,SAAS,QAAQ,YAAY,QAAQ,cAAoB;AAAA,MACjE,MAAM,gBAAgB,CAAC,OAAO;AAAA,MAC9B,MAAM,gBAA2C,CAAC;AAAA,MAClD,IAAI;AAAA,MACJ,IAAI;AAAA,QACF,SAAS,MAAM,iBAAiB,IAC9B,EAAE,eAAe,eAAe,gBAAgB,CAAC,EAAE,GACnD,OACF;AAAA,QACA,QAAQ;AAAA,QACR,OAAO,OAAO;AAAA,QACd,OAAO,KAAK;AAAA;AAAA,MAEd,MAAM,SAAS,MAAM,aAAa;AAAA,MAClC,MAAM,QAAQ,IAAI,cAAc,IAAI,CAAC,aAAY,SAAQ,CAAC,CAAC;AAAA,MAE3D,OAAO;AAAA;AAAA,EAEX;AAAA;",
|
|
8
|
-
"debugId": "75143A00A85F441C64756E2164756E21",
|
|
9
|
-
"names": []
|
|
10
|
-
}
|
|
@@ -1,10 +0,0 @@
|
|
|
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 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 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\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 return [] as Error | BaseInputEvent[]\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(\n 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 loadUntil(state, snapshotApi, streamId, undefined, filter),\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}.`,\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}\".`,\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 const retryStream = createStream(clone(initialState), streamId, {\n load: true,\n filter: config.filter,\n replayCommands: dispatchedCommands,\n errorHandlerEntries: Array.from(errorHandlers),\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 registerRootPromiseToUpstream(() => api.commands.settled())\n transaction.after(() => api.commands.settled())\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": "27B830D34C48B63764756E2164756E21",
|
|
9
|
-
"names": []
|
|
10
|
-
}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../src/createEventStore.ts"],
|
|
4
|
-
"sourcesContent": [
|
|
5
|
-
"import type {\n AggregateRootApi,\n AggregateRootSnapshotMethods,\n AnyAggregateRoot,\n InternalAggregateRootApi,\n} from './createAggregateRoot.ts'\nimport type { CheckpointMethods } from './createCheckpointApi.ts'\nimport {\n type EventListenerApi,\n type InternalEventListener,\n createEventListener,\n} from './createEventListener.ts'\nimport {\n type InternalProcessManager,\n type ProcessManagerApi,\n buildProcessManagerCreator,\n} from './createProcessManager.ts'\nimport {\n type InternalProjection,\n type ProjectionApi,\n type ProjectionApiWithSnapshots,\n type ProjectionSnapshotMethods,\n buildProjectionCreator,\n} from './createProjection.ts'\nimport lock, { type LockCreator } from './lock.ts'\nimport { withRefreshing } from './refresh.ts'\nimport createTransaction from './transaction.ts'\nimport type {\n BaseInputEvent,\n BaseOutputEvent,\n EventHandlers,\n EventTemplate,\n MaybePromise,\n Stream,\n StreamEvents,\n StreamId,\n StreamIdEvents,\n} from './utilityTypes.ts'\nimport {\n type WrappedEvent,\n unwrapEvent,\n wrappedEventBuilder,\n} from './wrappedEventBuilder.ts'\n\nexport type LoadEvents = (\n select:\n | Stream\n | StreamId\n | Stream[]\n | StreamId[]\n | StreamEvents\n | StreamEvents[]\n | StreamIdEvents\n | StreamIdEvents[]\n | null,\n range?: { from: number; to?: number },\n) => AsyncGenerator<BaseOutputEvent>\n\ntype AppendEvents = (\n streamId: StreamId,\n events: BaseInputEvent[],\n expectedVersion: number,\n) => MaybePromise<BaseOutputEvent[]>\n\nexport type InternalAppendEvents = (\n streamId: StreamId,\n events: BaseInputEvent[],\n expectedVersion: number,\n) => MaybePromise<BaseOutputEvent[]>\n\nexport type EmitEvents = (events: BaseOutputEvent[]) => Promise<void>\n\nexport type EventsFromRoot<Root> =\n Root extends Omit<AggregateRootApi<any, any, infer E>, any> ? E : never\n\nexport type OnProgress = {\n begin?: (projectionName: string) => void\n progress?: (\n projectionName: string,\n index: number,\n event: BaseOutputEvent,\n ) => void\n end?: (projectionName: string) => void\n}\n\ninterface BaseEventStoreParams<Root extends AnyAggregateRoot> {\n loadEvents: LoadEvents\n appendEvents: AppendEvents\n aggregateRoots: Root[]\n checkpoint: CheckpointMethods\n lock?: LockCreator\n projectionSnapshot?: ProjectionSnapshotMethods\n onProjectionReplay?: OnProgress\n onProcessManagerRefresh?: OnProgress\n autoInit?: boolean\n}\n\nexport interface EventStoreParamsWithAggregateRootSnapshots<\n Root extends AnyAggregateRoot,\n> extends BaseEventStoreParams<Root> {\n aggregateRootSnapshot: AggregateRootSnapshotMethods\n postProcessEvent?: (\n event: WrappedEvent<EventsFromRoot<Root>>,\n aggregateRoot: Root,\n ) => WrappedEvent\n}\n\nexport interface EventStoreParamsWithoutAggregateRootSnapshots<\n Root extends AnyAggregateRoot,\n> extends BaseEventStoreParams<Root> {\n aggregateRoots: Root[]\n aggregateRootSnapshot?: never\n postProcessEvent?: (\n event: WrappedEvent<EventsFromRoot<Root>>,\n aggregateRoot: Root,\n ) => WrappedEvent\n}\n\nexport type EventStore<\n Event extends EventTemplate,\n Root extends AnyAggregateRoot,\n SupportsProjectionSnapshots = boolean,\n> = {\n createProjection(\n name: string,\n ): SupportsProjectionSnapshots extends true\n ? ProjectionApiWithSnapshots<Event>\n : ProjectionApi<Event>\n createProcessManager(name: string): ProcessManagerApi<never, Event>\n createEventListener(name: string): EventListenerApi<Event>\n rebuild: () => Promise<void>\n isReady: () => Promise<void>\n init: () => Promise<EventStore<Event, Root, SupportsProjectionSnapshots>>\n getAggregateRoot<S extends Root['type']>(\n type: S,\n ): Root extends { type: S } ? Root : never\n transaction<T extends () => any>(handler: T): Promise<Awaited<ReturnType<T>>>\n}\n\nexport function createEventStore<const Root extends AnyAggregateRoot>(\n params: EventStoreParamsWithoutAggregateRootSnapshots<Root>,\n): EventStore<EventsFromRoot<Root>, Root, false>\nexport function createEventStore<const Root extends AnyAggregateRoot>(\n params: EventStoreParamsWithAggregateRootSnapshots<Root>,\n): EventStore<EventsFromRoot<Root>, Root, true>\nexport function createEventStore<const Root extends AnyAggregateRoot>(\n params:\n | EventStoreParamsWithoutAggregateRootSnapshots<Root>\n | EventStoreParamsWithAggregateRootSnapshots<Root>,\n) {\n const transaction = createTransaction()\n const { promise: initialized, resolve: resolveInitialized } =\n Promise.withResolvers<void>()\n const projections = new Map<string, InternalProjection>()\n const processManagers = new Map<string, InternalProcessManager>()\n const eventListeners = new Map<string, InternalEventListener>()\n const aggregatRootsByEvents = new Map<\n string,\n { aggregateRoot: InternalAggregateRootApi; eventType: string }\n >()\n\n let allReplaying = false\n let initializing = false\n\n const assertInitializing = () => {\n if (!initializing && params.autoInit === false) {\n throw new Error(\n 'Cannot emit events because the event store is not initialized. Set autoInit to true, or explicitly call .init() before emitting events.',\n )\n }\n }\n\n let exclusiveEmitEventsChain: Promise<any> = Promise.resolve()\n const emitEvents: EmitEvents = async (events) => {\n const result = exclusiveEmitEventsChain.then(async () => {\n await Promise.all(processManagers.values().map((pm) => pm.beginSession()))\n\n try {\n for (const event of events) {\n await Promise.all(\n [\n ...processManagers.values(),\n ...projections.values(),\n ...eventListeners.values(),\n ].map((listener) => listener.apply(event)),\n )\n }\n\n for (const event of events) {\n await Promise.all(\n [...processManagers.values(), ...eventListeners.values()].map(\n (processManager) => processManager.applyAfter(event),\n ),\n )\n }\n } finally {\n for (const pm of processManagers.values()) {\n pm.endSession()\n }\n }\n })\n\n // Advance the serialization chain but swallow this operation's outcome so a\n // rejection is delivered only to its own caller. Chaining the next op onto a\n // rejected promise would skip its callback and re-propagate the stale error,\n // permanently poisoning every subsequent emit for the life of the process.\n exclusiveEmitEventsChain = result.then(\n () => undefined,\n () => undefined,\n )\n\n return result\n }\n\n const loadEvents: LoadEvents = (select, range) => {\n assertInitializing()\n return params.loadEvents(select, range)\n }\n\n let exclusiveAppendEventsChain: Promise<any> = initialized\n const appendEvents: InternalAppendEvents = async (\n streamId,\n events,\n expectedVersion,\n ) => {\n assertInitializing()\n const result = exclusiveAppendEventsChain.then(async () => {\n if (events.length === 0) {\n return []\n }\n await new Promise((resolve) => setImmediate(resolve)) // edge case for sync setup, see 'can execute after effect' test\n\n const processedEvents = events.map((rawEvent) => {\n const event = structuredClone(rawEvent)\n if (params.postProcessEvent) {\n const wrappedEvent = wrappedEventBuilder(event) as WrappedEvent<any>\n const { aggregateRoot } = aggregatRootsByEvents.get(event.type)!\n const processedEvent = unwrapEvent(\n params.postProcessEvent(\n wrappedEvent,\n aggregateRoot as unknown as Root,\n ),\n )\n Object.assign(event, processedEvent)\n }\n\n return event\n })\n\n return params.appendEvents(streamId, processedEvents, expectedVersion)\n })\n\n // Advance the serialization chain but swallow this operation's outcome so a\n // rejection is delivered only to its own caller. Chaining the next append\n // onto a rejected promise would skip its callback and re-propagate the stale\n // error, permanently poisoning every subsequent append for the life of the\n // process (a single ConcurrencyError would take down all writes).\n exclusiveAppendEventsChain = result.then(\n () => undefined,\n () => undefined,\n )\n\n return result\n }\n\n for (const aggregateRoot of params.aggregateRoots as unknown as InternalAggregateRootApi[]) {\n aggregateRoot.eventTypes.forEach((eventType) => {\n aggregatRootsByEvents.set(eventType, {\n aggregateRoot,\n eventType,\n })\n })\n\n aggregateRoot.linkEventStore(\n loadEvents,\n appendEvents,\n emitEvents,\n transaction,\n params.lock ?? lock(5000),\n params.aggregateRootSnapshot,\n )\n }\n\n const baseCreateProjection = buildProjectionCreator({\n loadEvents,\n checkpoint: params.checkpoint,\n snapshot: params.projectionSnapshot,\n onReplay: params.onProjectionReplay,\n })\n\n const baseCreateProcessManager = buildProcessManagerCreator({\n loadEvents,\n checkpoint: params.checkpoint,\n onRefresh: params.onProcessManagerRefresh,\n })\n\n const getRelatedStreamEvents = (\n handlers: EventHandlers<any>,\n ): StreamEvents[] => {\n const relatedStreamEvents = new Map<string, Set<string>>()\n for (const handlerName of Object.keys(handlers)) {\n const sanitizedHandlerName = handlerName.replace(/^(on|after)/, '')\n if (!aggregatRootsByEvents.has(sanitizedHandlerName)) {\n throw new Error(\n `event handler ${handlerName} has no corresponding event in any aggregate root`,\n )\n }\n const {\n aggregateRoot: { type: aggregateRootName },\n eventType,\n } = aggregatRootsByEvents.get(sanitizedHandlerName)!\n if (!relatedStreamEvents.has(aggregateRootName)) {\n relatedStreamEvents.set(aggregateRootName, new Set())\n }\n relatedStreamEvents.get(aggregateRootName)!.add(eventType)\n }\n\n return Array.from(relatedStreamEvents, ([stream, events]) => ({\n stream,\n events: Array.from(events),\n }))\n }\n\n const initialize = async () => {\n initializing = true\n await Promise.all(\n projections.values().map((projection) => projection.init(true)),\n )\n await Promise.all(\n processManagers\n .values()\n .map((processManager) => processManager.init(true)),\n )\n resolveInitialized()\n }\n setImmediate(() => {\n if (allReplaying || params.autoInit === false) {\n return\n }\n\n initialize()\n })\n\n const api = {\n createProjection(name) {\n if (projections.has(name)) {\n throw new Error(`Projection ${name} is already registered`)\n }\n const api = baseCreateProjection(name)\n const internalApi = api as unknown as InternalProjection\n internalApi.setRelatedStreamEvents((handlers) =>\n getRelatedStreamEvents(handlers),\n )\n projections.set(name, internalApi)\n if (initializing) {\n internalApi.init(true)\n }\n return api\n },\n createProcessManager(name) {\n if (processManagers.has(name)) {\n throw new Error(`Process Manager ${name} is already registered`)\n }\n const api = baseCreateProcessManager(name)\n\n const internalApi = api as unknown as InternalProcessManager\n internalApi.setRelatedStreamEvents((handlers) =>\n getRelatedStreamEvents(handlers),\n )\n processManagers.set(name, internalApi)\n if (initializing) {\n internalApi.init(true)\n }\n return api\n },\n createEventListener(name) {\n if (eventListeners.has(name)) {\n throw new Error(`Event Listener ${name} is already registered`)\n }\n\n const api = createEventListener(name)\n\n const internalApi = api as unknown as InternalEventListener\n eventListeners.set(name, internalApi)\n return api\n },\n async isReady() {\n await initialized\n await Promise.all([\n ...projections.values().map((projection) => projection.isReady()),\n ...processManagers.values().map((projection) => projection.isReady()),\n ])\n },\n async rebuild() {\n allReplaying = true\n initializing = true\n const replayProjections = Array.from(projections.values()).filter(\n (projection) => projection.canReplay(),\n )\n const replayProcessManagers = Array.from(processManagers.values()).filter(\n (processManager) => processManager.hasState(),\n )\n\n await Promise.all([\n ...replayProjections.map((projection) => projection.init(false)),\n ...replayProcessManagers.map((projection) => projection.init(false)),\n ...replayProjections.map((projection) => projection.beginReplay()),\n ...replayProcessManagers.map((processManager) =>\n processManager.beginRefresh(),\n ),\n ])\n\n await withRefreshing(async () => {\n let index = 0\n for await (const event of loadEvents(null)) {\n index++\n await Promise.all([\n ...replayProjections.map((projection) =>\n projection.progressReplay(index, event),\n ),\n ...replayProcessManagers.map((processManager) =>\n processManager.progressRefresh(index, event, false),\n ),\n ...Array.from(eventListeners.values(), (listener) =>\n listener.apply(event),\n ),\n ])\n await Promise.all([\n ...replayProcessManagers.map((processManager) =>\n processManager.progressRefresh(index, event, true),\n ),\n ...Array.from(eventListeners.values(), (listener) =>\n listener.applyAfter(event),\n ),\n ])\n }\n })\n\n await Promise.all([\n ...replayProjections.map((projection) => projection.endReplay()),\n ...replayProcessManagers.map((processManager) =>\n processManager.endRefresh(),\n ),\n ])\n\n await Promise.all(\n projections.values().map(async (projection) => {\n if (!projection.canReplay()) {\n await projection.init(true)\n }\n }),\n )\n resolveInitialized()\n },\n async init() {\n if (initializing) {\n return api\n }\n await initialize()\n return api\n },\n getAggregateRoot(type) {\n return params.aggregateRoots.find(\n (aggregateRoot) => aggregateRoot.type === type,\n ) as any\n },\n async transaction(handler) {\n return transaction.run(handler)\n },\n } as EventStore<any, Root>\n\n return api\n}\n"
|
|
6
|
-
],
|
|
7
|
-
"mappings": "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",
|
|
8
|
-
"debugId": "D9F6BED8C771D2CD64756E2164756E21",
|
|
9
|
-
"names": []
|
|
10
|
-
}
|