@requence/event-sourcing 0.0.1 → 1.0.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.
Files changed (155) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +81 -0
  3. package/dist/chunk-24xjphpk.js +51 -0
  4. package/dist/chunk-24xjphpk.js.map +10 -0
  5. package/dist/chunk-3t1vzbab.js +88 -0
  6. package/dist/chunk-3t1vzbab.js.map +10 -0
  7. package/dist/chunk-6q8mr1sg.js +13 -0
  8. package/dist/chunk-6q8mr1sg.js.map +10 -0
  9. package/dist/chunk-9psg50cb.js +22 -0
  10. package/dist/chunk-9psg50cb.js.map +10 -0
  11. package/dist/chunk-dgzw1nj9.js +50 -0
  12. package/dist/chunk-dgzw1nj9.js.map +10 -0
  13. package/dist/chunk-gq80tgvf.js +70 -0
  14. package/dist/chunk-gq80tgvf.js.map +10 -0
  15. package/dist/chunk-jd4q8fcf.js +11 -0
  16. package/dist/chunk-jd4q8fcf.js.map +10 -0
  17. package/dist/chunk-m07vf8q9.js +210 -0
  18. package/dist/chunk-m07vf8q9.js.map +10 -0
  19. package/dist/chunk-ncpk70p4.js +313 -0
  20. package/dist/chunk-ncpk70p4.js.map +10 -0
  21. package/dist/chunk-pmfzjavb.js +49 -0
  22. package/dist/chunk-pmfzjavb.js.map +10 -0
  23. package/dist/chunk-qdczt68t.js +84 -0
  24. package/dist/chunk-qdczt68t.js.map +10 -0
  25. package/dist/chunk-tfy01fah.js +34 -0
  26. package/dist/chunk-tfy01fah.js.map +10 -0
  27. package/dist/chunk-tkvj6x8k.js +389 -0
  28. package/dist/chunk-tkvj6x8k.js.map +10 -0
  29. package/dist/chunk-ty9bhdvx.js +53 -0
  30. package/dist/chunk-ty9bhdvx.js.map +10 -0
  31. package/dist/chunk-wmz6a1jk.js +233 -0
  32. package/dist/chunk-wmz6a1jk.js.map +10 -0
  33. package/dist/chunk-x90g388y.js +22 -0
  34. package/dist/chunk-x90g388y.js.map +10 -0
  35. package/dist/chunk-z388cd25.js +91 -0
  36. package/dist/chunk-z388cd25.js.map +10 -0
  37. package/dist/chunk-zf3x573k.js +65 -0
  38. package/dist/chunk-zf3x573k.js.map +10 -0
  39. package/dist/createAggregateRoot.d.ts +191 -0
  40. package/dist/createAggregateRoot.d.ts.map +1 -0
  41. package/dist/createAggregateRoot.js +18 -0
  42. package/dist/createAggregateRoot.js.map +9 -0
  43. package/dist/createCheckpointApi.d.ts +38 -0
  44. package/dist/createCheckpointApi.d.ts.map +1 -0
  45. package/dist/createCheckpointApi.js +9 -0
  46. package/dist/createCheckpointApi.js.map +9 -0
  47. package/dist/createEventListener.d.ts +46 -0
  48. package/dist/createEventListener.d.ts.map +1 -0
  49. package/dist/createEventListener.js +12 -0
  50. package/dist/createEventListener.js.map +9 -0
  51. package/dist/createEventStore.d.ts +57 -0
  52. package/dist/createEventStore.d.ts.map +1 -0
  53. package/dist/createEventStore.js +20 -0
  54. package/dist/createEventStore.js.map +9 -0
  55. package/dist/createProcessManager.d.ts +70 -0
  56. package/dist/createProcessManager.d.ts.map +1 -0
  57. package/dist/createProcessManager.js +16 -0
  58. package/dist/createProcessManager.js.map +9 -0
  59. package/dist/createProjection.d.ts +120 -0
  60. package/dist/createProjection.d.ts.map +1 -0
  61. package/dist/createProjection.js +16 -0
  62. package/dist/createProjection.js.map +9 -0
  63. package/dist/drizzle/index.d.ts +449 -0
  64. package/dist/drizzle/index.d.ts.map +1 -0
  65. package/dist/drizzle/index.js +325 -0
  66. package/dist/drizzle/index.js.map +10 -0
  67. package/dist/drizzle/postgres.d.ts +686 -0
  68. package/dist/drizzle/postgres.d.ts.map +1 -0
  69. package/dist/drizzle/postgres.js +18 -0
  70. package/dist/drizzle/postgres.js.map +9 -0
  71. package/dist/errors.d.ts +53 -0
  72. package/dist/errors.d.ts.map +1 -0
  73. package/dist/errors.js +26 -0
  74. package/dist/errors.js.map +9 -0
  75. package/dist/index.d.ts +15 -0
  76. package/dist/index.d.ts.map +1 -0
  77. package/dist/index.js +73 -0
  78. package/dist/index.js.map +9 -0
  79. package/dist/lock.d.ts +6 -0
  80. package/dist/lock.d.ts.map +1 -0
  81. package/dist/lock.js +8 -0
  82. package/dist/lock.js.map +9 -0
  83. package/dist/memory/index.d.ts +15 -0
  84. package/dist/memory/index.d.ts.map +1 -0
  85. package/dist/memory/index.js +178 -0
  86. package/dist/memory/index.js.map +10 -0
  87. package/dist/redis/index.d.ts +2 -0
  88. package/dist/redis/index.d.ts.map +1 -0
  89. package/dist/redis/index.js +8 -0
  90. package/dist/redis/index.js.map +9 -0
  91. package/dist/redis/redisLock.d.ts +4 -0
  92. package/dist/redis/redisLock.d.ts.map +1 -0
  93. package/dist/redis/redisLock.js +8 -0
  94. package/dist/redis/redisLock.js.map +9 -0
  95. package/dist/refresh.d.ts +4 -0
  96. package/dist/refresh.d.ts.map +1 -0
  97. package/dist/refresh.js +13 -0
  98. package/dist/refresh.js.map +9 -0
  99. package/dist/replay.d.ts +4 -0
  100. package/dist/replay.d.ts.map +1 -0
  101. package/dist/replay.js +13 -0
  102. package/dist/replay.js.map +9 -0
  103. package/dist/snapshotGenerator.d.ts +79 -0
  104. package/dist/snapshotGenerator.d.ts.map +1 -0
  105. package/dist/snapshotGenerator.js +9 -0
  106. package/dist/snapshotGenerator.js.map +9 -0
  107. package/dist/superjson.d.ts +5 -0
  108. package/dist/superjson.d.ts.map +1 -0
  109. package/dist/superjson.js +12 -0
  110. package/dist/superjson.js.map +9 -0
  111. package/dist/transaction.d.ts +13 -0
  112. package/dist/transaction.d.ts.map +1 -0
  113. package/dist/transaction.js +8 -0
  114. package/dist/transaction.js.map +9 -0
  115. package/dist/utilityTypes.d.js +2 -0
  116. package/dist/utilityTypes.d.js.map +9 -0
  117. package/dist/utils.d.ts +4 -0
  118. package/dist/utils.d.ts.map +1 -0
  119. package/dist/utils.js +10 -0
  120. package/dist/utils.js.map +9 -0
  121. package/dist/wrappedEventBuilder.d.ts +37 -0
  122. package/dist/wrappedEventBuilder.d.ts.map +1 -0
  123. package/dist/wrappedEventBuilder.js +12 -0
  124. package/dist/wrappedEventBuilder.js.map +9 -0
  125. package/package.json +87 -1
  126. package/src/createAggregateRoot.ts +902 -0
  127. package/src/createCheckpointApi.ts +106 -0
  128. package/src/createEventListener.ts +118 -0
  129. package/src/createEventStore.ts +446 -0
  130. package/src/createProcessManager.ts +363 -0
  131. package/src/createProjection.ts +577 -0
  132. package/src/drizzle/index.ts +449 -0
  133. package/src/drizzle/postgres.ts +120 -0
  134. package/src/errors.ts +85 -0
  135. package/src/index.ts +45 -0
  136. package/src/lock.ts +58 -0
  137. package/src/memory/index.ts +224 -0
  138. package/src/redis/index.ts +1 -0
  139. package/src/redis/redisLock.ts +61 -0
  140. package/src/refresh.ts +19 -0
  141. package/src/replay.ts +19 -0
  142. package/src/snapshotGenerator.ts +190 -0
  143. package/src/superjson.ts +11 -0
  144. package/src/tests/aggregateRoot.spec.ts +532 -0
  145. package/src/tests/eventListener.spec.ts +57 -0
  146. package/src/tests/eventStore.spec.ts +86 -0
  147. package/src/tests/processManager.spec.ts +185 -0
  148. package/src/tests/projection.spec.ts +511 -0
  149. package/src/tests/projectionProcessManager.spec.ts +203 -0
  150. package/src/tests/setup.ts +230 -0
  151. package/src/tests/transaction.spec.ts +185 -0
  152. package/src/transaction.ts +93 -0
  153. package/src/utilityTypes.d.ts +110 -0
  154. package/src/utils.ts +43 -0
  155. package/src/wrappedEventBuilder.ts +181 -0
@@ -0,0 +1,210 @@
1
+ import {
2
+ clone
3
+ } from "./chunk-6q8mr1sg.js";
4
+ import {
5
+ createCheckpointApi
6
+ } from "./chunk-zf3x573k.js";
7
+ import {
8
+ isRefreshing,
9
+ withRefreshing
10
+ } from "./chunk-9psg50cb.js";
11
+ import {
12
+ ProcessManagerEventHandlerExecutionError,
13
+ RefreshingSkipError
14
+ } from "./chunk-qdczt68t.js";
15
+
16
+ // src/createProcessManager.ts
17
+ import { AsyncLocalStorage } from "node:async_hooks";
18
+ var processManagerInfoStore = new AsyncLocalStorage;
19
+ function withProcessManagerInfo(info, handler) {
20
+ return processManagerInfoStore.run(info, handler);
21
+ }
22
+ function getProcessManagerInfo() {
23
+ return processManagerInfoStore.getStore();
24
+ }
25
+ function isInsideProcessManager() {
26
+ return Boolean(getProcessManagerInfo());
27
+ }
28
+ function buildProcessManagerCreator(params) {
29
+ return (name) => {
30
+ let idle = true;
31
+ let createEventHandlers = () => ({});
32
+ let createAfterEffects = () => ({});
33
+ let hasState = false;
34
+ let state = null;
35
+ let initialState = null;
36
+ let exclusive = true;
37
+ let generateRelatedStreamEvents;
38
+ let checkpointApi;
39
+ let lastEventPosition = -1;
40
+ const { promise: hydrated, resolve: resolveHydrated } = Promise.withResolvers();
41
+ const locks = new Map;
42
+ const apply = async (event, after, hydrating = false) => {
43
+ const handler = after ? createAfterEffects(state)[`after${event.type}`] : createEventHandlers(state)[`on${event.type}`];
44
+ if (!handler) {
45
+ return Promise.resolve();
46
+ }
47
+ if (hydrating) {
48
+ lastEventPosition = event.position;
49
+ } else {
50
+ await hydrated;
51
+ if (event.position <= lastEventPosition) {
52
+ return;
53
+ }
54
+ }
55
+ const unlocked = !exclusive ? Promise.resolve() : locks.get(event.streamId)?.catch(() => {}) ?? Promise.resolve();
56
+ const runner = (async () => {
57
+ await unlocked;
58
+ const refreshing = isRefreshing();
59
+ await withProcessManagerInfo({
60
+ name,
61
+ event
62
+ }, async () => {
63
+ try {
64
+ await handler(event, { refreshing });
65
+ } catch (error) {
66
+ if (error instanceof RefreshingSkipError) {
67
+ if (refreshing) {
68
+ return;
69
+ }
70
+ throw new Error("RefreshingSkipError should never be thrown outside refresh");
71
+ }
72
+ if (!(error instanceof Error)) {
73
+ throw error;
74
+ }
75
+ throw new ProcessManagerEventHandlerExecutionError(name, after ? `after${event.type}` : `on${event.type}`, event, error);
76
+ }
77
+ });
78
+ await checkpointApi.upsert(event, { state });
79
+ })();
80
+ if (exclusive) {
81
+ locks.set(event.streamId, runner);
82
+ runner.finally(() => {
83
+ if (locks.get(event.streamId) === runner) {
84
+ locks.delete(event.streamId);
85
+ }
86
+ }).catch(() => {});
87
+ return runner;
88
+ }
89
+ return Promise.resolve();
90
+ };
91
+ let resolveRefresh = null;
92
+ const api = {
93
+ name,
94
+ hasState() {
95
+ return hasState;
96
+ },
97
+ async isReady() {
98
+ await hydrated;
99
+ },
100
+ async apply(event) {
101
+ await apply(event, false);
102
+ },
103
+ async applyAfter(event) {
104
+ await apply(event, true);
105
+ },
106
+ withState(nextState) {
107
+ state = clone(nextState);
108
+ initialState = clone(nextState);
109
+ hasState = true;
110
+ return api;
111
+ },
112
+ concurrent() {
113
+ exclusive = false;
114
+ return api;
115
+ },
116
+ withEventHandlers(handlers) {
117
+ createEventHandlers = typeof handlers === "function" ? handlers : () => handlers;
118
+ return api;
119
+ },
120
+ withAfterEffects(handlers) {
121
+ createAfterEffects = typeof handlers === "function" ? handlers : () => handlers;
122
+ return api;
123
+ },
124
+ setRelatedStreamEvents(generate) {
125
+ generateRelatedStreamEvents = generate;
126
+ },
127
+ async beginRefresh() {
128
+ params.onRefresh?.begin?.(name);
129
+ await checkpointApi.clear();
130
+ lastEventPosition = -1;
131
+ state = initialState;
132
+ },
133
+ async progressRefresh(index, event, after) {
134
+ await apply(event, after, true);
135
+ if (!checkpointApi.relatedStreamEvents || checkpointApi.relatedStreamEvents.some((streamEvent) => streamEvent.events.includes(event.type))) {
136
+ params.onRefresh?.progress?.(name, index, event);
137
+ }
138
+ },
139
+ endRefresh() {
140
+ params.onRefresh?.end?.(name);
141
+ resolveHydrated();
142
+ },
143
+ async refreshState() {
144
+ if (!idle) {
145
+ await refresh();
146
+ return;
147
+ }
148
+ const { promise, resolve } = Promise.withResolvers();
149
+ resolveRefresh = resolve;
150
+ return promise;
151
+ },
152
+ async state() {
153
+ await hydrated;
154
+ return state;
155
+ },
156
+ async init(catchUp) {
157
+ idle = false;
158
+ const relatedStreamEvents = generateRelatedStreamEvents({
159
+ ...createEventHandlers(null),
160
+ ...createAfterEffects(null)
161
+ });
162
+ checkpointApi = createCheckpointApi({
163
+ ...params.checkpoint,
164
+ name,
165
+ relatedStreamEvents,
166
+ type: "processManager",
167
+ loadEvents: params.loadEvents,
168
+ apply: (event) => apply(event, false, true),
169
+ applyAfter: (event) => apply(event, true, true)
170
+ });
171
+ if (resolveRefresh) {
172
+ await refresh();
173
+ return;
174
+ }
175
+ if (!catchUp) {
176
+ return;
177
+ }
178
+ await checkpointApi.rehydrated({
179
+ getMetadata() {
180
+ return { state };
181
+ },
182
+ onMetadata(metadata) {
183
+ state = metadata.state ?? state;
184
+ }
185
+ });
186
+ resolveHydrated();
187
+ },
188
+ $inferState: null
189
+ };
190
+ async function refresh() {
191
+ await withRefreshing(async () => {
192
+ await api.beginRefresh();
193
+ await checkpointApi.rehydrated({
194
+ getMetadata() {
195
+ return { state };
196
+ },
197
+ onProgress(index, event) {
198
+ params.onRefresh?.progress?.(name, index, event);
199
+ }
200
+ });
201
+ });
202
+ api.endRefresh();
203
+ }
204
+ return api;
205
+ };
206
+ }
207
+
208
+ export { getProcessManagerInfo, isInsideProcessManager, buildProcessManagerCreator };
209
+
210
+ //# debugId=F1319F7D0A1BF35E64756E2164756E21
@@ -0,0 +1,10 @@
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 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 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 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 await withProcessManagerInfo(\n {\n name,\n event,\n },\n async () => {\n try {\n await handler(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 await checkpointApi.upsert(event, { state })\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 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 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 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": "F1319F7D0A1BF35E64756E2164756E21",
9
+ "names": []
10
+ }
@@ -0,0 +1,313 @@
1
+ import {
2
+ isReplaying,
3
+ withReplaying
4
+ } from "./chunk-x90g388y.js";
5
+ import {
6
+ createCheckpointApi
7
+ } from "./chunk-zf3x573k.js";
8
+ import {
9
+ createSnapshotGenerator
10
+ } from "./chunk-pmfzjavb.js";
11
+ import {
12
+ ProjectionEventHandlerExecutionError,
13
+ ProjectionReplayLoopError,
14
+ ReplaySkipError,
15
+ ValidationError
16
+ } from "./chunk-qdczt68t.js";
17
+
18
+ // src/createProjection.ts
19
+ import { AsyncLocalStorage } from "node:async_hooks";
20
+ import z from "zod/v4";
21
+ var hydratingStore = new AsyncLocalStorage;
22
+ function isHydrating() {
23
+ return hydratingStore.getStore() ?? false;
24
+ }
25
+ async function withHydrating(handler) {
26
+ await hydratingStore.run(true, handler);
27
+ }
28
+ var projectionInfoStore = new AsyncLocalStorage;
29
+ function withProjectionInfo(info, handler) {
30
+ return projectionInfoStore.run(info, handler);
31
+ }
32
+ function getProjectionInfo() {
33
+ return projectionInfoStore.getStore();
34
+ }
35
+ function isInsideProjection() {
36
+ return Boolean(getProjectionInfo());
37
+ }
38
+ var snapshotSchema = z.object({
39
+ projectionId: z.string(),
40
+ projectionType: z.string(),
41
+ lastEventPosition: z.int(),
42
+ state: z.unknown(),
43
+ metadata: z.record(z.string(), z.unknown()).optional(),
44
+ schemaVersion: z.int(),
45
+ createdAt: z.date()
46
+ });
47
+ function buildProjectionCreator(params) {
48
+ return (name) => {
49
+ let idle = true;
50
+ let replaying = false;
51
+ let handlers = {};
52
+ let globalEventHandler = null;
53
+ let generateRelatedStreamEvents;
54
+ let relatedStreamEvents = null;
55
+ let exclusive = true;
56
+ let checkpointApi;
57
+ let lastEventPosition = -1;
58
+ let replayConfig = null;
59
+ let snapshotting = null;
60
+ const { promise: hydrated, resolve: resolveHydrated } = Promise.withResolvers();
61
+ const locks = new Map;
62
+ const apply = async (event) => {
63
+ const handler = handlers[`on${event.type}`];
64
+ if (!handler && !globalEventHandler) {
65
+ return Promise.resolve();
66
+ }
67
+ if (isHydrating()) {
68
+ lastEventPosition = event.position;
69
+ } else {
70
+ await hydrated;
71
+ if (event.position <= lastEventPosition) {
72
+ return;
73
+ }
74
+ }
75
+ const unlocked = !exclusive ? Promise.resolve() : locks.get(event.streamId)?.catch(() => {}) ?? Promise.resolve();
76
+ const runner = (async () => {
77
+ await unlocked;
78
+ await withProjectionInfo({ name, event }, async () => {
79
+ try {
80
+ await handler?.(event, {
81
+ replaying,
82
+ async replayUntil(position, filterEvents) {
83
+ if (position >= event.position) {
84
+ throw new ProjectionReplayLoopError(`Event handler on${event.type} of projection ${name} tried to replay to the future`, { name, eventHandler: `on${event.type}` }, event);
85
+ }
86
+ locks.delete(event.streamId);
87
+ return api.replayUntil(event.streamId, position, filterEvents);
88
+ }
89
+ });
90
+ } catch (error) {
91
+ if (error instanceof ReplaySkipError) {
92
+ if (isReplaying()) {
93
+ return;
94
+ }
95
+ throw new Error("ReplaySkipError should never be thrown outside replay");
96
+ }
97
+ if (!(error instanceof Error) || error instanceof ProjectionReplayLoopError) {
98
+ throw error;
99
+ }
100
+ throw new ProjectionEventHandlerExecutionError(name, `on${event.type}`, event, error);
101
+ }
102
+ try {
103
+ await globalEventHandler?.(event);
104
+ } catch (error) {
105
+ if (!(error instanceof Error)) {
106
+ throw error;
107
+ }
108
+ throw new ProjectionEventHandlerExecutionError(name, "GLOBAL", event, error);
109
+ }
110
+ });
111
+ if (params.snapshot && snapshotting) {
112
+ const appliedEvents = await params.snapshot.incrementAppliedCount({
113
+ projection: name,
114
+ id: event.streamId
115
+ });
116
+ const snapshot = await snapshotting.internalCapture(event, appliedEvents);
117
+ if (snapshot) {
118
+ await params.snapshot.put({
119
+ projectionType: name,
120
+ projectionId: event.streamId,
121
+ lastEventPosition: event.position,
122
+ state: snapshot.state,
123
+ schemaVersion: snapshot.version,
124
+ createdAt: new Date
125
+ });
126
+ }
127
+ }
128
+ await checkpointApi.upsert(event);
129
+ })();
130
+ if (exclusive) {
131
+ locks.set(event.streamId, runner);
132
+ runner.finally(() => {
133
+ if (locks.get(event.streamId) === runner) {
134
+ locks.delete(event.streamId);
135
+ }
136
+ }).catch(() => {});
137
+ return runner;
138
+ }
139
+ return Promise.resolve();
140
+ };
141
+ let resolveReplay = null;
142
+ let resolveReplayOne = null;
143
+ let replayOneStreamId = null;
144
+ const api = {
145
+ name: "projection " + name,
146
+ async isReady() {
147
+ await hydrated;
148
+ },
149
+ withEventHandlers(h) {
150
+ handlers = h;
151
+ return api;
152
+ },
153
+ withGlobalEventHandler(handler) {
154
+ globalEventHandler = handler;
155
+ return api;
156
+ },
157
+ concurrent() {
158
+ exclusive = false;
159
+ return api;
160
+ },
161
+ setRelatedStreamEvents(generate) {
162
+ generateRelatedStreamEvents = generate;
163
+ },
164
+ withReplay(config) {
165
+ replayConfig = config;
166
+ return api;
167
+ },
168
+ withSnapshots(handler) {
169
+ snapshotting = handler(createSnapshotGenerator());
170
+ return api;
171
+ },
172
+ async apply(event) {
173
+ await apply(event);
174
+ },
175
+ async replayOne(streamId) {
176
+ if (!idle) {
177
+ await replayOne(streamId);
178
+ return;
179
+ }
180
+ const { promise, resolve } = Promise.withResolvers();
181
+ resolveReplayOne = resolve;
182
+ replayOneStreamId = streamId;
183
+ return promise;
184
+ },
185
+ async replay() {
186
+ if (!idle) {
187
+ await replay();
188
+ return;
189
+ }
190
+ const { promise, resolve } = Promise.withResolvers();
191
+ resolveReplay = resolve;
192
+ return promise;
193
+ },
194
+ canReplay() {
195
+ return Boolean(replayConfig);
196
+ },
197
+ async beginReplay() {
198
+ if (!replayConfig?.deleteAll) {
199
+ throw new Error("this projection does not support replay all. withReplay({ deleteAll }) not implemented.");
200
+ }
201
+ lastEventPosition = -1;
202
+ params.onReplay?.begin?.(name);
203
+ await params.snapshot?.delete({ projection: name });
204
+ await replayConfig.deleteAll();
205
+ },
206
+ async progressReplay(index, event) {
207
+ await withReplaying(() => withHydrating(() => apply(event)));
208
+ if (!checkpointApi.relatedStreamEvents || checkpointApi.relatedStreamEvents.some((streamEvent) => streamEvent.events.includes(event.type))) {
209
+ params.onReplay?.progress?.(name, index, event);
210
+ }
211
+ },
212
+ endReplay() {
213
+ params.onReplay?.end?.(name);
214
+ resolveHydrated();
215
+ },
216
+ async replayUntil(id, position, filterEvents = () => true) {
217
+ let startPosition = 0;
218
+ if (snapshotting) {
219
+ await params.snapshot?.delete({ id, projection: name }, position);
220
+ const snapshot = await params.snapshot?.get({ id, projection: name });
221
+ if (snapshot) {
222
+ const result = snapshotSchema.safeParse(snapshot);
223
+ if (!result.success) {
224
+ throw new ValidationError("loaded projection snapshot does not comply with schema", result.error);
225
+ }
226
+ snapshotting.internalApply(result.data);
227
+ startPosition = result.data.lastEventPosition + 1;
228
+ }
229
+ }
230
+ const events = params.loadEvents(relatedStreamEvents?.map((relatedStreamEvent) => ({
231
+ ...relatedStreamEvent,
232
+ id
233
+ })) ?? null, {
234
+ from: startPosition,
235
+ to: position
236
+ });
237
+ replaying = true;
238
+ await withReplaying(async () => {
239
+ for await (const event of events) {
240
+ if (filterEvents(event)) {
241
+ await apply(event);
242
+ }
243
+ }
244
+ });
245
+ replaying = false;
246
+ },
247
+ async init(catchUp) {
248
+ idle = false;
249
+ relatedStreamEvents = globalEventHandler ? null : generateRelatedStreamEvents(handlers);
250
+ checkpointApi = createCheckpointApi({
251
+ ...params.checkpoint,
252
+ name,
253
+ relatedStreamEvents,
254
+ type: "projection",
255
+ loadEvents: params.loadEvents,
256
+ apply: (event) => withHydrating(() => apply(event))
257
+ });
258
+ if (resolveReplay) {
259
+ await replay();
260
+ resolveReplay();
261
+ return;
262
+ }
263
+ if (resolveReplayOne && replayOneStreamId) {
264
+ await replayOne(replayOneStreamId);
265
+ }
266
+ if (!catchUp) {
267
+ return;
268
+ }
269
+ await checkpointApi.rehydrated();
270
+ resolveHydrated();
271
+ resolveReplayOne?.();
272
+ }
273
+ };
274
+ async function replayOne(id) {
275
+ if (!replayConfig?.deleteOne) {
276
+ throw new Error("this projection does not support replay one. withReplay({ deleteOne }) not implemented.");
277
+ }
278
+ await params.snapshot?.delete({ id, projection: name });
279
+ await replayConfig.deleteOne(id);
280
+ const streamIds = relatedStreamEvents ? relatedStreamEvents.map((relatedStreamEvent) => ({
281
+ ...relatedStreamEvent,
282
+ id
283
+ })) : null;
284
+ const events = params.loadEvents(streamIds);
285
+ replaying = true;
286
+ await withReplaying(async () => {
287
+ for await (const event of events) {
288
+ await withHydrating(() => apply(event));
289
+ }
290
+ });
291
+ replaying = false;
292
+ }
293
+ async function replay() {
294
+ await api.beginReplay();
295
+ const events = params.loadEvents(relatedStreamEvents);
296
+ let index = 0;
297
+ replaying = true;
298
+ await withReplaying(async () => {
299
+ for await (const event of events) {
300
+ await api.progressReplay(index, event);
301
+ index++;
302
+ }
303
+ });
304
+ replaying = false;
305
+ api.endReplay();
306
+ }
307
+ return api;
308
+ };
309
+ }
310
+
311
+ export { getProjectionInfo, isInsideProjection, buildProjectionCreator };
312
+
313
+ //# debugId=B979DBD1EC4FBD5364756E2164756E21
@@ -0,0 +1,10 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/createProjection.ts"],
4
+ "sourcesContent": [
5
+ "import { AsyncLocalStorage } from 'node:async_hooks'\n\nimport z from 'zod/v4'\n\nimport {\n type CheckpointApi,\n type CheckpointMethods,\n createCheckpointApi,\n} from './createCheckpointApi.ts'\nimport type { LoadEvents, OnProgress } from './createEventStore.ts'\nimport {\n ProjectionEventHandlerExecutionError,\n ProjectionReplayLoopError,\n ReplaySkipError,\n ValidationError,\n} from './errors.ts'\nimport { isReplaying, withReplaying } from './replay.ts'\nimport type {\n CompleteSnapshotGenerator,\n InternalSnapshotGenerator,\n SnapshotGenerator,\n} from './snapshotGenerator.ts'\nimport createSnapshotGenerator from './snapshotGenerator.ts'\nimport type {\n AllEvents,\n BaseOutputEvent,\n EventHandlers,\n EventTemplate,\n Keys,\n MaybePromise,\n Merge,\n OutputEvent,\n StreamEvents,\n} from './utilityTypes.d.ts'\n\nconst hydratingStore = new AsyncLocalStorage<boolean>()\n\nfunction isHydrating() {\n return hydratingStore.getStore() ?? false\n}\n\nasync function withHydrating(handler: () => Promise<void>) {\n await hydratingStore.run(true, handler)\n}\n\ntype ProjectionInfo = {\n name: string\n event: BaseOutputEvent\n}\nconst projectionInfoStore = new AsyncLocalStorage<ProjectionInfo>()\n\nfunction withProjectionInfo(\n info: ProjectionInfo,\n handler: () => Promise<void>,\n) {\n return projectionInfoStore.run(info, handler)\n}\n\nexport function getProjectionInfo() {\n return projectionInfoStore.getStore()\n}\n\nexport function isInsideProjection() {\n return Boolean(getProjectionInfo())\n}\n\ntype ReplayConfig = {\n deleteOne?: (id: string) => MaybePromise<void>\n deleteAll?: () => MaybePromise<void>\n}\n\ntype ProjectionEventHandlers<Events extends EventTemplate> = EventHandlers<\n Events,\n {\n replaying: boolean\n replayUntil: (\n position: number,\n filterEvents?: (event: OutputEvent<Events>) => boolean,\n ) => Promise<void>\n }\n>\n\ntype ReplayProjection<Events extends EventTemplate> = {\n replayOne: (streamId: string) => Promise<void>\n replayUntil: (\n streamId: string,\n position: number,\n filterEvents?: (event: OutputEvent<Events>) => boolean,\n ) => Promise<void>\n replay: () => Promise<void>\n}\n\nexport type InternalProjection = {\n apply: (event: BaseOutputEvent) => Promise<void>\n setRelatedStreamEvents: (\n generateRelatedStreamEvents: (\n eventHandlers: EventHandlers<EventTemplate>,\n ) => StreamEvents[],\n ) => void\n isReady(): Promise<void>\n canReplay(): boolean\n beginReplay(): Promise<void>\n progressReplay(index: number, event: BaseOutputEvent): Promise<void>\n endReplay(): void\n init(catchUp: boolean): Promise<void>\n}\n\nexport type ProjectionApi<\n Events extends EventTemplate = never,\n RConfig extends ReplayConfig = never,\n Flags extends {\n withEventHandlers: boolean\n withGlobalEventHandler: boolean\n concurrent: boolean\n withReplay: boolean\n withSnapshots: boolean\n } = {\n withEventHandlers: false\n withGlobalEventHandler: false\n concurrent: false\n withReplay: false\n withSnapshots: true\n },\n> = {\n withEventHandlers: (\n handlers: ProjectionEventHandlers<Events>,\n ) => Omit<\n ProjectionApi<Events, RConfig, Merge<Flags, { withEventHandlers: true }>>,\n Keys<Merge<Flags, { withEventHandlers: true }>>\n >\n withGlobalEventHandler: (\n handler: (\n event: AllEvents<Events>,\n methods: ReplayProjection<Events>,\n ) => MaybePromise<void>,\n ) => Omit<\n ProjectionApi<\n Events,\n RConfig,\n Merge<Flags, { withGlobalEventHandler: true }>\n >,\n Keys<Merge<Flags, { withGlobalEventHandler: true }>>\n >\n concurrent: () => Omit<\n ProjectionApi<Events, RConfig, Merge<Flags, { concurrent: true }>>,\n Keys<Merge<Flags, { concurrent: true }>>\n >\n withReplay: <Config extends ReplayConfig>(\n config: Config,\n ) => Omit<\n ProjectionApi<Events, Config, Merge<Flags, { withReplay: true }>>,\n Keys<Merge<Flags, { withReplay: true }>>\n >\n withSnapshots: (\n handler: (\n generator: SnapshotGenerator<Omit<Snapshot, 'schemaVersion' | 'state'>>,\n ) => CompleteSnapshotGenerator,\n ) => Omit<\n ProjectionApi<Events, RConfig, Merge<Flags, { withSnapshots: true }>>,\n Keys<Merge<Flags, { withSnapshots: true }>>\n >\n isReady(): Promise<void>\n} & ('deleteOne' extends keyof RConfig\n ? Pick<ReplayProjection<Events>, 'replayOne' | 'replayUntil'>\n : {}) &\n ('deleteAll' extends keyof RConfig\n ? Pick<ReplayProjection<Events>, 'replay'>\n : {})\n\nexport type ProjectionApiWithSnapshots<\n Events extends EventTemplate = never,\n RConfig extends ReplayConfig = never,\n Flags extends {\n withEventHandlers: boolean\n withGlobalEventHandler: boolean\n concurrent: boolean\n withReplay: boolean\n withSnapshots: boolean\n } = {\n withEventHandlers: false\n withGlobalEventHandler: false\n concurrent: false\n withReplay: false\n withSnapshots: false\n },\n> = ProjectionApi<Events, RConfig, Flags>\n\nconst snapshotSchema = z.object({\n projectionId: z.string(),\n projectionType: z.string(),\n lastEventPosition: z.int(),\n state: z.unknown(),\n metadata: z.record(z.string(), z.unknown()).optional(),\n schemaVersion: z.int(),\n createdAt: z.date(),\n})\n\nexport type Snapshot = z.output<typeof snapshotSchema>\n\nexport type ProjectionSnapshotMethods = {\n get: (select: {\n projection: string\n id: string\n }) => MaybePromise<Snapshot | null | undefined>\n put: (snapshot: Snapshot) => MaybePromise<void>\n delete: (\n target: { id?: string; projection: string },\n fromPosition?: number,\n ) => MaybePromise<void>\n incrementAppliedCount: (target: {\n projection: string\n id: string\n }) => MaybePromise<number>\n}\n\nexport function buildProjectionCreator(params: {\n loadEvents: LoadEvents\n checkpoint: CheckpointMethods\n onReplay?: OnProgress\n snapshot?: ProjectionSnapshotMethods\n}): (name: string) => ProjectionApi {\n return (name) => {\n let idle = true\n let replaying = false\n let handlers: ProjectionEventHandlers<any> = {}\n let globalEventHandler:\n | ((event: BaseOutputEvent) => MaybePromise<void>)\n | null = null\n let generateRelatedStreamEvents: (\n eventHandlers: EventHandlers<any>,\n ) => StreamEvents[]\n let relatedStreamEvents: StreamEvents[] | null = null\n let exclusive = true\n let checkpointApi: CheckpointApi\n let lastEventPosition = -1\n\n let replayConfig: ReplayConfig | null = null\n\n let snapshotting:\n | (CompleteSnapshotGenerator & InternalSnapshotGenerator)\n | null = null\n\n const { promise: hydrated, resolve: resolveHydrated } =\n Promise.withResolvers<void>()\n\n const locks = new Map<string, Promise<void>>()\n const apply = async (event: BaseOutputEvent) => {\n const handler = handlers[`on${event.type}`]\n if (!handler && !globalEventHandler) {\n return Promise.resolve()\n }\n\n if (isHydrating()) {\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\n const unlocked = !exclusive\n ? Promise.resolve()\n : (locks.get(event.streamId)?.catch(() => {}) ?? Promise.resolve())\n\n const runner = (async () => {\n await unlocked\n await withProjectionInfo({ name, event }, async () => {\n try {\n await handler?.(event, {\n replaying,\n async replayUntil(position, filterEvents) {\n if (position >= event.position) {\n throw new ProjectionReplayLoopError(\n `Event handler on${event.type} of projection ${name} tried to replay to the future`,\n { name, eventHandler: `on${event.type}` },\n event,\n )\n }\n\n locks.delete(event.streamId)\n return api.replayUntil(event.streamId, position, filterEvents)\n },\n })\n } catch (error) {\n if (error instanceof ReplaySkipError) {\n if (isReplaying()) {\n return\n }\n\n throw new Error(\n 'ReplaySkipError should never be thrown outside replay',\n )\n }\n\n if (\n !(error instanceof Error) ||\n error instanceof ProjectionReplayLoopError\n ) {\n throw error\n }\n throw new ProjectionEventHandlerExecutionError(\n name,\n `on${event.type}`,\n event,\n error,\n )\n }\n try {\n await globalEventHandler?.(event)\n } catch (error) {\n if (!(error instanceof Error)) {\n throw error\n }\n\n throw new ProjectionEventHandlerExecutionError(\n name,\n 'GLOBAL',\n event,\n error,\n )\n }\n })\n\n if (params.snapshot && snapshotting) {\n const appliedEvents = await params.snapshot.incrementAppliedCount({\n projection: name,\n id: event.streamId,\n })\n const snapshot = await snapshotting.internalCapture(\n event,\n appliedEvents,\n )\n\n if (snapshot) {\n await params.snapshot.put({\n projectionType: name,\n projectionId: event.streamId,\n lastEventPosition: event.position,\n state: snapshot.state,\n schemaVersion: snapshot.version,\n createdAt: new Date(),\n })\n }\n }\n\n await checkpointApi.upsert(event)\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 resolveReplay: null | (() => void) = null\n let resolveReplayOne: null | (() => void) = null\n let replayOneStreamId: null | string = null\n\n const api = {\n name: 'projection ' + name,\n async isReady() {\n await hydrated\n },\n withEventHandlers(h) {\n handlers = h\n return api\n },\n withGlobalEventHandler(handler) {\n globalEventHandler = handler as any\n return api\n },\n concurrent() {\n exclusive = false\n return api\n },\n setRelatedStreamEvents(generate) {\n generateRelatedStreamEvents = generate\n },\n withReplay(config) {\n replayConfig = config\n return api as any\n },\n\n withSnapshots(handler) {\n snapshotting = handler(createSnapshotGenerator() as any) as any\n return api\n },\n\n async apply(event) {\n await apply(event)\n },\n\n async replayOne(streamId: string) {\n if (!idle) {\n await replayOne(streamId)\n return\n }\n\n const { promise, resolve } = Promise.withResolvers<void>()\n resolveReplayOne = resolve\n replayOneStreamId = streamId\n return promise\n },\n\n async replay() {\n if (!idle) {\n await replay()\n return\n }\n const { promise, resolve } = Promise.withResolvers<void>()\n resolveReplay = resolve\n return promise\n },\n\n canReplay() {\n return Boolean(replayConfig)\n },\n\n async beginReplay() {\n if (!replayConfig?.deleteAll) {\n throw new Error(\n 'this projection does not support replay all. withReplay({ deleteAll }) not implemented.',\n )\n }\n\n lastEventPosition = -1\n params.onReplay?.begin?.(name)\n await params.snapshot?.delete({ projection: name })\n await replayConfig.deleteAll()\n },\n\n async progressReplay(index, event) {\n await withReplaying(() => withHydrating(() => apply(event)))\n if (\n !checkpointApi.relatedStreamEvents ||\n checkpointApi.relatedStreamEvents.some((streamEvent) =>\n streamEvent.events.includes(event.type),\n )\n ) {\n params.onReplay?.progress?.(name, index, event)\n }\n },\n\n endReplay() {\n params.onReplay?.end?.(name)\n resolveHydrated()\n },\n\n async replayUntil(id, position, filterEvents = () => true) {\n let startPosition = 0\n if (snapshotting) {\n await params.snapshot?.delete({ id, projection: name }, position)\n const snapshot = await params.snapshot?.get({ id, projection: name })\n if (snapshot) {\n const result = snapshotSchema.safeParse(snapshot)\n\n if (!result.success) {\n throw new ValidationError(\n 'loaded projection snapshot does not comply with schema',\n result.error,\n )\n }\n snapshotting.internalApply(result.data)\n startPosition = result.data.lastEventPosition + 1\n }\n }\n\n const events = params.loadEvents(\n relatedStreamEvents?.map((relatedStreamEvent) => ({\n ...relatedStreamEvent,\n id,\n })) ?? null,\n {\n from: startPosition,\n to: position,\n },\n )\n\n replaying = true\n await withReplaying(async () => {\n for await (const event of events) {\n if ((filterEvents as (event: BaseOutputEvent) => boolean)(event)) {\n await apply(event)\n }\n }\n })\n replaying = false\n },\n async init(catchUp) {\n idle = false\n relatedStreamEvents = globalEventHandler\n ? null\n : generateRelatedStreamEvents(handlers as EventHandlers<any>)\n checkpointApi = createCheckpointApi({\n ...params.checkpoint,\n name,\n relatedStreamEvents,\n type: 'projection',\n loadEvents: params.loadEvents,\n apply: (event) => withHydrating(() => apply(event)),\n })\n\n if (resolveReplay) {\n await replay()\n resolveReplay()\n return\n }\n\n if (resolveReplayOne && replayOneStreamId) {\n await replayOne(replayOneStreamId)\n }\n\n if (!catchUp) {\n return\n }\n\n await checkpointApi.rehydrated()\n resolveHydrated()\n resolveReplayOne?.()\n },\n } as ProjectionApi & InternalProjection & ReplayProjection<any>\n\n async function replayOne(id: string) {\n if (!replayConfig?.deleteOne) {\n throw new Error(\n 'this projection does not support replay one. withReplay({ deleteOne }) not implemented.',\n )\n }\n await params.snapshot?.delete({ id, projection: name })\n await replayConfig.deleteOne(id)\n const streamIds = relatedStreamEvents\n ? relatedStreamEvents.map((relatedStreamEvent) => ({\n ...relatedStreamEvent,\n id,\n }))\n : null\n const events = params.loadEvents(streamIds)\n\n replaying = true\n await withReplaying(async () => {\n for await (const event of events) {\n await withHydrating(() => apply(event))\n }\n })\n replaying = false\n }\n\n async function replay() {\n await api.beginReplay()\n const events = params.loadEvents(relatedStreamEvents)\n let index = 0\n replaying = true\n await withReplaying(async () => {\n for await (const event of events) {\n await api.progressReplay(index, event)\n index++\n }\n })\n replaying = false\n api.endReplay()\n }\n\n return api\n }\n}\n"
6
+ ],
7
+ "mappings": "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",
8
+ "debugId": "B979DBD1EC4FBD5364756E2164756E21",
9
+ "names": []
10
+ }
@@ -0,0 +1,49 @@
1
+ import {
2
+ ValidationError
3
+ } from "./chunk-qdczt68t.js";
4
+
5
+ // src/snapshotGenerator.ts
6
+ import { z } from "zod/v4";
7
+ function createSnapshotGenerator(schemas = [], config = null, applier = null, capturer = null) {
8
+ return {
9
+ async internalApply(snapshot) {
10
+ const result = z.union(schemas.map(({ schema }) => schema)).safeParse(snapshot.state);
11
+ if (!result.success) {
12
+ throw new ValidationError(`loaded snapshot version ${snapshot.schemaVersion} does not comply with registered schema`, result.error);
13
+ }
14
+ await applier(snapshot);
15
+ },
16
+ async internalCapture(event, applied) {
17
+ if (!config || applied % config.every !== 0) {
18
+ return null;
19
+ }
20
+ const latestSchema = schemas.slice(1).reduce((latest, schema) => schema.schemaVersion > latest.schemaVersion ? schema : latest, schemas[0]);
21
+ const result = latestSchema.schema.safeParse(await capturer(event));
22
+ if (!result.success) {
23
+ throw new ValidationError(`generated snapshot does not comply with schema for version ${latestSchema.schemaVersion}`, result.error);
24
+ }
25
+ return {
26
+ state: result.data,
27
+ version: latestSchema.schemaVersion
28
+ };
29
+ },
30
+ every(count) {
31
+ return createSnapshotGenerator(schemas, { every: count }, applier, capturer);
32
+ },
33
+ schema(schema, schemaVersion) {
34
+ schemas.push({ schemaVersion: schemaVersion ?? 0, schema });
35
+ return createSnapshotGenerator(schemas, config, null, null);
36
+ },
37
+ apply(applier2) {
38
+ return createSnapshotGenerator(schemas, config, applier2, capturer);
39
+ },
40
+ capture(capturer2) {
41
+ return createSnapshotGenerator(schemas, config, applier, capturer2);
42
+ },
43
+ complete: true
44
+ };
45
+ }
46
+
47
+ export { createSnapshotGenerator };
48
+
49
+ //# debugId=53092F13C54E882C64756E2164756E21