@requence/event-sourcing 1.5.0 → 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/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-zznvzvnv.js → chunk-2wqpktzp.js} +31 -31
- package/dist/{chunk-zznvzvnv.js.map → chunk-2wqpktzp.js.map} +2 -2
- 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-kqh3q3fj.js → chunk-d6jqbrq2.js} +29 -29
- package/dist/{chunk-kqh3q3fj.js.map → chunk-d6jqbrq2.js.map} +2 -2
- package/dist/{chunk-7akf01zj.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-ak901ckt.js.map → chunk-mbxxvskx.js.map} +2 -2
- package/dist/{chunk-3251p253.js → chunk-nrhw3kde.js} +8 -8
- package/dist/{chunk-3251p253.js.map → chunk-nrhw3kde.js.map} +2 -2
- package/dist/{chunk-8edc30gz.js → chunk-pcggjrxr.js} +32 -32
- package/dist/{chunk-8edc30gz.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.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.js +12 -12
- package/dist/createProcessManager.js.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.js +31 -31
- package/dist/memory/index.js.map +2 -2
- 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.js +73 -73
- package/dist/surreal/index.js.map +2 -2
- package/dist/surreal/schema.js +8 -8
- package/dist/surreal/schema.js.map +1 -1
- 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 +1 -1
- package/src/createAggregateRoot.ts +22 -2
- package/src/lock.ts +17 -3
- package/src/redis/redisLock.ts +6 -2
- package/src/tests/aggregateRoot.spec.ts +42 -0
- package/dist/chunk-2fe8jjdc.js +0 -22
- package/dist/chunk-6q8mr1sg.js +0 -13
- package/dist/chunk-6yrb30rx.js +0 -22
- package/dist/chunk-7akf01zj.js.map +0 -10
- package/dist/chunk-ak901ckt.js +0 -67
- package/dist/chunk-dgzw1nj9.js.map +0 -10
- package/dist/chunk-jd4q8fcf.js +0 -11
- package/dist/chunk-ty9bhdvx.js.map +0 -10
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
CheckpointConcurrencyError2,
|
|
3
|
+
RefreshingSkipError2,
|
|
4
|
+
ProcessManagerEventHandlerExecutionError2
|
|
5
|
+
} from "./chunk-jw9e0fr0.js";
|
|
5
6
|
import {
|
|
6
|
-
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
createCheckpointApi2
|
|
8
|
+
} from "./chunk-nrhw3kde.js";
|
|
8
9
|
import {
|
|
9
|
-
|
|
10
|
-
|
|
10
|
+
isRefreshing2,
|
|
11
|
+
withRefreshing2
|
|
12
|
+
} from "./chunk-hmvwn02w.js";
|
|
11
13
|
import {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
RefreshingSkipError
|
|
15
|
-
} from "./chunk-391m4mfp.js";
|
|
14
|
+
clone2
|
|
15
|
+
} from "./chunk-fpjnk143.js";
|
|
16
16
|
|
|
17
17
|
// src/createProcessManager.ts
|
|
18
18
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
@@ -20,13 +20,13 @@ var processManagerInfoStore = new AsyncLocalStorage;
|
|
|
20
20
|
function withProcessManagerInfo(info, handler) {
|
|
21
21
|
return processManagerInfoStore.run(info, handler);
|
|
22
22
|
}
|
|
23
|
-
function
|
|
23
|
+
function getProcessManagerInfo2() {
|
|
24
24
|
return processManagerInfoStore.getStore();
|
|
25
25
|
}
|
|
26
|
-
function
|
|
27
|
-
return Boolean(
|
|
26
|
+
function isInsideProcessManager2() {
|
|
27
|
+
return Boolean(getProcessManagerInfo2());
|
|
28
28
|
}
|
|
29
|
-
function
|
|
29
|
+
function buildProcessManagerCreator2(params) {
|
|
30
30
|
return (name, options) => {
|
|
31
31
|
let idle = true;
|
|
32
32
|
let createEventHandlers = () => ({});
|
|
@@ -57,7 +57,7 @@ function buildProcessManagerCreator(params) {
|
|
|
57
57
|
const unlocked = !exclusive ? Promise.resolve() : locks.get(event.streamId)?.catch(() => {}) ?? Promise.resolve();
|
|
58
58
|
const runner = (async () => {
|
|
59
59
|
await unlocked;
|
|
60
|
-
const refreshing =
|
|
60
|
+
const refreshing = isRefreshing2();
|
|
61
61
|
const useCas = hasState && !after && !hydrating && !refreshing;
|
|
62
62
|
while (true) {
|
|
63
63
|
const currentHandler = after ? createAfterEffects(state)[`after${event.type}`] : createEventHandlers(state)[`on${event.type}`];
|
|
@@ -69,7 +69,7 @@ function buildProcessManagerCreator(params) {
|
|
|
69
69
|
try {
|
|
70
70
|
await currentHandler(event, { refreshing });
|
|
71
71
|
} catch (error) {
|
|
72
|
-
if (error instanceof
|
|
72
|
+
if (error instanceof RefreshingSkipError2) {
|
|
73
73
|
if (refreshing) {
|
|
74
74
|
return;
|
|
75
75
|
}
|
|
@@ -78,18 +78,18 @@ function buildProcessManagerCreator(params) {
|
|
|
78
78
|
if (!(error instanceof Error)) {
|
|
79
79
|
throw error;
|
|
80
80
|
}
|
|
81
|
-
throw new
|
|
81
|
+
throw new ProcessManagerEventHandlerExecutionError2(name, after ? `after${event.type}` : `on${event.type}`, event, error);
|
|
82
82
|
}
|
|
83
83
|
});
|
|
84
84
|
try {
|
|
85
85
|
await checkpointApi.upsert(event, { state }, useCas ? "cas" : "monotonic");
|
|
86
86
|
break;
|
|
87
87
|
} catch (error) {
|
|
88
|
-
if (!(error instanceof
|
|
88
|
+
if (!(error instanceof CheckpointConcurrencyError2)) {
|
|
89
89
|
throw error;
|
|
90
90
|
}
|
|
91
91
|
const checkpoint = await checkpointApi.load();
|
|
92
|
-
state = checkpoint?.metadata?.state != null ?
|
|
92
|
+
state = checkpoint?.metadata?.state != null ? clone2(checkpoint.metadata.state) : clone2(initialState);
|
|
93
93
|
}
|
|
94
94
|
}
|
|
95
95
|
})();
|
|
@@ -119,10 +119,10 @@ function buildProcessManagerCreator(params) {
|
|
|
119
119
|
}
|
|
120
120
|
const checkpoint = await checkpointApi.load();
|
|
121
121
|
if (checkpoint) {
|
|
122
|
-
state = checkpoint.metadata?.state != null ?
|
|
122
|
+
state = checkpoint.metadata?.state != null ? clone2(checkpoint.metadata.state) : clone2(initialState);
|
|
123
123
|
lastEventPosition = checkpoint.lastEventPosition;
|
|
124
124
|
} else {
|
|
125
|
-
state =
|
|
125
|
+
state = clone2(initialState);
|
|
126
126
|
lastEventPosition = -1;
|
|
127
127
|
}
|
|
128
128
|
sessionActive = true;
|
|
@@ -141,8 +141,8 @@ function buildProcessManagerCreator(params) {
|
|
|
141
141
|
await apply(event, true);
|
|
142
142
|
},
|
|
143
143
|
withState(nextState) {
|
|
144
|
-
state =
|
|
145
|
-
initialState =
|
|
144
|
+
state = clone2(nextState);
|
|
145
|
+
initialState = clone2(nextState);
|
|
146
146
|
hasState = true;
|
|
147
147
|
return api;
|
|
148
148
|
},
|
|
@@ -190,7 +190,7 @@ function buildProcessManagerCreator(params) {
|
|
|
190
190
|
await hydrated;
|
|
191
191
|
if (!sessionActive && hasState) {
|
|
192
192
|
const checkpoint = await params.checkpoint.get("processManager", name);
|
|
193
|
-
return checkpoint?.metadata?.state ??
|
|
193
|
+
return checkpoint?.metadata?.state ?? clone2(initialState);
|
|
194
194
|
}
|
|
195
195
|
return state;
|
|
196
196
|
},
|
|
@@ -200,7 +200,7 @@ function buildProcessManagerCreator(params) {
|
|
|
200
200
|
...createEventHandlers(null),
|
|
201
201
|
...createAfterEffects(null)
|
|
202
202
|
});
|
|
203
|
-
checkpointApi =
|
|
203
|
+
checkpointApi = createCheckpointApi2({
|
|
204
204
|
...params.checkpoint,
|
|
205
205
|
name,
|
|
206
206
|
relatedStreamEvents,
|
|
@@ -230,7 +230,7 @@ function buildProcessManagerCreator(params) {
|
|
|
230
230
|
$inferState: null
|
|
231
231
|
};
|
|
232
232
|
async function refresh() {
|
|
233
|
-
await
|
|
233
|
+
await withRefreshing2(async () => {
|
|
234
234
|
await api.beginRefresh();
|
|
235
235
|
await checkpointApi.rehydrated({
|
|
236
236
|
getMetadata() {
|
|
@@ -247,6 +247,6 @@ function buildProcessManagerCreator(params) {
|
|
|
247
247
|
};
|
|
248
248
|
}
|
|
249
249
|
|
|
250
|
-
export {
|
|
250
|
+
export { getProcessManagerInfo2, isInsideProcessManager2, buildProcessManagerCreator2 };
|
|
251
251
|
|
|
252
|
-
//# debugId=
|
|
252
|
+
//# debugId=81E4DAF885A8BB5964756E2164756E21
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"sourcesContent": [
|
|
5
5
|
"import { AsyncLocalStorage } from 'node:async_hooks'\n\nimport type { SettledOptions } from './createAggregateRoot.ts'\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\n/**\n * Options for `createProcessManager`.\n *\n * `settled` — default {@link SettledOptions} applied when the process manager\n * auto-settles the streams its handlers dispatched commands on (explicit\n * `settled()` calls are not allowed inside a process manager).\n */\nexport type ProcessManagerOptions = {\n settled?: SettledOptions\n}\n\ntype ProcessManagerInfo = {\n name: string\n event: BaseOutputEvent\n settledDefaults?: SettledOptions\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, options?: ProcessManagerOptions): 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 settledDefaults: options?.settled,\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) {\n return\n }\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) {\n return\n }\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('processManager', name)\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
6
|
],
|
|
7
|
-
"mappings": ";;;;;;;;;;;;;;;;;AAAA;AA0CA,IAAM,0BAA0B,IAAI;AAEpC,SAAS,sBAAsB,CAC7B,MACA,SACA;AAAA,EACA,OAAO,wBAAwB,IAAI,MAAM,OAAO;AAAA;AAG3C,SAAS,
|
|
8
|
-
"debugId": "
|
|
7
|
+
"mappings": "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",
|
|
8
|
+
"debugId": "81E4DAF885A8BB5964756E2164756E21",
|
|
9
9
|
"names": []
|
|
10
10
|
}
|
|
@@ -1,34 +1,37 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
2
|
+
ConcurrencyError2,
|
|
3
|
+
ValidationError2,
|
|
4
|
+
EventValidationError2,
|
|
5
|
+
InfiniteLoopError2,
|
|
6
|
+
CommandError2
|
|
7
|
+
} from "./chunk-jw9e0fr0.js";
|
|
6
8
|
import {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
} from "./chunk-tfy01fah.js";
|
|
9
|
+
isRefreshing2
|
|
10
|
+
} from "./chunk-hmvwn02w.js";
|
|
10
11
|
import {
|
|
11
|
-
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
clone2
|
|
13
|
+
} from "./chunk-fpjnk143.js";
|
|
14
|
+
import {
|
|
15
|
+
getProcessManagerInfo2
|
|
16
|
+
} from "./chunk-d6jqbrq2.js";
|
|
13
17
|
import {
|
|
14
18
|
createSnapshotGenerator
|
|
15
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-fxb9fbvz.js";
|
|
16
20
|
import {
|
|
17
|
-
|
|
18
|
-
} from "./chunk-
|
|
21
|
+
getProjectionInfo2
|
|
22
|
+
} from "./chunk-2wqpktzp.js";
|
|
19
23
|
import {
|
|
20
|
-
|
|
21
|
-
} from "./chunk-
|
|
24
|
+
DEFAULT_LOCK_TTL2
|
|
25
|
+
} from "./chunk-j4mwjx07.js";
|
|
22
26
|
import {
|
|
23
|
-
|
|
24
|
-
|
|
27
|
+
normalizeArray2,
|
|
28
|
+
awaitAll2
|
|
29
|
+
} from "./chunk-c7sytwpp.js";
|
|
25
30
|
import {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
ValidationError
|
|
31
|
-
} from "./chunk-391m4mfp.js";
|
|
31
|
+
unwrapEvent2,
|
|
32
|
+
handleEventError2,
|
|
33
|
+
wrappedEventBuilder2
|
|
34
|
+
} from "./chunk-zkz6ew8c.js";
|
|
32
35
|
|
|
33
36
|
// src/createAggregateRoot.ts
|
|
34
37
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
@@ -55,7 +58,7 @@ var snapshotSchema = z.object({
|
|
|
55
58
|
lastEventPosition: z.int(),
|
|
56
59
|
metadata: z.record(z.string(), z.unknown()).optional()
|
|
57
60
|
});
|
|
58
|
-
function
|
|
61
|
+
function createAggregateRoot2(type) {
|
|
59
62
|
let initialState = null;
|
|
60
63
|
let createEventHandlers = () => ({});
|
|
61
64
|
let loadEvents;
|
|
@@ -78,7 +81,7 @@ function createAggregateRoot(type) {
|
|
|
78
81
|
if (snapshot) {
|
|
79
82
|
const result = snapshotSchema.safeParse(snapshot);
|
|
80
83
|
if (!result.success) {
|
|
81
|
-
throw new
|
|
84
|
+
throw new ValidationError2("loaded aggregate root snapshot does not comply with schema", result.error);
|
|
82
85
|
}
|
|
83
86
|
snapshotApi.internalApply(result.data);
|
|
84
87
|
position = snapshot.lastEventPosition;
|
|
@@ -108,6 +111,7 @@ function createAggregateRoot(type) {
|
|
|
108
111
|
let downstreamSettledPromise = () => Promise.resolve();
|
|
109
112
|
let releaseLock;
|
|
110
113
|
let extendLock;
|
|
114
|
+
let lockTtl;
|
|
111
115
|
const warnReleaseLock = () => {
|
|
112
116
|
if (releasedAfterChain) {
|
|
113
117
|
console.warn(`aggregate root for ${type}:${streamId} was open too long`);
|
|
@@ -140,21 +144,30 @@ function createAggregateRoot(type) {
|
|
|
140
144
|
let commandChain = createLock([type, streamId]).then((lock) => {
|
|
141
145
|
releaseLock = lock.release;
|
|
142
146
|
extendLock = lock.extend;
|
|
147
|
+
lockTtl = lock.ttl;
|
|
143
148
|
return [];
|
|
144
149
|
});
|
|
150
|
+
const keepLockAlive = async (work) => {
|
|
151
|
+
const timer = setInterval(() => void extendLock().catch(() => false), (lockTtl ?? DEFAULT_LOCK_TTL2) / 4);
|
|
152
|
+
try {
|
|
153
|
+
return await work();
|
|
154
|
+
} finally {
|
|
155
|
+
clearInterval(timer);
|
|
156
|
+
}
|
|
157
|
+
};
|
|
145
158
|
let commandChainTouched = false;
|
|
146
159
|
let releasedAfterChain = false;
|
|
147
160
|
let transactionDelay;
|
|
148
161
|
const stateReady = Promise.withResolvers();
|
|
149
|
-
const rawCommands = createCommands(state,
|
|
162
|
+
const rawCommands = createCommands(state, wrappedEventBuilder2, {
|
|
150
163
|
streamId,
|
|
151
164
|
extendLock
|
|
152
165
|
});
|
|
153
166
|
const commands = Object.fromEntries(Object.entries(rawCommands).map(([commandName, commandFn]) => [
|
|
154
167
|
commandName,
|
|
155
168
|
(...args) => {
|
|
156
|
-
if (
|
|
157
|
-
return
|
|
169
|
+
if (isRefreshing2()) {
|
|
170
|
+
return api.commands;
|
|
158
171
|
}
|
|
159
172
|
dispatchedCommands.push({ name: commandName, args });
|
|
160
173
|
const commandId = crypto.randomUUID();
|
|
@@ -164,11 +177,11 @@ function createAggregateRoot(type) {
|
|
|
164
177
|
if (previousEvents instanceof Error) {
|
|
165
178
|
return previousEvents;
|
|
166
179
|
}
|
|
167
|
-
const events = (await
|
|
180
|
+
const events = (await normalizeArray2(commandFn.apply(rawCommands, args), () => extendLock())).filter((event) => Boolean(event));
|
|
168
181
|
const baseInputEvents = await Promise.all(events.map(async (event) => {
|
|
169
182
|
event.withAdditionalMetadata({ commandName });
|
|
170
183
|
event.withDefaultCausationId(commandId);
|
|
171
|
-
const unwrappedEvent =
|
|
184
|
+
const unwrappedEvent = unwrapEvent2(event);
|
|
172
185
|
const eventVersions = registeredEvents.get(unwrappedEvent.type);
|
|
173
186
|
if (!eventVersions) {
|
|
174
187
|
throw new Error(`cannot append unknown event ${unwrappedEvent.type}`);
|
|
@@ -177,8 +190,8 @@ function createAggregateRoot(type) {
|
|
|
177
190
|
const schema = eventVersions.get(latestVersion);
|
|
178
191
|
const result = schema.safeParse(unwrappedEvent.payload);
|
|
179
192
|
if (!result.success) {
|
|
180
|
-
const error = new
|
|
181
|
-
await
|
|
193
|
+
const error = new EventValidationError2(`payload does not comply with schema for event ${unwrappedEvent.type}@${latestVersion} at stream ${streamId}`, result.error);
|
|
194
|
+
await handleEventError2(event, error);
|
|
182
195
|
throw error;
|
|
183
196
|
}
|
|
184
197
|
unwrappedEvent.payload = result.data;
|
|
@@ -189,10 +202,10 @@ function createAggregateRoot(type) {
|
|
|
189
202
|
}));
|
|
190
203
|
const eventHandlers = createEventHandlers(state);
|
|
191
204
|
for (const event of baseInputEvents) {
|
|
192
|
-
const processManagerInfo =
|
|
205
|
+
const processManagerInfo = getProcessManagerInfo2();
|
|
193
206
|
if (processManagerInfo) {
|
|
194
207
|
if (processManagerInfo.event.streamId === streamId && processManagerInfo.event.streamType === type && processManagerInfo.event.type === event.type && deepEqual(processManagerInfo.event.payload, event.payload)) {
|
|
195
|
-
return new
|
|
208
|
+
return new InfiniteLoopError2(`Infinite loop detected. Process Manager "${processManagerInfo.name}" listens and emits same event "${event.type}" for stream ${type}:${streamId}, causing a recurring event cycle`);
|
|
196
209
|
}
|
|
197
210
|
}
|
|
198
211
|
await eventHandlers[`on${event.type}`]?.({
|
|
@@ -206,10 +219,10 @@ function createAggregateRoot(type) {
|
|
|
206
219
|
if (!(error instanceof Error)) {
|
|
207
220
|
throw error;
|
|
208
221
|
}
|
|
209
|
-
const commandError = new
|
|
222
|
+
const commandError = new CommandError2(type, commandName, streamId, error);
|
|
210
223
|
for (const [ErrorType, handler] of errorHandlers) {
|
|
211
224
|
if (error instanceof ErrorType) {
|
|
212
|
-
return new
|
|
225
|
+
return new CommandError2(type, commandName, streamId, handler(commandError));
|
|
213
226
|
}
|
|
214
227
|
}
|
|
215
228
|
return commandError;
|
|
@@ -241,7 +254,7 @@ function createAggregateRoot(type) {
|
|
|
241
254
|
});
|
|
242
255
|
}
|
|
243
256
|
});
|
|
244
|
-
return
|
|
257
|
+
return api.commands;
|
|
245
258
|
}
|
|
246
259
|
]));
|
|
247
260
|
setImmediate(() => {
|
|
@@ -253,9 +266,9 @@ function createAggregateRoot(type) {
|
|
|
253
266
|
});
|
|
254
267
|
}
|
|
255
268
|
});
|
|
256
|
-
const
|
|
269
|
+
const api = {
|
|
257
270
|
load(filter) {
|
|
258
|
-
commandChain = commandChain.then(() => loadUntil(state, snapshotApi, streamId, undefined, filter)).then((loadedVersion) => {
|
|
271
|
+
commandChain = commandChain.then(() => keepLockAlive(() => loadUntil(state, snapshotApi, streamId, undefined, filter))).then((loadedVersion) => {
|
|
259
272
|
version = loadedVersion;
|
|
260
273
|
return [];
|
|
261
274
|
});
|
|
@@ -265,7 +278,7 @@ function createAggregateRoot(type) {
|
|
|
265
278
|
async state() {
|
|
266
279
|
const maybeError = await Promise.race([
|
|
267
280
|
stateReady.promise,
|
|
268
|
-
|
|
281
|
+
awaitAll2(() => commandChain)
|
|
269
282
|
]);
|
|
270
283
|
if (maybeError) {
|
|
271
284
|
throw maybeError;
|
|
@@ -273,7 +286,7 @@ function createAggregateRoot(type) {
|
|
|
273
286
|
return state;
|
|
274
287
|
},
|
|
275
288
|
async settled(options) {
|
|
276
|
-
const parentProcessManager =
|
|
289
|
+
const parentProcessManager = getProcessManagerInfo2();
|
|
277
290
|
if (parentProcessManager) {
|
|
278
291
|
const error = new Error(`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 }).`);
|
|
279
292
|
commandChain = commandChain.then(() => error);
|
|
@@ -286,11 +299,11 @@ function createAggregateRoot(type) {
|
|
|
286
299
|
}
|
|
287
300
|
const maxRetries = options?.maxRetries ?? 0;
|
|
288
301
|
try {
|
|
289
|
-
await
|
|
302
|
+
await awaitAll2(() => commandChain);
|
|
290
303
|
} catch (error) {
|
|
291
|
-
if (maxRetries > 0 && error instanceof
|
|
304
|
+
if (maxRetries > 0 && error instanceof ConcurrencyError2) {
|
|
292
305
|
await releaseLock?.();
|
|
293
|
-
const retryStream = dispatchContext(() => transaction.exit(() => downstreamRootsPromiseStore.exit(() => createStream(
|
|
306
|
+
const retryStream = dispatchContext(() => transaction.exit(() => downstreamRootsPromiseStore.exit(() => createStream(clone2(initialState), streamId, {
|
|
294
307
|
load: true,
|
|
295
308
|
filter: config.filter,
|
|
296
309
|
replayCommands: dispatchedCommands,
|
|
@@ -304,30 +317,30 @@ function createAggregateRoot(type) {
|
|
|
304
317
|
throw error;
|
|
305
318
|
}
|
|
306
319
|
await downstreamSettledPromise();
|
|
307
|
-
return
|
|
320
|
+
return api.commands;
|
|
308
321
|
},
|
|
309
322
|
transformError(error, handler) {
|
|
310
323
|
errorHandlers.set(error, handler);
|
|
311
|
-
return
|
|
324
|
+
return api.commands;
|
|
312
325
|
},
|
|
313
326
|
streamId
|
|
314
327
|
}
|
|
315
328
|
};
|
|
316
|
-
const autoSettleOptions =
|
|
317
|
-
registerRootPromiseToUpstream(() =>
|
|
318
|
-
transaction.after(() =>
|
|
329
|
+
const autoSettleOptions = getProcessManagerInfo2()?.settledDefaults ?? transaction.settledDefaults;
|
|
330
|
+
registerRootPromiseToUpstream(() => api.commands.settled(autoSettleOptions));
|
|
331
|
+
transaction.after(() => api.commands.settled(autoSettleOptions));
|
|
319
332
|
if (config.load) {
|
|
320
|
-
|
|
333
|
+
api.load(config.filter);
|
|
321
334
|
}
|
|
322
335
|
for (const { name, args } of config.replayCommands ?? []) {
|
|
323
|
-
|
|
336
|
+
api.commands[name](...args);
|
|
324
337
|
}
|
|
325
|
-
return
|
|
338
|
+
return api;
|
|
326
339
|
};
|
|
327
340
|
const api = {
|
|
328
341
|
type,
|
|
329
342
|
withInitialState: (state) => {
|
|
330
|
-
initialState =
|
|
343
|
+
initialState = clone2(state);
|
|
331
344
|
return api;
|
|
332
345
|
},
|
|
333
346
|
withCommands(handlers) {
|
|
@@ -341,7 +354,7 @@ function createAggregateRoot(type) {
|
|
|
341
354
|
},
|
|
342
355
|
withEvents(handler) {
|
|
343
356
|
const eventMap = typeof handler === "function" ? handler({ version: (version, schema) => ({ version, schema }), z }) : handler;
|
|
344
|
-
for (const [
|
|
357
|
+
for (const [type, config] of Object.entries(eventMap)) {
|
|
345
358
|
const versions = Array.isArray(config) ? config : [config];
|
|
346
359
|
for (const v of versions) {
|
|
347
360
|
let schema;
|
|
@@ -353,13 +366,13 @@ function createAggregateRoot(type) {
|
|
|
353
366
|
schema = v;
|
|
354
367
|
version = 0;
|
|
355
368
|
}
|
|
356
|
-
if (registeredEvents.get(
|
|
357
|
-
throw new Error(`event ${
|
|
369
|
+
if (registeredEvents.get(type)?.has(version)) {
|
|
370
|
+
throw new Error(`event ${type} is already registered in version ${version}`);
|
|
358
371
|
}
|
|
359
|
-
if (!registeredEvents.has(
|
|
360
|
-
registeredEvents.set(
|
|
372
|
+
if (!registeredEvents.has(type)) {
|
|
373
|
+
registeredEvents.set(type, new Map);
|
|
361
374
|
}
|
|
362
|
-
registeredEvents.get(
|
|
375
|
+
registeredEvents.get(type).set(version, schema);
|
|
363
376
|
}
|
|
364
377
|
}
|
|
365
378
|
return api;
|
|
@@ -376,11 +389,11 @@ function createAggregateRoot(type) {
|
|
|
376
389
|
if (!loadEvents) {
|
|
377
390
|
throw new Error(`aggregate root ${type} is not linked to an event store`);
|
|
378
391
|
}
|
|
379
|
-
const parentProjectionName =
|
|
392
|
+
const parentProjectionName = getProjectionInfo2()?.name;
|
|
380
393
|
if (parentProjectionName) {
|
|
381
394
|
throw new Error(`aggregateRoot.newStream() cannot be called inside a projection. Attempted on aggregate stream ${type} within Projection ${parentProjectionName}.`);
|
|
382
395
|
}
|
|
383
|
-
return createStream(
|
|
396
|
+
return createStream(clone2(initialState), id ?? crypto.randomUUID(), {
|
|
384
397
|
load: false
|
|
385
398
|
}).commands;
|
|
386
399
|
},
|
|
@@ -388,11 +401,11 @@ function createAggregateRoot(type) {
|
|
|
388
401
|
if (!loadEvents) {
|
|
389
402
|
throw new Error(`aggregate root ${type} is not linked to an event store`);
|
|
390
403
|
}
|
|
391
|
-
const parentProjectionName =
|
|
404
|
+
const parentProjectionName = getProjectionInfo2()?.name;
|
|
392
405
|
if (parentProjectionName) {
|
|
393
406
|
throw new Error(`aggregateRoot.loadStream("${id}") cannot be called inside a projection. Attempted on aggregate stream ${type} within Projection ${parentProjectionName}.`);
|
|
394
407
|
}
|
|
395
|
-
return createStream(
|
|
408
|
+
return createStream(clone2(initialState), id, {
|
|
396
409
|
load: true,
|
|
397
410
|
filter
|
|
398
411
|
}).commands;
|
|
@@ -416,6 +429,6 @@ function createAggregateRoot(type) {
|
|
|
416
429
|
return api;
|
|
417
430
|
}
|
|
418
431
|
|
|
419
|
-
export {
|
|
432
|
+
export { createAggregateRoot2 };
|
|
420
433
|
|
|
421
|
-
//# debugId=
|
|
434
|
+
//# debugId=3DB62A08BB7BF61F64756E2164756E21
|
|
@@ -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
|
+
}
|