@tanstack/workflow-runtime 0.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 (47) hide show
  1. package/README.md +22 -0
  2. package/dist/define-runtime.cjs +50 -0
  3. package/dist/define-runtime.cjs.map +1 -0
  4. package/dist/define-runtime.d.cts +16 -0
  5. package/dist/define-runtime.d.ts +16 -0
  6. package/dist/define-runtime.js +48 -0
  7. package/dist/define-runtime.js.map +1 -0
  8. package/dist/in-memory-store.cjs +457 -0
  9. package/dist/in-memory-store.cjs.map +1 -0
  10. package/dist/in-memory-store.d.cts +8 -0
  11. package/dist/in-memory-store.d.ts +8 -0
  12. package/dist/in-memory-store.js +457 -0
  13. package/dist/in-memory-store.js.map +1 -0
  14. package/dist/index.cjs +14 -0
  15. package/dist/index.d.cts +7 -0
  16. package/dist/index.d.ts +7 -0
  17. package/dist/index.js +7 -0
  18. package/dist/run-store-adapter.cjs +30 -0
  19. package/dist/run-store-adapter.cjs.map +1 -0
  20. package/dist/run-store-adapter.d.cts +7 -0
  21. package/dist/run-store-adapter.d.ts +7 -0
  22. package/dist/run-store-adapter.js +29 -0
  23. package/dist/run-store-adapter.js.map +1 -0
  24. package/dist/runtime-driver.cjs +334 -0
  25. package/dist/runtime-driver.cjs.map +1 -0
  26. package/dist/runtime-driver.d.cts +12 -0
  27. package/dist/runtime-driver.d.ts +12 -0
  28. package/dist/runtime-driver.js +334 -0
  29. package/dist/runtime-driver.js.map +1 -0
  30. package/dist/schedule-materializer.cjs +156 -0
  31. package/dist/schedule-materializer.cjs.map +1 -0
  32. package/dist/schedule-materializer.d.cts +28 -0
  33. package/dist/schedule-materializer.d.ts +28 -0
  34. package/dist/schedule-materializer.js +155 -0
  35. package/dist/schedule-materializer.js.map +1 -0
  36. package/dist/types.cjs +0 -0
  37. package/dist/types.d.cts +375 -0
  38. package/dist/types.d.ts +375 -0
  39. package/dist/types.js +1 -0
  40. package/package.json +60 -0
  41. package/src/define-runtime.ts +46 -0
  42. package/src/in-memory-store.ts +607 -0
  43. package/src/index.ts +74 -0
  44. package/src/run-store-adapter.ts +49 -0
  45. package/src/runtime-driver.ts +536 -0
  46. package/src/schedule-materializer.ts +272 -0
  47. package/src/types.ts +462 -0
package/README.md ADDED
@@ -0,0 +1,22 @@
1
+ # @tanstack/workflow-runtime
2
+
3
+ Experimental runtime contracts for TanStack Workflow.
4
+
5
+ This package is the staging area for durable execution store, schedule, timer,
6
+ signal, lease, and host-adapter contracts. It is intentionally separate from
7
+ `@tanstack/workflow-core`, which remains the small replay engine.
8
+
9
+ See the main docs:
10
+
11
+ - [Guide](../../docs/guide/index.md)
12
+ - [Runtime model](../../docs/guide/runtime-model.md)
13
+ - [Runtime API](../../docs/api/runtime.md)
14
+
15
+ ## Store adapter contract tests
16
+
17
+ Storage adapters should wire their implementation into
18
+ `tests/contracts/workflow-execution-store.contract.ts`. The contract suite covers
19
+ the behavior every durable store must preserve: idempotent run creation,
20
+ compare-and-swap event appends, run leases, stale run claiming, timers, signal
21
+ and approval delivery, schedules, timelines, and integration with the runtime
22
+ driver.
@@ -0,0 +1,50 @@
1
+ const require_runtime_driver = require('./runtime-driver.cjs');
2
+
3
+ //#region src/define-runtime.ts
4
+ function defineWorkflowRuntime(config) {
5
+ const driver = require_runtime_driver.createRuntimeDriver(config);
6
+ return {
7
+ __kind: "workflow-runtime",
8
+ ...config,
9
+ ...driver
10
+ };
11
+ }
12
+ function cron(expression, options = {}) {
13
+ return {
14
+ kind: "cron",
15
+ expression,
16
+ timezone: options.timezone
17
+ };
18
+ }
19
+ const every = {
20
+ milliseconds(everyMs) {
21
+ return {
22
+ kind: "interval",
23
+ everyMs
24
+ };
25
+ },
26
+ seconds(seconds) {
27
+ return {
28
+ kind: "interval",
29
+ everyMs: seconds * 1e3
30
+ };
31
+ },
32
+ minutes(minutes) {
33
+ return {
34
+ kind: "interval",
35
+ everyMs: minutes * 60 * 1e3
36
+ };
37
+ },
38
+ hours(hours) {
39
+ return {
40
+ kind: "interval",
41
+ everyMs: hours * 60 * 60 * 1e3
42
+ };
43
+ }
44
+ };
45
+
46
+ //#endregion
47
+ exports.cron = cron;
48
+ exports.defineWorkflowRuntime = defineWorkflowRuntime;
49
+ exports.every = every;
50
+ //# sourceMappingURL=define-runtime.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"define-runtime.cjs","names":["createRuntimeDriver"],"sources":["../src/define-runtime.ts"],"sourcesContent":["import { createRuntimeDriver } from './runtime-driver'\nimport type {\n WorkflowRegistrationMap,\n WorkflowRuntimeConfig,\n WorkflowRuntimeDefinition,\n WorkflowScheduleSpec,\n} from './types'\n\nexport function defineWorkflowRuntime<\n const TWorkflows extends WorkflowRegistrationMap,\n>(\n config: WorkflowRuntimeConfig<TWorkflows>,\n): WorkflowRuntimeDefinition<TWorkflows> {\n const driver = createRuntimeDriver(config)\n return {\n __kind: 'workflow-runtime',\n ...config,\n ...driver,\n }\n}\n\nexport function cron(\n expression: string,\n options: { timezone?: string } = {},\n): WorkflowScheduleSpec {\n return {\n kind: 'cron',\n expression,\n timezone: options.timezone,\n }\n}\n\nexport const every = {\n milliseconds(everyMs: number): WorkflowScheduleSpec {\n return { kind: 'interval', everyMs }\n },\n seconds(seconds: number): WorkflowScheduleSpec {\n return { kind: 'interval', everyMs: seconds * 1000 }\n },\n minutes(minutes: number): WorkflowScheduleSpec {\n return { kind: 'interval', everyMs: minutes * 60 * 1000 }\n },\n hours(hours: number): WorkflowScheduleSpec {\n return { kind: 'interval', everyMs: hours * 60 * 60 * 1000 }\n },\n}\n"],"mappings":";;;AAQA,SAAgB,sBAGd,QACuC;CACvC,MAAM,SAASA,2CAAoB,OAAO;AAC1C,QAAO;EACL,QAAQ;EACR,GAAG;EACH,GAAG;EACJ;;AAGH,SAAgB,KACd,YACA,UAAiC,EAAE,EACb;AACtB,QAAO;EACL,MAAM;EACN;EACA,UAAU,QAAQ;EACnB;;AAGH,MAAa,QAAQ;CACnB,aAAa,SAAuC;AAClD,SAAO;GAAE,MAAM;GAAY;GAAS;;CAEtC,QAAQ,SAAuC;AAC7C,SAAO;GAAE,MAAM;GAAY,SAAS,UAAU;GAAM;;CAEtD,QAAQ,SAAuC;AAC7C,SAAO;GAAE,MAAM;GAAY,SAAS,UAAU,KAAK;GAAM;;CAE3D,MAAM,OAAqC;AACzC,SAAO;GAAE,MAAM;GAAY,SAAS,QAAQ,KAAK,KAAK;GAAM;;CAE/D"}
@@ -0,0 +1,16 @@
1
+ import { WorkflowRegistrationMap, WorkflowRuntimeConfig, WorkflowRuntimeDefinition, WorkflowScheduleSpec } from "./types.cjs";
2
+
3
+ //#region src/define-runtime.d.ts
4
+ declare function defineWorkflowRuntime<const TWorkflows extends WorkflowRegistrationMap>(config: WorkflowRuntimeConfig<TWorkflows>): WorkflowRuntimeDefinition<TWorkflows>;
5
+ declare function cron(expression: string, options?: {
6
+ timezone?: string;
7
+ }): WorkflowScheduleSpec;
8
+ declare const every: {
9
+ milliseconds(everyMs: number): WorkflowScheduleSpec;
10
+ seconds(seconds: number): WorkflowScheduleSpec;
11
+ minutes(minutes: number): WorkflowScheduleSpec;
12
+ hours(hours: number): WorkflowScheduleSpec;
13
+ };
14
+ //#endregion
15
+ export { cron, defineWorkflowRuntime, every };
16
+ //# sourceMappingURL=define-runtime.d.cts.map
@@ -0,0 +1,16 @@
1
+ import { WorkflowRegistrationMap, WorkflowRuntimeConfig, WorkflowRuntimeDefinition, WorkflowScheduleSpec } from "./types.js";
2
+
3
+ //#region src/define-runtime.d.ts
4
+ declare function defineWorkflowRuntime<const TWorkflows extends WorkflowRegistrationMap>(config: WorkflowRuntimeConfig<TWorkflows>): WorkflowRuntimeDefinition<TWorkflows>;
5
+ declare function cron(expression: string, options?: {
6
+ timezone?: string;
7
+ }): WorkflowScheduleSpec;
8
+ declare const every: {
9
+ milliseconds(everyMs: number): WorkflowScheduleSpec;
10
+ seconds(seconds: number): WorkflowScheduleSpec;
11
+ minutes(minutes: number): WorkflowScheduleSpec;
12
+ hours(hours: number): WorkflowScheduleSpec;
13
+ };
14
+ //#endregion
15
+ export { cron, defineWorkflowRuntime, every };
16
+ //# sourceMappingURL=define-runtime.d.ts.map
@@ -0,0 +1,48 @@
1
+ import { createRuntimeDriver } from "./runtime-driver.js";
2
+
3
+ //#region src/define-runtime.ts
4
+ function defineWorkflowRuntime(config) {
5
+ const driver = createRuntimeDriver(config);
6
+ return {
7
+ __kind: "workflow-runtime",
8
+ ...config,
9
+ ...driver
10
+ };
11
+ }
12
+ function cron(expression, options = {}) {
13
+ return {
14
+ kind: "cron",
15
+ expression,
16
+ timezone: options.timezone
17
+ };
18
+ }
19
+ const every = {
20
+ milliseconds(everyMs) {
21
+ return {
22
+ kind: "interval",
23
+ everyMs
24
+ };
25
+ },
26
+ seconds(seconds) {
27
+ return {
28
+ kind: "interval",
29
+ everyMs: seconds * 1e3
30
+ };
31
+ },
32
+ minutes(minutes) {
33
+ return {
34
+ kind: "interval",
35
+ everyMs: minutes * 60 * 1e3
36
+ };
37
+ },
38
+ hours(hours) {
39
+ return {
40
+ kind: "interval",
41
+ everyMs: hours * 60 * 60 * 1e3
42
+ };
43
+ }
44
+ };
45
+
46
+ //#endregion
47
+ export { cron, defineWorkflowRuntime, every };
48
+ //# sourceMappingURL=define-runtime.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"define-runtime.js","names":[],"sources":["../src/define-runtime.ts"],"sourcesContent":["import { createRuntimeDriver } from './runtime-driver'\nimport type {\n WorkflowRegistrationMap,\n WorkflowRuntimeConfig,\n WorkflowRuntimeDefinition,\n WorkflowScheduleSpec,\n} from './types'\n\nexport function defineWorkflowRuntime<\n const TWorkflows extends WorkflowRegistrationMap,\n>(\n config: WorkflowRuntimeConfig<TWorkflows>,\n): WorkflowRuntimeDefinition<TWorkflows> {\n const driver = createRuntimeDriver(config)\n return {\n __kind: 'workflow-runtime',\n ...config,\n ...driver,\n }\n}\n\nexport function cron(\n expression: string,\n options: { timezone?: string } = {},\n): WorkflowScheduleSpec {\n return {\n kind: 'cron',\n expression,\n timezone: options.timezone,\n }\n}\n\nexport const every = {\n milliseconds(everyMs: number): WorkflowScheduleSpec {\n return { kind: 'interval', everyMs }\n },\n seconds(seconds: number): WorkflowScheduleSpec {\n return { kind: 'interval', everyMs: seconds * 1000 }\n },\n minutes(minutes: number): WorkflowScheduleSpec {\n return { kind: 'interval', everyMs: minutes * 60 * 1000 }\n },\n hours(hours: number): WorkflowScheduleSpec {\n return { kind: 'interval', everyMs: hours * 60 * 60 * 1000 }\n },\n}\n"],"mappings":";;;AAQA,SAAgB,sBAGd,QACuC;CACvC,MAAM,SAAS,oBAAoB,OAAO;AAC1C,QAAO;EACL,QAAQ;EACR,GAAG;EACH,GAAG;EACJ;;AAGH,SAAgB,KACd,YACA,UAAiC,EAAE,EACb;AACtB,QAAO;EACL,MAAM;EACN;EACA,UAAU,QAAQ;EACnB;;AAGH,MAAa,QAAQ;CACnB,aAAa,SAAuC;AAClD,SAAO;GAAE,MAAM;GAAY;GAAS;;CAEtC,QAAQ,SAAuC;AAC7C,SAAO;GAAE,MAAM;GAAY,SAAS,UAAU;GAAM;;CAEtD,QAAQ,SAAuC;AAC7C,SAAO;GAAE,MAAM;GAAY,SAAS,UAAU,KAAK;GAAM;;CAE3D,MAAM,OAAqC;AACzC,SAAO;GAAE,MAAM;GAAY,SAAS,QAAQ,KAAK,KAAK;GAAM;;CAE/D"}
@@ -0,0 +1,457 @@
1
+ let _tanstack_workflow_core = require("@tanstack/workflow-core");
2
+
3
+ //#region src/in-memory-store.ts
4
+ function inMemoryWorkflowExecutionStore() {
5
+ const runs = /* @__PURE__ */ new Map();
6
+ const runStates = /* @__PURE__ */ new Map();
7
+ const logs = /* @__PURE__ */ new Map();
8
+ const timers = /* @__PURE__ */ new Map();
9
+ const signalDeliveries = /* @__PURE__ */ new Map();
10
+ const schedules = /* @__PURE__ */ new Map();
11
+ const scheduleBuckets = /* @__PURE__ */ new Map();
12
+ const subscribers = /* @__PURE__ */ new Map();
13
+ function setRun(run) {
14
+ runs.set(run.runId, cloneRun(run));
15
+ }
16
+ function getRun(runId) {
17
+ const run = runs.get(runId);
18
+ return run ? cloneRun(run) : void 0;
19
+ }
20
+ function updateRun(runId, updater) {
21
+ const existing = runs.get(runId);
22
+ if (!existing) return void 0;
23
+ const next = updater(cloneRun(existing));
24
+ setRun(next);
25
+ return cloneRun(next);
26
+ }
27
+ return {
28
+ async createRun(args) {
29
+ const existing = getRun(args.runId);
30
+ if (existing) return {
31
+ kind: "existing",
32
+ run: existing
33
+ };
34
+ const run = {
35
+ runId: args.runId,
36
+ workflowId: args.workflowId,
37
+ workflowVersion: args.workflowVersion,
38
+ status: "queued",
39
+ input: args.input,
40
+ createdAt: args.now,
41
+ updatedAt: args.now
42
+ };
43
+ setRun(run);
44
+ return {
45
+ kind: "created",
46
+ run: cloneRun(run)
47
+ };
48
+ },
49
+ async loadRun(runId) {
50
+ return getRun(runId);
51
+ },
52
+ async loadExecution(runId) {
53
+ const run = getRun(runId);
54
+ if (!run) return void 0;
55
+ return {
56
+ run,
57
+ events: cloneStoredEvents(logs.get(runId) ?? [])
58
+ };
59
+ },
60
+ async loadRunState(runId) {
61
+ const state = runStates.get(runId);
62
+ return state ? cloneRunState(state) : void 0;
63
+ },
64
+ async saveRunState(args) {
65
+ const state = cloneRunState(args.state);
66
+ runStates.set(state.runId, state);
67
+ setRun(executionFromRunState(state, runs.get(state.runId)?.lease));
68
+ },
69
+ async deleteRun(runId, _reason) {
70
+ runs.delete(runId);
71
+ runStates.delete(runId);
72
+ logs.delete(runId);
73
+ subscribers.delete(runId);
74
+ for (const [key, timer] of timers.entries()) if (timer.runId === runId) timers.delete(key);
75
+ for (const key of signalDeliveries.keys()) if (key.startsWith(`${runId}:`)) signalDeliveries.delete(key);
76
+ },
77
+ async appendEvents(args) {
78
+ const log = logs.get(args.runId) ?? [];
79
+ if (log.length !== args.expectedNextIndex) throw new _tanstack_workflow_core.LogConflictError(args.runId, args.expectedNextIndex, log[args.expectedNextIndex]?.event);
80
+ for (const event of args.events) {
81
+ const stored = storeEvent(args.runId, log.length, event);
82
+ log.push(stored);
83
+ publish(subscribers, args.runId, stored.event, stored.eventIndex);
84
+ }
85
+ logs.set(args.runId, log);
86
+ return { nextIndex: log.length };
87
+ },
88
+ async readEvents(args) {
89
+ const fromIndex = args.fromIndex ?? 0;
90
+ return cloneStoredEvents((logs.get(args.runId) ?? []).slice(fromIndex));
91
+ },
92
+ subscribeEvents(runId, fromIndex, onEvent) {
93
+ const log = logs.get(runId) ?? [];
94
+ for (let index = fromIndex; index < log.length; index++) {
95
+ const stored = log[index];
96
+ if (stored) onEvent(stored.event, stored.eventIndex);
97
+ }
98
+ let runSubscribers = subscribers.get(runId);
99
+ if (!runSubscribers) {
100
+ runSubscribers = /* @__PURE__ */ new Set();
101
+ subscribers.set(runId, runSubscribers);
102
+ }
103
+ runSubscribers.add(onEvent);
104
+ return () => {
105
+ runSubscribers.delete(onEvent);
106
+ if (runSubscribers.size === 0) subscribers.delete(runId);
107
+ };
108
+ },
109
+ async claimRun(args) {
110
+ const existing = getRun(args.runId);
111
+ if (!existing) return { kind: "not-found" };
112
+ if (isTerminal(existing.status)) return {
113
+ kind: "not-claimable",
114
+ run: existing
115
+ };
116
+ if (!canClaim(existing.lease, args.leaseOwner, args.now)) return {
117
+ kind: "not-claimable",
118
+ run: existing
119
+ };
120
+ return {
121
+ kind: "claimed",
122
+ run: updateRun(args.runId, (run) => ({
123
+ ...run,
124
+ status: "running",
125
+ lease: lease(args.leaseOwner, args.leaseMs, args.now),
126
+ updatedAt: args.now
127
+ }))
128
+ };
129
+ },
130
+ async heartbeatRunLease(args) {
131
+ updateRun(args.runId, (run) => {
132
+ if (run.lease?.owner !== args.leaseOwner) return run;
133
+ return {
134
+ ...run,
135
+ lease: lease(args.leaseOwner, args.leaseMs, args.now),
136
+ updatedAt: args.now
137
+ };
138
+ });
139
+ },
140
+ async releaseRunLease(args) {
141
+ updateRun(args.runId, (run) => {
142
+ if (run.lease?.owner !== args.leaseOwner) return run;
143
+ return {
144
+ ...run,
145
+ lease: void 0
146
+ };
147
+ });
148
+ },
149
+ async markRunPaused(args) {
150
+ updateRun(args.runId, (run) => ({
151
+ ...run,
152
+ status: "paused",
153
+ waitingFor: args.waitingFor,
154
+ pendingApproval: args.pendingApproval,
155
+ wakeAt: args.wakeAt,
156
+ lease: void 0,
157
+ updatedAt: args.now
158
+ }));
159
+ },
160
+ async markRunFinished(args) {
161
+ updateRun(args.runId, (run) => ({
162
+ ...run,
163
+ status: "finished",
164
+ output: args.output,
165
+ waitingFor: void 0,
166
+ pendingApproval: void 0,
167
+ wakeAt: void 0,
168
+ lease: void 0,
169
+ updatedAt: args.now
170
+ }));
171
+ },
172
+ async markRunErrored(args) {
173
+ args.code;
174
+ updateRun(args.runId, (run) => ({
175
+ ...run,
176
+ status: "errored",
177
+ error: args.error,
178
+ waitingFor: void 0,
179
+ pendingApproval: void 0,
180
+ wakeAt: void 0,
181
+ lease: void 0,
182
+ updatedAt: args.now
183
+ }));
184
+ },
185
+ async scheduleTimer(args) {
186
+ timers.set(timerKey(args.runId, args.signalId), {
187
+ runId: args.runId,
188
+ workflowId: args.workflowId,
189
+ workflowVersion: args.workflowVersion,
190
+ wakeAt: args.wakeAt,
191
+ signalId: args.signalId
192
+ });
193
+ updateRun(args.runId, (run) => ({
194
+ ...run,
195
+ wakeAt: args.wakeAt,
196
+ updatedAt: args.now
197
+ }));
198
+ },
199
+ async claimDueTimers(args) {
200
+ const due = [];
201
+ for (const [key, timer] of timers.entries()) {
202
+ if (due.length >= args.limit) break;
203
+ if (timer.wakeAt > args.now) continue;
204
+ if (!canClaim(timer.lease, args.leaseOwner, args.now)) continue;
205
+ timers.set(key, {
206
+ ...timer,
207
+ lease: lease(args.leaseOwner, args.leaseMs, args.now)
208
+ });
209
+ due.push(cloneTimerWakeup(timer));
210
+ }
211
+ return due;
212
+ },
213
+ async deliverSignal(args) {
214
+ const run = getRun(args.runId);
215
+ if (!run) return { kind: "not-found" };
216
+ const key = signalKey(args.runId, args.delivery.signalId);
217
+ if (signalDeliveries.has(key)) return {
218
+ kind: "duplicate",
219
+ run
220
+ };
221
+ if (run.waitingFor?.signalName !== args.delivery.name) return {
222
+ kind: "not-waiting",
223
+ run
224
+ };
225
+ signalDeliveries.set(key, true);
226
+ timers.delete(timerKey(args.runId, args.delivery.signalId));
227
+ return {
228
+ kind: "delivered",
229
+ run: updateRun(args.runId, (current) => ({
230
+ ...current,
231
+ status: "queued",
232
+ waitingFor: void 0,
233
+ pendingApproval: void 0,
234
+ wakeAt: void 0,
235
+ updatedAt: args.now
236
+ }))
237
+ };
238
+ },
239
+ async deliverApproval(args) {
240
+ const run = getRun(args.runId);
241
+ if (!run) return { kind: "not-found" };
242
+ const key = signalKey(args.runId, `approval:${args.approval.approvalId}`);
243
+ if (signalDeliveries.has(key)) return {
244
+ kind: "duplicate",
245
+ run
246
+ };
247
+ if (run.pendingApproval?.approvalId !== args.approval.approvalId) return {
248
+ kind: "not-waiting",
249
+ run
250
+ };
251
+ signalDeliveries.set(key, true);
252
+ return {
253
+ kind: "delivered",
254
+ run: updateRun(args.runId, (current) => ({
255
+ ...current,
256
+ status: "queued",
257
+ waitingFor: void 0,
258
+ pendingApproval: void 0,
259
+ wakeAt: void 0,
260
+ updatedAt: args.now
261
+ }))
262
+ };
263
+ },
264
+ async upsertSchedule(args) {
265
+ schedules.set(args.scheduleId, {
266
+ scheduleId: args.scheduleId,
267
+ workflowId: args.workflowId,
268
+ workflowVersion: args.workflowVersion,
269
+ nextFireAt: args.nextFireAt,
270
+ input: args.input,
271
+ overlapPolicy: args.overlapPolicy,
272
+ enabled: args.enabled
273
+ });
274
+ },
275
+ async claimDueScheduleBuckets(args) {
276
+ const due = [];
277
+ for (const schedule of schedules.values()) {
278
+ if (due.length >= args.limit) break;
279
+ if (!schedule.enabled || schedule.nextFireAt === void 0) continue;
280
+ if (schedule.nextFireAt > args.now) continue;
281
+ const bucketId = `${schedule.nextFireAt}`;
282
+ const key = scheduleBucketKey(schedule.scheduleId, bucketId);
283
+ const existing = scheduleBuckets.get(key);
284
+ if (existing?.status === "started") continue;
285
+ if (existing && !canClaim(existing.lease, args.leaseOwner, args.now)) continue;
286
+ const bucket = {
287
+ scheduleId: schedule.scheduleId,
288
+ bucketId,
289
+ workflowId: schedule.workflowId,
290
+ workflowVersion: schedule.workflowVersion,
291
+ runId: `${schedule.workflowId}:${schedule.scheduleId}:${bucketId}`,
292
+ fireAt: schedule.nextFireAt,
293
+ input: schedule.input,
294
+ overlapPolicy: schedule.overlapPolicy,
295
+ status: "claimed",
296
+ lease: lease(args.leaseOwner, args.leaseMs, args.now)
297
+ };
298
+ scheduleBuckets.set(key, bucket);
299
+ due.push(cloneScheduleBucket(bucket));
300
+ }
301
+ return due;
302
+ },
303
+ async markScheduleBucketStarted(args) {
304
+ const key = scheduleBucketKey(args.scheduleId, args.bucketId);
305
+ const bucket = scheduleBuckets.get(key);
306
+ if (!bucket) return;
307
+ scheduleBuckets.set(key, {
308
+ ...bucket,
309
+ runId: args.runId,
310
+ status: "started"
311
+ });
312
+ },
313
+ async claimStaleRuns(args) {
314
+ const claims = [];
315
+ for (const run of runs.values()) {
316
+ if (claims.length >= args.limit) break;
317
+ if (run.status !== "running") continue;
318
+ if (!run.lease || run.lease.expiresAt > args.now) continue;
319
+ const nextLease = lease(args.leaseOwner, args.leaseMs, args.now);
320
+ const claimed = updateRun(run.runId, (current) => ({
321
+ ...current,
322
+ lease: nextLease,
323
+ updatedAt: args.now
324
+ }));
325
+ if (claimed) claims.push({
326
+ run: claimed,
327
+ lease: cloneLease(nextLease)
328
+ });
329
+ }
330
+ return claims;
331
+ },
332
+ async listRuns(args) {
333
+ const offset = args.cursor ? Number(args.cursor) : 0;
334
+ const start = Number.isFinite(offset) && offset > 0 ? offset : 0;
335
+ return Array.from(runs.values()).filter((run) => !args.workflowId || run.workflowId === args.workflowId).filter((run) => !args.status || run.status === args.status).sort((a, b) => b.updatedAt - a.updatedAt).slice(start, start + args.limit).map(toRunSummary);
336
+ },
337
+ async getRunTimeline(runId) {
338
+ const run = getRun(runId);
339
+ if (!run) return void 0;
340
+ return {
341
+ run,
342
+ events: cloneStoredEvents(logs.get(runId) ?? [])
343
+ };
344
+ }
345
+ };
346
+ }
347
+ function executionFromRunState(state, leaseValue) {
348
+ return {
349
+ runId: state.runId,
350
+ workflowId: state.workflowId,
351
+ workflowVersion: state.workflowVersion,
352
+ status: state.status,
353
+ input: state.input,
354
+ output: state.output,
355
+ error: state.error,
356
+ waitingFor: state.waitingFor,
357
+ pendingApproval: state.pendingApproval,
358
+ wakeAt: state.waitingFor?.signalName === "__timer" ? state.waitingFor.deadline : void 0,
359
+ lease: leaseValue ? cloneLease(leaseValue) : void 0,
360
+ createdAt: state.createdAt,
361
+ updatedAt: state.updatedAt
362
+ };
363
+ }
364
+ function storeEvent(runId, eventIndex, event) {
365
+ return {
366
+ runId,
367
+ eventIndex,
368
+ eventType: event.type,
369
+ stepId: getStepId(event),
370
+ event,
371
+ createdAt: event.ts
372
+ };
373
+ }
374
+ function getStepId(event) {
375
+ return "stepId" in event ? event.stepId : void 0;
376
+ }
377
+ function lease(owner, leaseMs, now) {
378
+ return {
379
+ owner,
380
+ expiresAt: now + leaseMs
381
+ };
382
+ }
383
+ function canClaim(existing, owner, now) {
384
+ return !existing || existing.owner === owner || existing.expiresAt <= now;
385
+ }
386
+ function isTerminal(status) {
387
+ return status === "finished" || status === "errored" || status === "aborted";
388
+ }
389
+ function timerKey(runId, signalId) {
390
+ return `${runId}:${signalId}`;
391
+ }
392
+ function signalKey(runId, signalId) {
393
+ return `${runId}:${signalId}`;
394
+ }
395
+ function scheduleBucketKey(scheduleId, bucketId) {
396
+ return `${scheduleId}:${bucketId}`;
397
+ }
398
+ function publish(subscribers, runId, event, index) {
399
+ const runSubscribers = subscribers.get(runId);
400
+ if (!runSubscribers) return;
401
+ for (const subscriber of runSubscribers) try {
402
+ subscriber(event, index);
403
+ } catch {}
404
+ }
405
+ function toRunSummary(run) {
406
+ return {
407
+ runId: run.runId,
408
+ workflowId: run.workflowId,
409
+ workflowVersion: run.workflowVersion,
410
+ status: run.status,
411
+ waitingFor: run.waitingFor,
412
+ pendingApproval: run.pendingApproval,
413
+ wakeAt: run.wakeAt,
414
+ createdAt: run.createdAt,
415
+ updatedAt: run.updatedAt
416
+ };
417
+ }
418
+ function cloneRun(run) {
419
+ return {
420
+ ...run,
421
+ waitingFor: run.waitingFor ? {
422
+ ...run.waitingFor,
423
+ meta: cloneRecord(run.waitingFor.meta)
424
+ } : void 0,
425
+ pendingApproval: run.pendingApproval ? { ...run.pendingApproval } : void 0,
426
+ lease: run.lease ? cloneLease(run.lease) : void 0
427
+ };
428
+ }
429
+ function cloneRunState(state) {
430
+ return {
431
+ ...state,
432
+ waitingFor: state.waitingFor ? {
433
+ ...state.waitingFor,
434
+ meta: cloneRecord(state.waitingFor.meta)
435
+ } : void 0,
436
+ pendingApproval: state.pendingApproval ? { ...state.pendingApproval } : void 0
437
+ };
438
+ }
439
+ function cloneStoredEvents(events) {
440
+ return events.map((event) => ({ ...event }));
441
+ }
442
+ function cloneTimerWakeup(timer) {
443
+ return { ...timer };
444
+ }
445
+ function cloneScheduleBucket(bucket) {
446
+ return { ...bucket };
447
+ }
448
+ function cloneLease(leaseValue) {
449
+ return { ...leaseValue };
450
+ }
451
+ function cloneRecord(value) {
452
+ return value ? { ...value } : value;
453
+ }
454
+
455
+ //#endregion
456
+ exports.inMemoryWorkflowExecutionStore = inMemoryWorkflowExecutionStore;
457
+ //# sourceMappingURL=in-memory-store.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"in-memory-store.cjs","names":["LogConflictError"],"sources":["../src/in-memory-store.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/require-await -- In-memory implementation satisfies async storage contracts synchronously. */\nimport { LogConflictError } from '@tanstack/workflow-core'\nimport type {\n DeleteReason,\n RunState,\n WorkflowEvent,\n} from '@tanstack/workflow-core'\nimport type {\n AppendEventsArgs,\n AppendEventsResult,\n ClaimDueScheduleBucketsArgs,\n ClaimDueTimersArgs,\n ClaimRunArgs,\n ClaimRunResult,\n ClaimStaleRunsArgs,\n CreateRunArgs,\n CreateRunResult,\n DeliverApprovalArgs,\n DeliverApprovalResult,\n DeliverSignalArgs,\n DeliverSignalResult,\n HeartbeatRunLeaseArgs,\n LeaseOwner,\n ListRunsArgs,\n LoadedExecution,\n MarkRunErroredArgs,\n MarkRunFinishedArgs,\n MarkRunPausedArgs,\n MarkScheduleBucketStartedArgs,\n ReadEventsArgs,\n ReleaseRunLeaseArgs,\n RunClaim,\n RunId,\n RunSummary,\n RunTimeline,\n SaveRunStateArgs,\n ScheduleBucket,\n ScheduleBucketId,\n ScheduleId,\n ScheduleTimerArgs,\n StoredWorkflowEvent,\n TimerWakeup,\n UpsertScheduleArgs,\n WorkflowExecution,\n WorkflowExecutionStore,\n WorkflowLease,\n WorkflowRunStoreAdapterStore,\n} from './types'\n\ninterface TimerRecord extends TimerWakeup {\n lease?: WorkflowLease\n}\n\ninterface ScheduleRecord {\n scheduleId: ScheduleId\n workflowId: string\n workflowVersion?: string\n nextFireAt?: number\n input: unknown\n overlapPolicy: ScheduleBucket['overlapPolicy']\n enabled: boolean\n}\n\ninterface ScheduleBucketRecord extends ScheduleBucket {\n status: 'claimed' | 'started'\n lease?: WorkflowLease\n}\n\nexport type InMemoryWorkflowExecutionStore = WorkflowExecutionStore &\n WorkflowRunStoreAdapterStore\n\nexport function inMemoryWorkflowExecutionStore(): InMemoryWorkflowExecutionStore {\n const runs = new Map<RunId, WorkflowExecution>()\n const runStates = new Map<RunId, RunState>()\n const logs = new Map<RunId, Array<StoredWorkflowEvent>>()\n const timers = new Map<string, TimerRecord>()\n const signalDeliveries = new Map<string, true>()\n const schedules = new Map<ScheduleId, ScheduleRecord>()\n const scheduleBuckets = new Map<string, ScheduleBucketRecord>()\n const subscribers = new Map<\n RunId,\n Set<(event: WorkflowEvent, index: number) => void>\n >()\n\n function setRun(run: WorkflowExecution) {\n runs.set(run.runId, cloneRun(run))\n }\n\n function getRun(runId: RunId) {\n const run = runs.get(runId)\n return run ? cloneRun(run) : undefined\n }\n\n function updateRun(\n runId: RunId,\n updater: (run: WorkflowExecution) => WorkflowExecution,\n ) {\n const existing = runs.get(runId)\n if (!existing) return undefined\n const next = updater(cloneRun(existing))\n setRun(next)\n return cloneRun(next)\n }\n\n return {\n async createRun(args: CreateRunArgs): Promise<CreateRunResult> {\n const existing = getRun(args.runId)\n if (existing) return { kind: 'existing', run: existing }\n\n const run: WorkflowExecution = {\n runId: args.runId,\n workflowId: args.workflowId,\n workflowVersion: args.workflowVersion,\n status: 'queued',\n input: args.input,\n createdAt: args.now,\n updatedAt: args.now,\n }\n setRun(run)\n return { kind: 'created', run: cloneRun(run) }\n },\n\n async loadRun(runId: RunId) {\n return getRun(runId)\n },\n\n async loadExecution(runId: RunId): Promise<LoadedExecution | undefined> {\n const run = getRun(runId)\n if (!run) return undefined\n return {\n run,\n events: cloneStoredEvents(logs.get(runId) ?? []),\n }\n },\n\n async loadRunState(runId: RunId) {\n const state = runStates.get(runId)\n return state ? cloneRunState(state) : undefined\n },\n\n async saveRunState(args: SaveRunStateArgs) {\n const state = cloneRunState(args.state)\n runStates.set(state.runId, state)\n setRun(executionFromRunState(state, runs.get(state.runId)?.lease))\n },\n\n async deleteRun(runId: RunId, _reason: DeleteReason) {\n runs.delete(runId)\n runStates.delete(runId)\n logs.delete(runId)\n subscribers.delete(runId)\n for (const [key, timer] of timers.entries()) {\n if (timer.runId === runId) timers.delete(key)\n }\n for (const key of signalDeliveries.keys()) {\n if (key.startsWith(`${runId}:`)) signalDeliveries.delete(key)\n }\n },\n\n async appendEvents(args: AppendEventsArgs): Promise<AppendEventsResult> {\n const log = logs.get(args.runId) ?? []\n if (log.length !== args.expectedNextIndex) {\n throw new LogConflictError(\n args.runId,\n args.expectedNextIndex,\n log[args.expectedNextIndex]?.event,\n )\n }\n\n for (const event of args.events) {\n const stored = storeEvent(args.runId, log.length, event)\n log.push(stored)\n publish(subscribers, args.runId, stored.event, stored.eventIndex)\n }\n\n logs.set(args.runId, log)\n return { nextIndex: log.length }\n },\n\n async readEvents(args: ReadEventsArgs) {\n const fromIndex = args.fromIndex ?? 0\n return cloneStoredEvents((logs.get(args.runId) ?? []).slice(fromIndex))\n },\n\n subscribeEvents(runId, fromIndex, onEvent) {\n const log = logs.get(runId) ?? []\n for (let index = fromIndex; index < log.length; index++) {\n const stored = log[index]\n if (stored) onEvent(stored.event, stored.eventIndex)\n }\n\n let runSubscribers = subscribers.get(runId)\n if (!runSubscribers) {\n runSubscribers = new Set()\n subscribers.set(runId, runSubscribers)\n }\n runSubscribers.add(onEvent)\n\n return () => {\n runSubscribers.delete(onEvent)\n if (runSubscribers.size === 0) subscribers.delete(runId)\n }\n },\n\n async claimRun(args: ClaimRunArgs): Promise<ClaimRunResult> {\n const existing = getRun(args.runId)\n if (!existing) return { kind: 'not-found' }\n if (isTerminal(existing.status)) {\n return { kind: 'not-claimable', run: existing }\n }\n if (!canClaim(existing.lease, args.leaseOwner, args.now)) {\n return { kind: 'not-claimable', run: existing }\n }\n\n const claimed = updateRun(args.runId, (run) => ({\n ...run,\n status: 'running',\n lease: lease(args.leaseOwner, args.leaseMs, args.now),\n updatedAt: args.now,\n }))\n return { kind: 'claimed', run: claimed! }\n },\n\n async heartbeatRunLease(args: HeartbeatRunLeaseArgs) {\n updateRun(args.runId, (run) => {\n if (run.lease?.owner !== args.leaseOwner) return run\n return {\n ...run,\n lease: lease(args.leaseOwner, args.leaseMs, args.now),\n updatedAt: args.now,\n }\n })\n },\n\n async releaseRunLease(args: ReleaseRunLeaseArgs) {\n updateRun(args.runId, (run) => {\n if (run.lease?.owner !== args.leaseOwner) return run\n return {\n ...run,\n lease: undefined,\n }\n })\n },\n\n async markRunPaused(args: MarkRunPausedArgs) {\n updateRun(args.runId, (run) => ({\n ...run,\n status: 'paused',\n waitingFor: args.waitingFor,\n pendingApproval: args.pendingApproval,\n wakeAt: args.wakeAt,\n lease: undefined,\n updatedAt: args.now,\n }))\n },\n\n async markRunFinished(args: MarkRunFinishedArgs) {\n updateRun(args.runId, (run) => ({\n ...run,\n status: 'finished',\n output: args.output,\n waitingFor: undefined,\n pendingApproval: undefined,\n wakeAt: undefined,\n lease: undefined,\n updatedAt: args.now,\n }))\n },\n\n async markRunErrored(args: MarkRunErroredArgs) {\n void args.code\n updateRun(args.runId, (run) => ({\n ...run,\n status: 'errored',\n error: args.error,\n waitingFor: undefined,\n pendingApproval: undefined,\n wakeAt: undefined,\n lease: undefined,\n updatedAt: args.now,\n }))\n },\n\n async scheduleTimer(args: ScheduleTimerArgs) {\n timers.set(timerKey(args.runId, args.signalId), {\n runId: args.runId,\n workflowId: args.workflowId,\n workflowVersion: args.workflowVersion,\n wakeAt: args.wakeAt,\n signalId: args.signalId,\n })\n updateRun(args.runId, (run) => ({\n ...run,\n wakeAt: args.wakeAt,\n updatedAt: args.now,\n }))\n },\n\n async claimDueTimers(args: ClaimDueTimersArgs) {\n const due: Array<TimerWakeup> = []\n for (const [key, timer] of timers.entries()) {\n if (due.length >= args.limit) break\n if (timer.wakeAt > args.now) continue\n if (!canClaim(timer.lease, args.leaseOwner, args.now)) continue\n\n timers.set(key, {\n ...timer,\n lease: lease(args.leaseOwner, args.leaseMs, args.now),\n })\n due.push(cloneTimerWakeup(timer))\n }\n return due\n },\n\n async deliverSignal<TPayload>(\n args: DeliverSignalArgs<TPayload>,\n ): Promise<DeliverSignalResult> {\n const run = getRun(args.runId)\n if (!run) return { kind: 'not-found' }\n\n const key = signalKey(args.runId, args.delivery.signalId)\n if (signalDeliveries.has(key)) return { kind: 'duplicate', run }\n if (run.waitingFor?.signalName !== args.delivery.name) {\n return { kind: 'not-waiting', run }\n }\n\n signalDeliveries.set(key, true)\n timers.delete(timerKey(args.runId, args.delivery.signalId))\n const updated = updateRun(args.runId, (current) => ({\n ...current,\n status: 'queued',\n waitingFor: undefined,\n pendingApproval: undefined,\n wakeAt: undefined,\n updatedAt: args.now,\n }))\n return { kind: 'delivered', run: updated! }\n },\n\n async deliverApproval(\n args: DeliverApprovalArgs,\n ): Promise<DeliverApprovalResult> {\n const run = getRun(args.runId)\n if (!run) return { kind: 'not-found' }\n\n const key = signalKey(args.runId, `approval:${args.approval.approvalId}`)\n if (signalDeliveries.has(key)) return { kind: 'duplicate', run }\n if (run.pendingApproval?.approvalId !== args.approval.approvalId) {\n return { kind: 'not-waiting', run }\n }\n\n signalDeliveries.set(key, true)\n const updated = updateRun(args.runId, (current) => ({\n ...current,\n status: 'queued',\n waitingFor: undefined,\n pendingApproval: undefined,\n wakeAt: undefined,\n updatedAt: args.now,\n }))\n return { kind: 'delivered', run: updated! }\n },\n\n async upsertSchedule(args: UpsertScheduleArgs) {\n schedules.set(args.scheduleId, {\n scheduleId: args.scheduleId,\n workflowId: args.workflowId,\n workflowVersion: args.workflowVersion,\n nextFireAt: args.nextFireAt,\n input: args.input,\n overlapPolicy: args.overlapPolicy,\n enabled: args.enabled,\n })\n },\n\n async claimDueScheduleBuckets(args: ClaimDueScheduleBucketsArgs) {\n const due: Array<ScheduleBucket> = []\n for (const schedule of schedules.values()) {\n if (due.length >= args.limit) break\n if (!schedule.enabled || schedule.nextFireAt === undefined) continue\n if (schedule.nextFireAt > args.now) continue\n\n const bucketId = `${schedule.nextFireAt}` satisfies ScheduleBucketId\n const key = scheduleBucketKey(schedule.scheduleId, bucketId)\n const existing = scheduleBuckets.get(key)\n if (existing?.status === 'started') continue\n if (existing && !canClaim(existing.lease, args.leaseOwner, args.now)) {\n continue\n }\n\n const bucket: ScheduleBucketRecord = {\n scheduleId: schedule.scheduleId,\n bucketId,\n workflowId: schedule.workflowId,\n workflowVersion: schedule.workflowVersion,\n runId: `${schedule.workflowId}:${schedule.scheduleId}:${bucketId}`,\n fireAt: schedule.nextFireAt,\n input: schedule.input,\n overlapPolicy: schedule.overlapPolicy,\n status: 'claimed',\n lease: lease(args.leaseOwner, args.leaseMs, args.now),\n }\n scheduleBuckets.set(key, bucket)\n due.push(cloneScheduleBucket(bucket))\n }\n return due\n },\n\n async markScheduleBucketStarted(args: MarkScheduleBucketStartedArgs) {\n const key = scheduleBucketKey(args.scheduleId, args.bucketId)\n const bucket = scheduleBuckets.get(key)\n if (!bucket) return\n scheduleBuckets.set(key, {\n ...bucket,\n runId: args.runId,\n status: 'started',\n })\n },\n\n async claimStaleRuns(args: ClaimStaleRunsArgs) {\n const claims: Array<RunClaim> = []\n for (const run of runs.values()) {\n if (claims.length >= args.limit) break\n if (run.status !== 'running') continue\n if (!run.lease || run.lease.expiresAt > args.now) continue\n\n const nextLease = lease(args.leaseOwner, args.leaseMs, args.now)\n const claimed = updateRun(run.runId, (current) => ({\n ...current,\n lease: nextLease,\n updatedAt: args.now,\n }))\n if (claimed) claims.push({ run: claimed, lease: cloneLease(nextLease) })\n }\n return claims\n },\n\n async listRuns(args: ListRunsArgs) {\n const offset = args.cursor ? Number(args.cursor) : 0\n const start = Number.isFinite(offset) && offset > 0 ? offset : 0\n return Array.from(runs.values())\n .filter((run) => !args.workflowId || run.workflowId === args.workflowId)\n .filter((run) => !args.status || run.status === args.status)\n .sort((a, b) => b.updatedAt - a.updatedAt)\n .slice(start, start + args.limit)\n .map(toRunSummary)\n },\n\n async getRunTimeline(runId: RunId): Promise<RunTimeline | undefined> {\n const run = getRun(runId)\n if (!run) return undefined\n return {\n run,\n events: cloneStoredEvents(logs.get(runId) ?? []),\n }\n },\n }\n}\n\nfunction executionFromRunState(\n state: RunState,\n leaseValue?: WorkflowLease,\n): WorkflowExecution {\n return {\n runId: state.runId,\n workflowId: state.workflowId,\n workflowVersion: state.workflowVersion,\n status: state.status,\n input: state.input,\n output: state.output,\n error: state.error,\n waitingFor: state.waitingFor,\n pendingApproval: state.pendingApproval,\n wakeAt:\n state.waitingFor?.signalName === '__timer'\n ? state.waitingFor.deadline\n : undefined,\n lease: leaseValue ? cloneLease(leaseValue) : undefined,\n createdAt: state.createdAt,\n updatedAt: state.updatedAt,\n }\n}\n\nfunction storeEvent(\n runId: RunId,\n eventIndex: number,\n event: WorkflowEvent,\n): StoredWorkflowEvent {\n return {\n runId,\n eventIndex,\n eventType: event.type,\n stepId: getStepId(event),\n event,\n createdAt: event.ts,\n }\n}\n\nfunction getStepId(event: WorkflowEvent) {\n return 'stepId' in event ? event.stepId : undefined\n}\n\nfunction lease(owner: LeaseOwner, leaseMs: number, now: number): WorkflowLease {\n return { owner, expiresAt: now + leaseMs }\n}\n\nfunction canClaim(\n existing: WorkflowLease | undefined,\n owner: LeaseOwner,\n now: number,\n) {\n return !existing || existing.owner === owner || existing.expiresAt <= now\n}\n\nfunction isTerminal(status: WorkflowExecution['status']) {\n return status === 'finished' || status === 'errored' || status === 'aborted'\n}\n\nfunction timerKey(runId: RunId, signalId: string) {\n return `${runId}:${signalId}`\n}\n\nfunction signalKey(runId: RunId, signalId: string) {\n return `${runId}:${signalId}`\n}\n\nfunction scheduleBucketKey(scheduleId: ScheduleId, bucketId: ScheduleBucketId) {\n return `${scheduleId}:${bucketId}`\n}\n\nfunction publish(\n subscribers: Map<RunId, Set<(event: WorkflowEvent, index: number) => void>>,\n runId: RunId,\n event: WorkflowEvent,\n index: number,\n) {\n const runSubscribers = subscribers.get(runId)\n if (!runSubscribers) return\n for (const subscriber of runSubscribers) {\n try {\n subscriber(event, index)\n } catch {\n /* Subscriber errors must not break persistence. */\n }\n }\n}\n\nfunction toRunSummary(run: WorkflowExecution): RunSummary {\n return {\n runId: run.runId,\n workflowId: run.workflowId,\n workflowVersion: run.workflowVersion,\n status: run.status,\n waitingFor: run.waitingFor,\n pendingApproval: run.pendingApproval,\n wakeAt: run.wakeAt,\n createdAt: run.createdAt,\n updatedAt: run.updatedAt,\n }\n}\n\nfunction cloneRun(run: WorkflowExecution): WorkflowExecution {\n return {\n ...run,\n waitingFor: run.waitingFor\n ? { ...run.waitingFor, meta: cloneRecord(run.waitingFor.meta) }\n : undefined,\n pendingApproval: run.pendingApproval\n ? { ...run.pendingApproval }\n : undefined,\n lease: run.lease ? cloneLease(run.lease) : undefined,\n }\n}\n\nfunction cloneRunState(state: RunState): RunState {\n return {\n ...state,\n waitingFor: state.waitingFor\n ? { ...state.waitingFor, meta: cloneRecord(state.waitingFor.meta) }\n : undefined,\n pendingApproval: state.pendingApproval\n ? { ...state.pendingApproval }\n : undefined,\n }\n}\n\nfunction cloneStoredEvents(\n events: ReadonlyArray<StoredWorkflowEvent>,\n): Array<StoredWorkflowEvent> {\n return events.map((event) => ({ ...event }))\n}\n\nfunction cloneTimerWakeup(timer: TimerWakeup): TimerWakeup {\n return { ...timer }\n}\n\nfunction cloneScheduleBucket(bucket: ScheduleBucket): ScheduleBucket {\n return { ...bucket }\n}\n\nfunction cloneLease(leaseValue: WorkflowLease): WorkflowLease {\n return { ...leaseValue }\n}\n\nfunction cloneRecord(value: Record<string, unknown> | undefined) {\n return value ? { ...value } : value\n}\n"],"mappings":"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"}