@dudousxd/nestjs-durable-store-prisma 0.16.0 → 0.18.0

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/index.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- import { StateStore, WorkflowRun, StepCheckpoint, RunQuery, RunFacetQuery, RunFacetRow, SignalWaiter } from '@dudousxd/nestjs-durable-core';
1
+ import { StateStore, WorkflowRun, RetentionPolicy, StepCheckpoint, RunQuery, RunFacetQuery, RunFacetRow, RunValueAxis, RunValueFacetOptions, RunValueFacetRow, ScheduleRecord, ScheduleQuery, SignalWaiter } from '@dudousxd/nestjs-durable-core';
2
2
 
3
3
  interface RunRow {
4
4
  id: string;
@@ -82,10 +82,23 @@ interface Delegate<Row> {
82
82
  deleteMany(args?: Args): Promise<{
83
83
  count: number;
84
84
  }>;
85
+ count(args?: Args): Promise<number>;
85
86
  /** Aggregate form — used only by `runFacets`, whose rows are `(status, origin, count)` cells, not
86
87
  * model rows, so the result type is stated at the call site rather than derived from `Row`. */
87
88
  groupBy(args: Args): Promise<Record<string, unknown>[]>;
88
89
  }
90
+ interface ScheduleRow {
91
+ id: string;
92
+ namespace: string;
93
+ workflow: string;
94
+ paused: boolean;
95
+ nextFireAt: bigint | null;
96
+ tags: unknown;
97
+ spec: unknown;
98
+ state: unknown;
99
+ createdAt: Date;
100
+ updatedAt: Date;
101
+ }
89
102
  interface DurablePrismaTx {
90
103
  durableWorkflowRun: Delegate<RunRow>;
91
104
  durableStepCheckpoint: Delegate<CheckpointRow>;
@@ -93,6 +106,8 @@ interface DurablePrismaTx {
93
106
  durableSignalWaiter: Delegate<WaiterRow>;
94
107
  durableBufferedSignal: Delegate<BufferedSignalRow>;
95
108
  durableBufferedEvent: Delegate<BufferedEventRow>;
109
+ /** Only needed for persisted schedules (`engine.schedules`) — add the `DurableSchedule` model. */
110
+ durableSchedule?: Delegate<ScheduleRow>;
96
111
  }
97
112
  interface DurablePrismaClient extends DurablePrismaTx {
98
113
  /** Prisma's interactive-transaction form: runs `fn` with a tx-scoped client and commits on resolve. */
@@ -118,6 +133,8 @@ declare class PrismaStateStore implements StateStore {
118
133
  private reindexAttributes;
119
134
  getRun(runId: string): Promise<WorkflowRun | null>;
120
135
  deleteRun(runId: string): Promise<void>;
136
+ deleteRuns(runIds: string[]): Promise<void>;
137
+ pruneTerminalRuns(policy: RetentionPolicy, nowMs: number, limit: number): Promise<number>;
121
138
  getCheckpoint(runId: string, seq: number): Promise<StepCheckpoint | null>;
122
139
  saveCheckpoint(checkpoint: StepCheckpoint): Promise<void>;
123
140
  transaction<T>(work: (tx: {
@@ -133,10 +150,23 @@ declare class PrismaStateStore implements StateStore {
133
150
  /** The `where` every run query shares — {@link listRuns} pages it, {@link runFacets} groups it. */
134
151
  private runWhere;
135
152
  listRuns(query: RunQuery): Promise<WorkflowRun[]>;
153
+ countRuns(query: Omit<RunQuery, 'limit' | 'offset'>): Promise<number>;
136
154
  /** `GROUP BY status, origin` over the same predicates {@link listRuns} pages — one aggregate, so a
137
155
  * console can show whole-set counts next to a bounded page instead of downloading every run to
138
156
  * count them in the browser. */
139
157
  runFacets(query: RunFacetQuery): Promise<RunFacetRow[]>;
158
+ /** Distinct values of one filter axis over the same predicates {@link listRuns} pages. A run-table
159
+ * column is a `groupBy` like {@link runFacets}, exact over the whole matching set; the tag and
160
+ * attribute axes live outside the row (json column / side table) and are counted from a bounded
161
+ * page of runs instead — see `RunValueFacetOptions.scan`. */
162
+ runValueFacets(axis: RunValueAxis, query: RunFacetQuery, opts?: RunValueFacetOptions): Promise<RunValueFacetRow[]>;
163
+ private schedules;
164
+ saveSchedule(record: ScheduleRecord): Promise<void>;
165
+ getSchedule(id: string): Promise<ScheduleRecord | null>;
166
+ /** One conditional `updateMany`: the compare-and-set on `next_fire_at` is a single statement. */
167
+ updateSchedule(id: string, patch: Partial<Omit<ScheduleRecord, 'id' | 'createdAt'>>, expectedNextFireAt?: number | null): Promise<boolean>;
168
+ deleteSchedule(id: string): Promise<boolean>;
169
+ listSchedules(query: ScheduleQuery): Promise<ScheduleRecord[]>;
140
170
  listCheckpoints(runId: string): Promise<StepCheckpoint[]>;
141
171
  getLatestCheckpointByName(runId: string, name: string): Promise<StepCheckpoint | undefined>;
142
172
  listCheckpointsByNamePrefix(runId: string, prefixes: string[]): Promise<StepCheckpoint[]>;
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { StateStore, WorkflowRun, StepCheckpoint, RunQuery, RunFacetQuery, RunFacetRow, SignalWaiter } from '@dudousxd/nestjs-durable-core';
1
+ import { StateStore, WorkflowRun, RetentionPolicy, StepCheckpoint, RunQuery, RunFacetQuery, RunFacetRow, RunValueAxis, RunValueFacetOptions, RunValueFacetRow, ScheduleRecord, ScheduleQuery, SignalWaiter } from '@dudousxd/nestjs-durable-core';
2
2
 
3
3
  interface RunRow {
4
4
  id: string;
@@ -82,10 +82,23 @@ interface Delegate<Row> {
82
82
  deleteMany(args?: Args): Promise<{
83
83
  count: number;
84
84
  }>;
85
+ count(args?: Args): Promise<number>;
85
86
  /** Aggregate form — used only by `runFacets`, whose rows are `(status, origin, count)` cells, not
86
87
  * model rows, so the result type is stated at the call site rather than derived from `Row`. */
87
88
  groupBy(args: Args): Promise<Record<string, unknown>[]>;
88
89
  }
90
+ interface ScheduleRow {
91
+ id: string;
92
+ namespace: string;
93
+ workflow: string;
94
+ paused: boolean;
95
+ nextFireAt: bigint | null;
96
+ tags: unknown;
97
+ spec: unknown;
98
+ state: unknown;
99
+ createdAt: Date;
100
+ updatedAt: Date;
101
+ }
89
102
  interface DurablePrismaTx {
90
103
  durableWorkflowRun: Delegate<RunRow>;
91
104
  durableStepCheckpoint: Delegate<CheckpointRow>;
@@ -93,6 +106,8 @@ interface DurablePrismaTx {
93
106
  durableSignalWaiter: Delegate<WaiterRow>;
94
107
  durableBufferedSignal: Delegate<BufferedSignalRow>;
95
108
  durableBufferedEvent: Delegate<BufferedEventRow>;
109
+ /** Only needed for persisted schedules (`engine.schedules`) — add the `DurableSchedule` model. */
110
+ durableSchedule?: Delegate<ScheduleRow>;
96
111
  }
97
112
  interface DurablePrismaClient extends DurablePrismaTx {
98
113
  /** Prisma's interactive-transaction form: runs `fn` with a tx-scoped client and commits on resolve. */
@@ -118,6 +133,8 @@ declare class PrismaStateStore implements StateStore {
118
133
  private reindexAttributes;
119
134
  getRun(runId: string): Promise<WorkflowRun | null>;
120
135
  deleteRun(runId: string): Promise<void>;
136
+ deleteRuns(runIds: string[]): Promise<void>;
137
+ pruneTerminalRuns(policy: RetentionPolicy, nowMs: number, limit: number): Promise<number>;
121
138
  getCheckpoint(runId: string, seq: number): Promise<StepCheckpoint | null>;
122
139
  saveCheckpoint(checkpoint: StepCheckpoint): Promise<void>;
123
140
  transaction<T>(work: (tx: {
@@ -133,10 +150,23 @@ declare class PrismaStateStore implements StateStore {
133
150
  /** The `where` every run query shares — {@link listRuns} pages it, {@link runFacets} groups it. */
134
151
  private runWhere;
135
152
  listRuns(query: RunQuery): Promise<WorkflowRun[]>;
153
+ countRuns(query: Omit<RunQuery, 'limit' | 'offset'>): Promise<number>;
136
154
  /** `GROUP BY status, origin` over the same predicates {@link listRuns} pages — one aggregate, so a
137
155
  * console can show whole-set counts next to a bounded page instead of downloading every run to
138
156
  * count them in the browser. */
139
157
  runFacets(query: RunFacetQuery): Promise<RunFacetRow[]>;
158
+ /** Distinct values of one filter axis over the same predicates {@link listRuns} pages. A run-table
159
+ * column is a `groupBy` like {@link runFacets}, exact over the whole matching set; the tag and
160
+ * attribute axes live outside the row (json column / side table) and are counted from a bounded
161
+ * page of runs instead — see `RunValueFacetOptions.scan`. */
162
+ runValueFacets(axis: RunValueAxis, query: RunFacetQuery, opts?: RunValueFacetOptions): Promise<RunValueFacetRow[]>;
163
+ private schedules;
164
+ saveSchedule(record: ScheduleRecord): Promise<void>;
165
+ getSchedule(id: string): Promise<ScheduleRecord | null>;
166
+ /** One conditional `updateMany`: the compare-and-set on `next_fire_at` is a single statement. */
167
+ updateSchedule(id: string, patch: Partial<Omit<ScheduleRecord, 'id' | 'createdAt'>>, expectedNextFireAt?: number | null): Promise<boolean>;
168
+ deleteSchedule(id: string): Promise<boolean>;
169
+ listSchedules(query: ScheduleQuery): Promise<ScheduleRecord[]>;
140
170
  listCheckpoints(runId: string): Promise<StepCheckpoint[]>;
141
171
  getLatestCheckpointByName(runId: string, name: string): Promise<StepCheckpoint | undefined>;
142
172
  listCheckpointsByNamePrefix(runId: string, prefixes: string[]): Promise<StepCheckpoint[]>;
package/dist/index.js CHANGED
@@ -2,7 +2,7 @@ var __defProp = Object.defineProperty;
2
2
  var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
3
3
 
4
4
  // src/prisma-state-store.ts
5
- import { attributeColumnFor, attributeOperand, mergeRunFacetRows, normalizeAttributeRows } from "@dudousxd/nestjs-durable-core";
5
+ import { RUN_VALUE_FACET_SCAN, TERMINAL_RUN_STATUSES, attributePredicateOperands, axisIsRunColumn, mergeRunFacetRows, mergeRunValueFacetRows, normalizeAttributeRows, parseDuration, runValueFacetsFromRuns } from "@dudousxd/nestjs-durable-core";
6
6
  function namespaceWhere(namespace) {
7
7
  if (namespace === void 0) return {};
8
8
  return {
@@ -76,6 +76,99 @@ var PrismaStateStore = class {
76
76
  }
77
77
  });
78
78
  }
79
+ async deleteRuns(runIds) {
80
+ if (runIds.length === 0) return;
81
+ await this.db.$transaction(async (tx) => {
82
+ await tx.durableStepCheckpoint.deleteMany({
83
+ where: {
84
+ runId: {
85
+ in: runIds
86
+ }
87
+ }
88
+ });
89
+ await tx.durableSignalWaiter.deleteMany({
90
+ where: {
91
+ runId: {
92
+ in: runIds
93
+ }
94
+ }
95
+ });
96
+ await tx.durableRunAttribute.deleteMany({
97
+ where: {
98
+ runId: {
99
+ in: runIds
100
+ }
101
+ }
102
+ });
103
+ await tx.durableWorkflowRun.deleteMany({
104
+ where: {
105
+ id: {
106
+ in: runIds
107
+ }
108
+ }
109
+ });
110
+ });
111
+ }
112
+ async pruneTerminalRuns(policy, nowMs, limit) {
113
+ const statuses = policy.statuses.filter((s) => TERMINAL_RUN_STATUSES.includes(s));
114
+ if (statuses.length === 0 || limit <= 0) return 0;
115
+ if (policy.maxAge == null && policy.maxCount == null) return 0;
116
+ const scoped = this.runWhere({
117
+ ...policy.scope ?? {},
118
+ statuses
119
+ });
120
+ const ids = /* @__PURE__ */ new Set();
121
+ if (policy.maxAge != null) {
122
+ const cutoff = new Date(nowMs - parseDuration(policy.maxAge));
123
+ const rows = await this.db.durableWorkflowRun.findMany({
124
+ where: {
125
+ AND: [
126
+ scoped,
127
+ {
128
+ updatedAt: {
129
+ lt: cutoff
130
+ }
131
+ }
132
+ ]
133
+ },
134
+ select: {
135
+ id: true
136
+ },
137
+ orderBy: {
138
+ updatedAt: "asc"
139
+ },
140
+ take: limit
141
+ });
142
+ for (const r of rows) ids.add(r.id);
143
+ }
144
+ if (policy.maxCount != null && ids.size < limit) {
145
+ const rows = await this.db.durableWorkflowRun.findMany({
146
+ where: scoped,
147
+ select: {
148
+ id: true
149
+ },
150
+ orderBy: [
151
+ {
152
+ updatedAt: "desc"
153
+ },
154
+ {
155
+ id: "desc"
156
+ }
157
+ ],
158
+ skip: policy.maxCount,
159
+ take: limit
160
+ });
161
+ for (const r of rows) {
162
+ if (ids.size >= limit) break;
163
+ ids.add(r.id);
164
+ }
165
+ }
166
+ const doomed = [
167
+ ...ids
168
+ ].slice(0, limit);
169
+ await this.deleteRuns(doomed);
170
+ return doomed.length;
171
+ }
79
172
  async getCheckpoint(runId, seq) {
80
173
  const row = await this.db.durableStepCheckpoint.findUnique({
81
174
  where: {
@@ -208,19 +301,26 @@ var PrismaStateStore = class {
208
301
  const where = {
209
302
  ...namespaceWhere(query.namespace)
210
303
  };
304
+ const and = [];
211
305
  if (query.workflow) where.workflow = query.workflow;
306
+ if (query.workflows) and.push(anyOf(query.workflows.map((w) => ({
307
+ workflow: w
308
+ }))));
309
+ if (query.namespaces) and.push(anyOf(query.namespaces.map((n) => ({
310
+ namespace: n
311
+ }))));
212
312
  if (query.origin !== void 0) where.origin = query.origin;
313
+ if (query.origins) and.push(anyOf(query.origins.map((o) => ({
314
+ origin: o
315
+ }))));
213
316
  if (query.status && query.statuses) {
214
- where.AND = [
215
- {
216
- status: query.status
217
- },
218
- {
219
- status: {
220
- in: query.statuses
221
- }
317
+ and.push({
318
+ status: query.status
319
+ }, {
320
+ status: {
321
+ in: query.statuses
222
322
  }
223
- ];
323
+ });
224
324
  } else if (query.status) {
225
325
  where.status = query.status;
226
326
  } else if (query.statuses) {
@@ -231,13 +331,13 @@ var PrismaStateStore = class {
231
331
  if (query.tag) where.tags = {
232
332
  array_contains: query.tag
233
333
  };
234
- if (query.attributes?.length) {
235
- const existing = where.AND ?? [];
236
- where.AND = [
237
- ...existing,
238
- ...query.attributes.map((f) => attributeSome(f))
239
- ];
240
- }
334
+ if (query.tags) and.push(anyOf(query.tags.map((t) => ({
335
+ tags: {
336
+ array_contains: t
337
+ }
338
+ }))));
339
+ if (query.attributes?.length) and.push(...query.attributes.map((f) => attributeSome(f)));
340
+ if (and.length) where.AND = and;
241
341
  return where;
242
342
  }
243
343
  async listRuns(query) {
@@ -252,6 +352,11 @@ var PrismaStateStore = class {
252
352
  });
253
353
  return rows.map(fromRunRow);
254
354
  }
355
+ async countRuns(query) {
356
+ return this.db.durableWorkflowRun.count({
357
+ where: this.runWhere(query)
358
+ });
359
+ }
255
360
  /** `GROUP BY status, origin` over the same predicates {@link listRuns} pages — one aggregate, so a
256
361
  * console can show whole-set counts next to a bounded page instead of downloading every run to
257
362
  * count them in the browser. */
@@ -272,6 +377,127 @@ var PrismaStateStore = class {
272
377
  count: r._count._all
273
378
  })));
274
379
  }
380
+ /** Distinct values of one filter axis over the same predicates {@link listRuns} pages. A run-table
381
+ * column is a `groupBy` like {@link runFacets}, exact over the whole matching set; the tag and
382
+ * attribute axes live outside the row (json column / side table) and are counted from a bounded
383
+ * page of runs instead — see `RunValueFacetOptions.scan`. */
384
+ async runValueFacets(axis, query, opts) {
385
+ if (!axisIsRunColumn(axis)) {
386
+ const runs = await this.listRuns({
387
+ ...query,
388
+ limit: opts?.scan ?? RUN_VALUE_FACET_SCAN
389
+ });
390
+ return runValueFacetsFromRuns(runs, axis, opts);
391
+ }
392
+ const rows = await this.db.durableWorkflowRun.groupBy({
393
+ by: [
394
+ axis.field
395
+ ],
396
+ where: this.runWhere(query),
397
+ _count: {
398
+ _all: true
399
+ }
400
+ });
401
+ return mergeRunValueFacetRows(rows.map((r) => ({
402
+ value: r[axis.field] ?? null,
403
+ count: r._count._all
404
+ })), opts);
405
+ }
406
+ // ---- persisted schedules ----------------------------------------------------------------------
407
+ schedules() {
408
+ const delegate = this.db.durableSchedule;
409
+ if (!delegate) {
410
+ throw new Error("persisted schedules need the DurableSchedule model \u2014 copy it from prisma/schema.prisma into your schema and re-run `prisma generate`");
411
+ }
412
+ return delegate;
413
+ }
414
+ async saveSchedule(record) {
415
+ const data = toScheduleData(record);
416
+ await this.schedules().upsert({
417
+ where: {
418
+ id: record.id
419
+ },
420
+ create: data,
421
+ update: data
422
+ });
423
+ }
424
+ async getSchedule(id) {
425
+ const row = await this.schedules().findUnique({
426
+ where: {
427
+ id
428
+ }
429
+ });
430
+ return row ? fromScheduleRow(row) : null;
431
+ }
432
+ /** One conditional `updateMany`: the compare-and-set on `next_fire_at` is a single statement. */
433
+ async updateSchedule(id, patch, expectedNextFireAt) {
434
+ const data = {};
435
+ if (patch.namespace !== void 0) data.namespace = patch.namespace;
436
+ if (patch.workflow !== void 0) data.workflow = patch.workflow;
437
+ if (patch.paused !== void 0) data.paused = patch.paused;
438
+ if ("nextFireAt" in patch) data.nextFireAt = patch.nextFireAt == null ? null : BigInt(patch.nextFireAt);
439
+ if ("tags" in patch) data.tags = jsonOrNull(patch.tags);
440
+ if (patch.spec !== void 0) data.spec = patch.spec;
441
+ if (patch.state !== void 0) data.state = patch.state;
442
+ if (patch.updatedAt !== void 0) data.updatedAt = patch.updatedAt;
443
+ if (!Object.keys(data).length) return await this.getSchedule(id) !== null;
444
+ const where = {
445
+ id
446
+ };
447
+ if (expectedNextFireAt !== void 0) where.nextFireAt = expectedNextFireAt === null ? null : BigInt(expectedNextFireAt);
448
+ const { count } = await this.schedules().updateMany({
449
+ where,
450
+ data
451
+ });
452
+ return count > 0;
453
+ }
454
+ async deleteSchedule(id) {
455
+ const { count } = await this.schedules().deleteMany({
456
+ where: {
457
+ id
458
+ }
459
+ });
460
+ return count > 0;
461
+ }
462
+ async listSchedules(query) {
463
+ const where = {};
464
+ if (query.namespace !== void 0) where.namespace = query.namespace;
465
+ if (query.workflow !== void 0) where.workflow = query.workflow;
466
+ if (query.paused !== void 0) where.paused = query.paused;
467
+ if (query.tag !== void 0) where.tags = {
468
+ array_contains: query.tag
469
+ };
470
+ if (query.dueBy !== void 0) {
471
+ where.AND = [
472
+ {
473
+ paused: false
474
+ },
475
+ {
476
+ nextFireAt: {
477
+ lte: BigInt(query.dueBy)
478
+ }
479
+ }
480
+ ];
481
+ }
482
+ const rows = await this.schedules().findMany({
483
+ where,
484
+ // Soonest-due first, never-firing (NULL) last, id as the stable tie-break.
485
+ orderBy: [
486
+ {
487
+ nextFireAt: {
488
+ sort: "asc",
489
+ nulls: "last"
490
+ }
491
+ },
492
+ {
493
+ id: "asc"
494
+ }
495
+ ],
496
+ take: query.limit,
497
+ skip: query.offset
498
+ });
499
+ return rows.map(fromScheduleRow);
500
+ }
275
501
  async listCheckpoints(runId) {
276
502
  const rows = await this.db.durableStepCheckpoint.findMany({
277
503
  where: {
@@ -436,23 +662,35 @@ var PrismaStateStore = class {
436
662
  }
437
663
  };
438
664
  function attributeSome(f) {
439
- const col = attributeColumnFor(f);
440
- const operand = attributeOperand(f);
441
- const condition = f.op === "eq" ? operand : f.op === "ne" ? {
442
- not: operand
443
- } : {
444
- [f.op]: operand
445
- };
665
+ const comparisons = attributePredicateOperands(f).map(({ column, comparator, operand }) => ({
666
+ [column]: comparator === "=" ? operand : comparator === "<>" ? {
667
+ not: operand
668
+ } : {
669
+ [f.op]: operand
670
+ }
671
+ }));
672
+ if (comparisons.length === 0) return MATCHES_NOTHING;
446
673
  return {
447
674
  attributes: {
448
675
  some: {
449
676
  key: f.key,
450
- [col]: condition
677
+ ...anyOf(comparisons)
451
678
  }
452
679
  }
453
680
  };
454
681
  }
455
682
  __name(attributeSome, "attributeSome");
683
+ var MATCHES_NOTHING = {
684
+ id: {
685
+ in: []
686
+ }
687
+ };
688
+ function anyOf(branches) {
689
+ return branches.length ? {
690
+ OR: branches
691
+ } : MATCHES_NOTHING;
692
+ }
693
+ __name(anyOf, "anyOf");
456
694
  var bigOrNull = /* @__PURE__ */ __name((n) => n == null ? null : BigInt(n), "bigOrNull");
457
695
  var numOrUndef = /* @__PURE__ */ __name((n) => n == null ? void 0 : Number(n), "numOrUndef");
458
696
  var jsonOrNull = /* @__PURE__ */ __name((v) => v ?? null, "jsonOrNull");
@@ -581,6 +819,39 @@ function fromCheckpointRow(row) {
581
819
  };
582
820
  }
583
821
  __name(fromCheckpointRow, "fromCheckpointRow");
822
+ function toScheduleData(r) {
823
+ return {
824
+ id: r.id,
825
+ namespace: r.namespace,
826
+ workflow: r.workflow,
827
+ paused: r.paused,
828
+ nextFireAt: r.nextFireAt == null ? null : BigInt(r.nextFireAt),
829
+ tags: jsonOrNull(r.tags),
830
+ spec: r.spec,
831
+ state: r.state,
832
+ createdAt: r.createdAt,
833
+ updatedAt: r.updatedAt
834
+ };
835
+ }
836
+ __name(toScheduleData, "toScheduleData");
837
+ function fromScheduleRow(row) {
838
+ const tags = Array.isArray(row.tags) ? row.tags : void 0;
839
+ return {
840
+ id: row.id,
841
+ namespace: row.namespace,
842
+ workflow: row.workflow,
843
+ paused: row.paused,
844
+ nextFireAt: row.nextFireAt == null ? null : Number(row.nextFireAt),
845
+ ...tags?.length ? {
846
+ tags
847
+ } : {},
848
+ spec: row.spec ?? {},
849
+ state: row.state ?? {},
850
+ createdAt: row.createdAt,
851
+ updatedAt: row.updatedAt
852
+ };
853
+ }
854
+ __name(fromScheduleRow, "fromScheduleRow");
584
855
 
585
856
  // src/schema.ts
586
857
  function durableManagedTables() {
@@ -590,7 +861,8 @@ function durableManagedTables() {
590
861
  "durable_run_attributes",
591
862
  "durable_signal_waiters",
592
863
  "durable_buffered_signals",
593
- "durable_buffered_events"
864
+ "durable_buffered_events",
865
+ "durable_schedules"
594
866
  ];
595
867
  }
596
868
  __name(durableManagedTables, "durableManagedTables");