@dudousxd/nestjs-durable-store-typeorm 0.9.0 → 0.10.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.cjs CHANGED
@@ -30,6 +30,9 @@ __export(index_exports, {
30
30
  TypeOrmStateStore: () => TypeOrmStateStore,
31
31
  WorkflowRunEntity: () => WorkflowRunEntity,
32
32
  buildWidenStatements: () => buildWidenStatements,
33
+ columnNamer: () => columnNamer,
34
+ durableColumnResolver: () => durableColumnResolver,
35
+ durableEntities: () => durableEntities,
33
36
  ensureTypeOrmDurableSchema: () => ensureTypeOrmDurableSchema,
34
37
  jsonBlobColumnType: () => jsonBlobColumnType,
35
38
  parseJsonColumn: () => parseJsonColumn
@@ -38,17 +41,6 @@ module.exports = __toCommonJS(index_exports);
38
41
 
39
42
  // src/entities.ts
40
43
  var import_typeorm = require("typeorm");
41
- function _ts_decorate(decorators, target, key, desc) {
42
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
43
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
44
- else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
45
- return c > 3 && r && Object.defineProperty(target, key, r), r;
46
- }
47
- __name(_ts_decorate, "_ts_decorate");
48
- function _ts_metadata(k, v) {
49
- if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
50
- }
51
- __name(_ts_metadata, "_ts_metadata");
52
44
  function parseJsonColumn(raw, field) {
53
45
  if (raw == null) return void 0;
54
46
  if (typeof raw !== "string") return raw;
@@ -67,6 +59,16 @@ function jsonColumnTransformer(field) {
67
59
  };
68
60
  }
69
61
  __name(jsonColumnTransformer, "jsonColumnTransformer");
62
+ function snakeCase(property) {
63
+ return property.replace(/[A-Z]/g, (c) => `_${c.toLowerCase()}`);
64
+ }
65
+ __name(snakeCase, "snakeCase");
66
+ function columnNamer(naming) {
67
+ if (naming === "snake_case") return snakeCase;
68
+ if (naming === "preserve") return (property) => property;
69
+ return naming;
70
+ }
71
+ __name(columnNamer, "columnNamer");
70
72
  var WorkflowRunEntity = class {
71
73
  static {
72
74
  __name(this, "WorkflowRunEntity");
@@ -87,94 +89,6 @@ var WorkflowRunEntity = class {
87
89
  createdAt;
88
90
  updatedAt;
89
91
  };
90
- _ts_decorate([
91
- (0, import_typeorm.PrimaryColumn)("text"),
92
- _ts_metadata("design:type", String)
93
- ], WorkflowRunEntity.prototype, "id", void 0);
94
- _ts_decorate([
95
- (0, import_typeorm.Column)("text"),
96
- _ts_metadata("design:type", String)
97
- ], WorkflowRunEntity.prototype, "workflow", void 0);
98
- _ts_decorate([
99
- (0, import_typeorm.Column)("text"),
100
- _ts_metadata("design:type", String)
101
- ], WorkflowRunEntity.prototype, "workflowVersion", void 0);
102
- _ts_decorate([
103
- (0, import_typeorm.Column)("text"),
104
- _ts_metadata("design:type", typeof RunStatus === "undefined" ? Object : RunStatus)
105
- ], WorkflowRunEntity.prototype, "status", void 0);
106
- _ts_decorate([
107
- (0, import_typeorm.Column)("text", {
108
- nullable: true,
109
- transformer: jsonColumnTransformer("runs.input")
110
- }),
111
- _ts_metadata("design:type", Object)
112
- ], WorkflowRunEntity.prototype, "input", void 0);
113
- _ts_decorate([
114
- (0, import_typeorm.Column)("text", {
115
- nullable: true,
116
- transformer: jsonColumnTransformer("runs.output")
117
- }),
118
- _ts_metadata("design:type", Object)
119
- ], WorkflowRunEntity.prototype, "output", void 0);
120
- _ts_decorate([
121
- (0, import_typeorm.Column)("text", {
122
- nullable: true,
123
- transformer: jsonColumnTransformer("runs.error")
124
- }),
125
- _ts_metadata("design:type", Object)
126
- ], WorkflowRunEntity.prototype, "error", void 0);
127
- _ts_decorate([
128
- (0, import_typeorm.Column)({
129
- nullable: true
130
- }),
131
- _ts_metadata("design:type", typeof Date === "undefined" ? Object : Date)
132
- ], WorkflowRunEntity.prototype, "wakeAt", void 0);
133
- _ts_decorate([
134
- (0, import_typeorm.Column)("text", {
135
- nullable: true
136
- }),
137
- _ts_metadata("design:type", Object)
138
- ], WorkflowRunEntity.prototype, "lockedBy", void 0);
139
- _ts_decorate([
140
- (0, import_typeorm.Column)({
141
- nullable: true
142
- }),
143
- _ts_metadata("design:type", typeof Date === "undefined" ? Object : Date)
144
- ], WorkflowRunEntity.prototype, "lockedUntil", void 0);
145
- _ts_decorate([
146
- (0, import_typeorm.Column)("integer", {
147
- nullable: true
148
- }),
149
- _ts_metadata("design:type", Number)
150
- ], WorkflowRunEntity.prototype, "recoveryAttempts", void 0);
151
- _ts_decorate([
152
- (0, import_typeorm.Column)("text", {
153
- nullable: true,
154
- transformer: jsonColumnTransformer("runs.tags")
155
- }),
156
- _ts_metadata("design:type", Object)
157
- ], WorkflowRunEntity.prototype, "tags", void 0);
158
- _ts_decorate([
159
- (0, import_typeorm.Column)("text", {
160
- nullable: true,
161
- transformer: jsonColumnTransformer("runs.searchAttributes")
162
- }),
163
- _ts_metadata("design:type", Object)
164
- ], WorkflowRunEntity.prototype, "searchAttributes", void 0);
165
- _ts_decorate([
166
- (0, import_typeorm.Column)(),
167
- _ts_metadata("design:type", typeof Date === "undefined" ? Object : Date)
168
- ], WorkflowRunEntity.prototype, "createdAt", void 0);
169
- _ts_decorate([
170
- (0, import_typeorm.Column)(),
171
- _ts_metadata("design:type", typeof Date === "undefined" ? Object : Date)
172
- ], WorkflowRunEntity.prototype, "updatedAt", void 0);
173
- WorkflowRunEntity = _ts_decorate([
174
- (0, import_typeorm.Entity)({
175
- name: "durable_workflow_runs"
176
- })
177
- ], WorkflowRunEntity);
178
92
  var StepCheckpointEntity = class {
179
93
  static {
180
94
  __name(this, "StepCheckpointEntity");
@@ -196,93 +110,6 @@ var StepCheckpointEntity = class {
196
110
  startedAt;
197
111
  finishedAt;
198
112
  };
199
- _ts_decorate([
200
- (0, import_typeorm.PrimaryColumn)("text"),
201
- _ts_metadata("design:type", String)
202
- ], StepCheckpointEntity.prototype, "runId", void 0);
203
- _ts_decorate([
204
- (0, import_typeorm.PrimaryColumn)("integer"),
205
- _ts_metadata("design:type", Number)
206
- ], StepCheckpointEntity.prototype, "seq", void 0);
207
- _ts_decorate([
208
- (0, import_typeorm.Column)("text"),
209
- _ts_metadata("design:type", String)
210
- ], StepCheckpointEntity.prototype, "name", void 0);
211
- _ts_decorate([
212
- (0, import_typeorm.Column)("text"),
213
- _ts_metadata("design:type", typeof StepKind === "undefined" ? Object : StepKind)
214
- ], StepCheckpointEntity.prototype, "kind", void 0);
215
- _ts_decorate([
216
- (0, import_typeorm.Column)("text"),
217
- _ts_metadata("design:type", String)
218
- ], StepCheckpointEntity.prototype, "stepId", void 0);
219
- _ts_decorate([
220
- (0, import_typeorm.Column)("text"),
221
- _ts_metadata("design:type", String)
222
- ], StepCheckpointEntity.prototype, "status", void 0);
223
- _ts_decorate([
224
- (0, import_typeorm.Column)("text", {
225
- nullable: true,
226
- transformer: jsonColumnTransformer("checkpoints.input")
227
- }),
228
- _ts_metadata("design:type", Object)
229
- ], StepCheckpointEntity.prototype, "input", void 0);
230
- _ts_decorate([
231
- (0, import_typeorm.Column)("text", {
232
- nullable: true,
233
- transformer: jsonColumnTransformer("checkpoints.output")
234
- }),
235
- _ts_metadata("design:type", Object)
236
- ], StepCheckpointEntity.prototype, "output", void 0);
237
- _ts_decorate([
238
- (0, import_typeorm.Column)("text", {
239
- nullable: true,
240
- transformer: jsonColumnTransformer("checkpoints.error")
241
- }),
242
- _ts_metadata("design:type", Object)
243
- ], StepCheckpointEntity.prototype, "error", void 0);
244
- _ts_decorate([
245
- (0, import_typeorm.Column)("text", {
246
- nullable: true,
247
- transformer: jsonColumnTransformer("checkpoints.events")
248
- }),
249
- _ts_metadata("design:type", Object)
250
- ], StepCheckpointEntity.prototype, "events", void 0);
251
- _ts_decorate([
252
- (0, import_typeorm.Column)("integer"),
253
- _ts_metadata("design:type", Number)
254
- ], StepCheckpointEntity.prototype, "attempts", void 0);
255
- _ts_decorate([
256
- (0, import_typeorm.Column)("text", {
257
- nullable: true
258
- }),
259
- _ts_metadata("design:type", Object)
260
- ], StepCheckpointEntity.prototype, "workerGroup", void 0);
261
- _ts_decorate([
262
- (0, import_typeorm.Column)({
263
- nullable: true
264
- }),
265
- _ts_metadata("design:type", typeof Date === "undefined" ? Object : Date)
266
- ], StepCheckpointEntity.prototype, "wakeAt", void 0);
267
- _ts_decorate([
268
- (0, import_typeorm.Column)({
269
- nullable: true
270
- }),
271
- _ts_metadata("design:type", typeof Date === "undefined" ? Object : Date)
272
- ], StepCheckpointEntity.prototype, "enqueuedAt", void 0);
273
- _ts_decorate([
274
- (0, import_typeorm.Column)(),
275
- _ts_metadata("design:type", typeof Date === "undefined" ? Object : Date)
276
- ], StepCheckpointEntity.prototype, "startedAt", void 0);
277
- _ts_decorate([
278
- (0, import_typeorm.Column)(),
279
- _ts_metadata("design:type", typeof Date === "undefined" ? Object : Date)
280
- ], StepCheckpointEntity.prototype, "finishedAt", void 0);
281
- StepCheckpointEntity = _ts_decorate([
282
- (0, import_typeorm.Entity)({
283
- name: "durable_step_checkpoints"
284
- })
285
- ], StepCheckpointEntity);
286
113
  var RunAttributeEntity = class {
287
114
  static {
288
115
  __name(this, "RunAttributeEntity");
@@ -290,34 +117,8 @@ var RunAttributeEntity = class {
290
117
  runId;
291
118
  key;
292
119
  strValue;
293
- // `float`/`double` portable across SQLite/MySQL/Postgres for numeric range scans.
294
120
  numValue;
295
121
  };
296
- _ts_decorate([
297
- (0, import_typeorm.PrimaryColumn)("text"),
298
- _ts_metadata("design:type", String)
299
- ], RunAttributeEntity.prototype, "runId", void 0);
300
- _ts_decorate([
301
- (0, import_typeorm.PrimaryColumn)("text"),
302
- _ts_metadata("design:type", String)
303
- ], RunAttributeEntity.prototype, "key", void 0);
304
- _ts_decorate([
305
- (0, import_typeorm.Column)("text", {
306
- nullable: true
307
- }),
308
- _ts_metadata("design:type", Object)
309
- ], RunAttributeEntity.prototype, "strValue", void 0);
310
- _ts_decorate([
311
- (0, import_typeorm.Column)("float", {
312
- nullable: true
313
- }),
314
- _ts_metadata("design:type", Object)
315
- ], RunAttributeEntity.prototype, "numValue", void 0);
316
- RunAttributeEntity = _ts_decorate([
317
- (0, import_typeorm.Entity)({
318
- name: "durable_run_attributes"
319
- })
320
- ], RunAttributeEntity);
321
122
  var SignalWaiterEntity = class {
322
123
  static {
323
124
  __name(this, "SignalWaiterEntity");
@@ -326,60 +127,265 @@ var SignalWaiterEntity = class {
326
127
  runId;
327
128
  seq;
328
129
  };
329
- _ts_decorate([
330
- (0, import_typeorm.PrimaryColumn)("text"),
331
- _ts_metadata("design:type", String)
332
- ], SignalWaiterEntity.prototype, "token", void 0);
333
- _ts_decorate([
334
- (0, import_typeorm.Column)("text"),
335
- _ts_metadata("design:type", String)
336
- ], SignalWaiterEntity.prototype, "runId", void 0);
337
- _ts_decorate([
338
- (0, import_typeorm.Column)("integer"),
339
- _ts_metadata("design:type", Number)
340
- ], SignalWaiterEntity.prototype, "seq", void 0);
341
- SignalWaiterEntity = _ts_decorate([
342
- (0, import_typeorm.Entity)({
343
- name: "durable_signal_waiters"
344
- })
345
- ], SignalWaiterEntity);
346
130
  var BufferedSignalEntity = class {
347
131
  static {
348
132
  __name(this, "BufferedSignalEntity");
349
133
  }
350
- // Auto-increment PK for FIFO ordering. Left as TypeORM's default increment type so it maps to the
351
- // driver-native auto-increment column (INTEGER on SQLite, BIGINT/SERIAL on MySQL/Postgres).
352
134
  id;
353
135
  token;
354
136
  payload;
355
137
  };
356
- _ts_decorate([
357
- (0, import_typeorm.PrimaryGeneratedColumn)(),
358
- _ts_metadata("design:type", Number)
359
- ], BufferedSignalEntity.prototype, "id", void 0);
360
- _ts_decorate([
361
- (0, import_typeorm.Column)("text"),
362
- _ts_metadata("design:type", String)
363
- ], BufferedSignalEntity.prototype, "token", void 0);
364
- _ts_decorate([
365
- (0, import_typeorm.Column)("text", {
366
- nullable: true,
367
- transformer: jsonColumnTransformer("buffered.payload")
368
- }),
369
- _ts_metadata("design:type", Object)
370
- ], BufferedSignalEntity.prototype, "payload", void 0);
371
- BufferedSignalEntity = _ts_decorate([
372
- (0, import_typeorm.Entity)({
373
- name: "durable_buffered_signals"
374
- })
375
- ], BufferedSignalEntity);
376
- var ENTITIES = [
377
- WorkflowRunEntity,
378
- StepCheckpointEntity,
379
- RunAttributeEntity,
380
- SignalWaiterEntity,
381
- BufferedSignalEntity
382
- ];
138
+ function durableEntities(options = {}) {
139
+ const col = columnNamer(options.naming ?? "snake_case");
140
+ const workflowRuns = new import_typeorm.EntitySchema({
141
+ name: "WorkflowRunEntity",
142
+ target: WorkflowRunEntity,
143
+ tableName: "durable_workflow_runs",
144
+ columns: {
145
+ id: {
146
+ type: "text",
147
+ primary: true,
148
+ name: col("id")
149
+ },
150
+ workflow: {
151
+ type: "text",
152
+ name: col("workflow")
153
+ },
154
+ workflowVersion: {
155
+ type: "text",
156
+ name: col("workflowVersion")
157
+ },
158
+ status: {
159
+ type: "text",
160
+ name: col("status")
161
+ },
162
+ input: {
163
+ type: "text",
164
+ nullable: true,
165
+ name: col("input"),
166
+ transformer: jsonColumnTransformer("runs.input")
167
+ },
168
+ output: {
169
+ type: "text",
170
+ nullable: true,
171
+ name: col("output"),
172
+ transformer: jsonColumnTransformer("runs.output")
173
+ },
174
+ error: {
175
+ type: "text",
176
+ nullable: true,
177
+ name: col("error"),
178
+ transformer: jsonColumnTransformer("runs.error")
179
+ },
180
+ wakeAt: {
181
+ type: Date,
182
+ nullable: true,
183
+ name: col("wakeAt")
184
+ },
185
+ lockedBy: {
186
+ type: "text",
187
+ nullable: true,
188
+ name: col("lockedBy")
189
+ },
190
+ lockedUntil: {
191
+ type: Date,
192
+ nullable: true,
193
+ name: col("lockedUntil")
194
+ },
195
+ recoveryAttempts: {
196
+ type: "integer",
197
+ nullable: true,
198
+ name: col("recoveryAttempts")
199
+ },
200
+ tags: {
201
+ type: "text",
202
+ nullable: true,
203
+ name: col("tags"),
204
+ transformer: jsonColumnTransformer("runs.tags")
205
+ },
206
+ searchAttributes: {
207
+ type: "text",
208
+ nullable: true,
209
+ name: col("searchAttributes"),
210
+ transformer: jsonColumnTransformer("runs.searchAttributes")
211
+ },
212
+ createdAt: {
213
+ type: Date,
214
+ name: col("createdAt")
215
+ },
216
+ updatedAt: {
217
+ type: Date,
218
+ name: col("updatedAt")
219
+ }
220
+ }
221
+ });
222
+ const stepCheckpoints = new import_typeorm.EntitySchema({
223
+ name: "StepCheckpointEntity",
224
+ target: StepCheckpointEntity,
225
+ tableName: "durable_step_checkpoints",
226
+ columns: {
227
+ runId: {
228
+ type: "text",
229
+ primary: true,
230
+ name: col("runId")
231
+ },
232
+ seq: {
233
+ type: "integer",
234
+ primary: true,
235
+ name: col("seq")
236
+ },
237
+ name: {
238
+ type: "text",
239
+ name: col("name")
240
+ },
241
+ kind: {
242
+ type: "text",
243
+ name: col("kind")
244
+ },
245
+ stepId: {
246
+ type: "text",
247
+ name: col("stepId")
248
+ },
249
+ status: {
250
+ type: "text",
251
+ name: col("status")
252
+ },
253
+ input: {
254
+ type: "text",
255
+ nullable: true,
256
+ name: col("input"),
257
+ transformer: jsonColumnTransformer("checkpoints.input")
258
+ },
259
+ output: {
260
+ type: "text",
261
+ nullable: true,
262
+ name: col("output"),
263
+ transformer: jsonColumnTransformer("checkpoints.output")
264
+ },
265
+ error: {
266
+ type: "text",
267
+ nullable: true,
268
+ name: col("error"),
269
+ transformer: jsonColumnTransformer("checkpoints.error")
270
+ },
271
+ events: {
272
+ type: "text",
273
+ nullable: true,
274
+ name: col("events"),
275
+ transformer: jsonColumnTransformer("checkpoints.events")
276
+ },
277
+ attempts: {
278
+ type: "integer",
279
+ name: col("attempts")
280
+ },
281
+ workerGroup: {
282
+ type: "text",
283
+ nullable: true,
284
+ name: col("workerGroup")
285
+ },
286
+ wakeAt: {
287
+ type: Date,
288
+ nullable: true,
289
+ name: col("wakeAt")
290
+ },
291
+ enqueuedAt: {
292
+ type: Date,
293
+ nullable: true,
294
+ name: col("enqueuedAt")
295
+ },
296
+ startedAt: {
297
+ type: Date,
298
+ name: col("startedAt")
299
+ },
300
+ finishedAt: {
301
+ type: Date,
302
+ name: col("finishedAt")
303
+ }
304
+ }
305
+ });
306
+ const runAttributes = new import_typeorm.EntitySchema({
307
+ name: "RunAttributeEntity",
308
+ target: RunAttributeEntity,
309
+ tableName: "durable_run_attributes",
310
+ columns: {
311
+ runId: {
312
+ type: "text",
313
+ primary: true,
314
+ name: col("runId")
315
+ },
316
+ key: {
317
+ type: "text",
318
+ primary: true,
319
+ name: col("key")
320
+ },
321
+ strValue: {
322
+ type: "text",
323
+ nullable: true,
324
+ name: col("strValue")
325
+ },
326
+ // `float`/`double` portable across SQLite/MySQL/Postgres for numeric range scans.
327
+ numValue: {
328
+ type: "float",
329
+ nullable: true,
330
+ name: col("numValue")
331
+ }
332
+ }
333
+ });
334
+ const signalWaiters = new import_typeorm.EntitySchema({
335
+ name: "SignalWaiterEntity",
336
+ target: SignalWaiterEntity,
337
+ tableName: "durable_signal_waiters",
338
+ columns: {
339
+ token: {
340
+ type: "text",
341
+ primary: true,
342
+ name: col("token")
343
+ },
344
+ runId: {
345
+ type: "text",
346
+ name: col("runId")
347
+ },
348
+ seq: {
349
+ type: "integer",
350
+ name: col("seq")
351
+ }
352
+ }
353
+ });
354
+ const bufferedSignals = new import_typeorm.EntitySchema({
355
+ name: "BufferedSignalEntity",
356
+ target: BufferedSignalEntity,
357
+ tableName: "durable_buffered_signals",
358
+ columns: {
359
+ // Auto-increment PK for FIFO ordering. Left as TypeORM's default increment generation so it
360
+ // maps to the driver-native auto-increment column (INTEGER on SQLite, BIGINT/SERIAL elsewhere).
361
+ id: {
362
+ type: Number,
363
+ primary: true,
364
+ generated: "increment",
365
+ name: col("id")
366
+ },
367
+ token: {
368
+ type: "text",
369
+ name: col("token")
370
+ },
371
+ payload: {
372
+ type: "text",
373
+ nullable: true,
374
+ name: col("payload"),
375
+ transformer: jsonColumnTransformer("buffered.payload")
376
+ }
377
+ }
378
+ });
379
+ return [
380
+ workflowRuns,
381
+ stepCheckpoints,
382
+ runAttributes,
383
+ signalWaiters,
384
+ bufferedSignals
385
+ ];
386
+ }
387
+ __name(durableEntities, "durableEntities");
388
+ var ENTITIES = durableEntities();
383
389
 
384
390
  // src/schema.ts
385
391
  var JSON_BLOB_COLUMNS = {
@@ -397,16 +403,36 @@ var JSON_BLOB_COLUMNS = {
397
403
  "events"
398
404
  ]
399
405
  };
406
+ var TABLE_TO_ENTITY = {
407
+ durable_workflow_runs: WorkflowRunEntity,
408
+ durable_step_checkpoints: StepCheckpointEntity,
409
+ durable_run_attributes: RunAttributeEntity,
410
+ durable_signal_waiters: SignalWaiterEntity,
411
+ durable_buffered_signals: BufferedSignalEntity
412
+ };
413
+ function durableColumnResolver(dataSource) {
414
+ return (table, property) => {
415
+ const entity = TABLE_TO_ENTITY[table];
416
+ if (!entity) throw new Error(`durable store: unknown table "${table}"`);
417
+ const meta = dataSource.getMetadata(entity);
418
+ const column = meta.findColumnWithPropertyName(property);
419
+ if (!column) {
420
+ throw new Error(`durable store: no column for ${table}.${property} in entity metadata`);
421
+ }
422
+ return column.databaseName;
423
+ };
424
+ }
425
+ __name(durableColumnResolver, "durableColumnResolver");
400
426
  function jsonBlobColumnType(isMysql) {
401
427
  return isMysql ? "longtext" : "text";
402
428
  }
403
429
  __name(jsonBlobColumnType, "jsonBlobColumnType");
404
- function buildWidenStatements(isMysql, quote) {
430
+ function buildWidenStatements(isMysql, quote, col) {
405
431
  if (!isMysql) return [];
406
432
  const out = [];
407
- for (const [table, cols] of Object.entries(JSON_BLOB_COLUMNS)) {
408
- for (const col of cols) {
409
- out.push(`ALTER TABLE ${quote(table)} MODIFY COLUMN ${quote(col)} longtext`);
433
+ for (const [table, props] of Object.entries(JSON_BLOB_COLUMNS)) {
434
+ for (const prop of props) {
435
+ out.push(`ALTER TABLE ${quote(table)} MODIFY COLUMN ${quote(col(table, prop))} longtext`);
410
436
  }
411
437
  }
412
438
  return out;
@@ -414,6 +440,7 @@ function buildWidenStatements(isMysql, quote) {
414
440
  __name(buildWidenStatements, "buildWidenStatements");
415
441
  async function ensureTypeOrmDurableSchema(dataSource) {
416
442
  const q = /* @__PURE__ */ __name((id) => dataSource.driver.escape(id), "q");
443
+ const resolve = durableColumnResolver(dataSource);
417
444
  const type = String(dataSource.options.type);
418
445
  const isPg = type === "postgres" || type === "aurora-postgres";
419
446
  const isMysql = type === "mysql" || type === "mariadb" || type === "aurora-mysql";
@@ -427,40 +454,45 @@ async function ensureTypeOrmDurableSchema(dataSource) {
427
454
  const runAttributes = q("durable_run_attributes");
428
455
  const waiters = q("durable_signal_waiters");
429
456
  const buffered = q("durable_buffered_signals");
457
+ const runsCol = /* @__PURE__ */ __name((property) => q(resolve("durable_workflow_runs", property)), "runsCol");
458
+ const cpCol = /* @__PURE__ */ __name((property) => q(resolve("durable_step_checkpoints", property)), "cpCol");
459
+ const attrCol = /* @__PURE__ */ __name((property) => q(resolve("durable_run_attributes", property)), "attrCol");
460
+ const waiterCol = /* @__PURE__ */ __name((property) => q(resolve("durable_signal_waiters", property)), "waiterCol");
461
+ const bufCol = /* @__PURE__ */ __name((property) => q(resolve("durable_buffered_signals", property)), "bufCol");
430
462
  const num = isPg ? "double precision" : isMysql ? "double" : "real";
431
- const bufferedId = isSqlite ? `${q("id")} integer PRIMARY KEY AUTOINCREMENT` : isMysql ? `${q("id")} bigint NOT NULL AUTO_INCREMENT PRIMARY KEY` : isPg ? `${q("id")} bigserial PRIMARY KEY` : `${q("id")} bigint NOT NULL AUTO_INCREMENT PRIMARY KEY`;
463
+ const bufferedId = isSqlite ? `${bufCol("id")} integer PRIMARY KEY AUTOINCREMENT` : isMysql ? `${bufCol("id")} bigint NOT NULL AUTO_INCREMENT PRIMARY KEY` : isPg ? `${bufCol("id")} bigserial PRIMARY KEY` : `${bufCol("id")} bigint NOT NULL AUTO_INCREMENT PRIMARY KEY`;
432
464
  const tables = [
433
465
  `CREATE TABLE IF NOT EXISTS ${runs} (
434
- ${q("id")} ${str} PRIMARY KEY,
435
- ${q("workflow")} ${str} NOT NULL,
436
- ${q("workflowVersion")} ${str} NOT NULL,
437
- ${q("status")} ${str} NOT NULL,
438
- ${q("input")} ${txt}, ${q("output")} ${txt}, ${q("error")} ${txt},
439
- ${q("wakeAt")} ${ts}, ${q("lockedBy")} ${str}, ${q("lockedUntil")} ${ts},
440
- ${q("recoveryAttempts")} ${int}, ${q("tags")} ${txt}, ${q("searchAttributes")} ${txt},
441
- ${q("createdAt")} ${ts} NOT NULL, ${q("updatedAt")} ${ts} NOT NULL
466
+ ${runsCol("id")} ${str} PRIMARY KEY,
467
+ ${runsCol("workflow")} ${str} NOT NULL,
468
+ ${runsCol("workflowVersion")} ${str} NOT NULL,
469
+ ${runsCol("status")} ${str} NOT NULL,
470
+ ${runsCol("input")} ${txt}, ${runsCol("output")} ${txt}, ${runsCol("error")} ${txt},
471
+ ${runsCol("wakeAt")} ${ts}, ${runsCol("lockedBy")} ${str}, ${runsCol("lockedUntil")} ${ts},
472
+ ${runsCol("recoveryAttempts")} ${int}, ${runsCol("tags")} ${txt}, ${runsCol("searchAttributes")} ${txt},
473
+ ${runsCol("createdAt")} ${ts} NOT NULL, ${runsCol("updatedAt")} ${ts} NOT NULL
442
474
  )`,
443
475
  `CREATE TABLE IF NOT EXISTS ${checkpoints} (
444
- ${q("runId")} ${str} NOT NULL, ${q("seq")} ${int} NOT NULL,
445
- ${q("name")} ${str} NOT NULL, ${q("kind")} ${str} NOT NULL, ${q("stepId")} ${str} NOT NULL,
446
- ${q("status")} ${str} NOT NULL, ${q("input")} ${txt}, ${q("output")} ${txt}, ${q("error")} ${txt}, ${q("events")} ${txt},
447
- ${q("attempts")} ${int} NOT NULL, ${q("workerGroup")} ${str},
448
- ${q("wakeAt")} ${ts}, ${q("enqueuedAt")} ${ts},
449
- ${q("startedAt")} ${ts} NOT NULL, ${q("finishedAt")} ${ts} NOT NULL,
450
- PRIMARY KEY (${q("runId")}, ${q("seq")})
476
+ ${cpCol("runId")} ${str} NOT NULL, ${cpCol("seq")} ${int} NOT NULL,
477
+ ${cpCol("name")} ${str} NOT NULL, ${cpCol("kind")} ${str} NOT NULL, ${cpCol("stepId")} ${str} NOT NULL,
478
+ ${cpCol("status")} ${str} NOT NULL, ${cpCol("input")} ${txt}, ${cpCol("output")} ${txt}, ${cpCol("error")} ${txt}, ${cpCol("events")} ${txt},
479
+ ${cpCol("attempts")} ${int} NOT NULL, ${cpCol("workerGroup")} ${str},
480
+ ${cpCol("wakeAt")} ${ts}, ${cpCol("enqueuedAt")} ${ts},
481
+ ${cpCol("startedAt")} ${ts} NOT NULL, ${cpCol("finishedAt")} ${ts} NOT NULL,
482
+ PRIMARY KEY (${cpCol("runId")}, ${cpCol("seq")})
451
483
  )`,
452
484
  // Normalized search-attribute side-table: one row per (run, key) so attribute predicates push
453
485
  // DOWN into SQL via an EXISTS join (indexed below). `key` is keyed → must be varchar on MySQL.
454
486
  `CREATE TABLE IF NOT EXISTS ${runAttributes} (
455
- ${q("runId")} ${str} NOT NULL, ${q("key")} ${str} NOT NULL,
456
- ${q("strValue")} ${str}, ${q("numValue")} ${num},
457
- PRIMARY KEY (${q("runId")}, ${q("key")})
487
+ ${attrCol("runId")} ${str} NOT NULL, ${attrCol("key")} ${str} NOT NULL,
488
+ ${attrCol("strValue")} ${str}, ${attrCol("numValue")} ${num},
489
+ PRIMARY KEY (${attrCol("runId")}, ${attrCol("key")})
458
490
  )`,
459
491
  `CREATE TABLE IF NOT EXISTS ${waiters} (
460
- ${q("token")} ${str} PRIMARY KEY, ${q("runId")} ${str} NOT NULL, ${q("seq")} ${int} NOT NULL
492
+ ${waiterCol("token")} ${str} PRIMARY KEY, ${waiterCol("runId")} ${str} NOT NULL, ${waiterCol("seq")} ${int} NOT NULL
461
493
  )`,
462
494
  `CREATE TABLE IF NOT EXISTS ${buffered} (
463
- ${bufferedId}, ${q("token")} ${str} NOT NULL, ${q("payload")} ${txt}
495
+ ${bufferedId}, ${bufCol("token")} ${str} NOT NULL, ${bufCol("payload")} ${txt}
464
496
  )`
465
497
  ];
466
498
  const additive = {
@@ -520,18 +552,19 @@ async function ensureTypeOrmDurableSchema(dataSource) {
520
552
  const runner = dataSource.createQueryRunner();
521
553
  try {
522
554
  for (const sql of tables) await runner.query(sql);
523
- for (const [table, cols] of Object.entries(additive)) {
555
+ for (const [table, props] of Object.entries(additive)) {
524
556
  const have = await existingColumns(runner, table, {
525
557
  isSqlite,
526
558
  isMysql
527
559
  });
528
- for (const [col, colType] of cols) {
529
- if (!have.has(col)) {
530
- await runner.query(`ALTER TABLE ${q(table)} ADD COLUMN ${q(col)} ${colType}`);
560
+ for (const [property, colType] of props) {
561
+ const column = resolve(table, property);
562
+ if (!have.has(column)) {
563
+ await runner.query(`ALTER TABLE ${q(table)} ADD COLUMN ${q(column)} ${colType}`);
531
564
  }
532
565
  }
533
566
  }
534
- for (const sql of buildWidenStatements(isMysql, q)) {
567
+ for (const sql of buildWidenStatements(isMysql, q, resolve)) {
535
568
  try {
536
569
  await runner.query(sql);
537
570
  } catch {
@@ -540,26 +573,26 @@ async function ensureTypeOrmDurableSchema(dataSource) {
540
573
  const indexes = [
541
574
  [
542
575
  "durable_runs_status_idx",
543
- `${runs} (${q("status")}, ${q("wakeAt")})`
576
+ `${runs} (${runsCol("status")}, ${runsCol("wakeAt")})`
544
577
  ],
545
578
  [
546
579
  "durable_runs_workflow_status_idx",
547
- `${runs} (${q("workflow")}, ${q("status")})`
580
+ `${runs} (${runsCol("workflow")}, ${runsCol("status")})`
548
581
  ],
549
582
  // buffered signals are taken FIFO per token (smallest id) — index the token for the scan.
550
583
  [
551
584
  "durable_buffered_signals_token_idx",
552
- `${buffered} (${q("token")})`
585
+ `${buffered} (${bufCol("token")})`
553
586
  ],
554
587
  // Search-attribute pushdown: equality + range predicates probe by (key, value). Two composite
555
588
  // indexes — one per typed column — so a numeric range or a string equality is an index scan.
556
589
  [
557
590
  "durable_run_attributes_num_idx",
558
- `${runAttributes} (${q("key")}, ${q("numValue")})`
591
+ `${runAttributes} (${attrCol("key")}, ${attrCol("numValue")})`
559
592
  ],
560
593
  [
561
594
  "durable_run_attributes_str_idx",
562
- `${runAttributes} (${q("key")}, ${q("strValue")})`
595
+ `${runAttributes} (${attrCol("key")}, ${attrCol("strValue")})`
563
596
  ]
564
597
  ];
565
598
  for (const [name, target] of indexes) {
@@ -761,13 +794,21 @@ var TypeOrmStateStore = class {
761
794
  /** Add one attribute predicate to `qb` as an EXISTS subquery on the side-table. `i` namespaces the
762
795
  * bind params so multiple ANDed filters don't collide. */
763
796
  applyAttributeExists(qb, f, i) {
764
- const col = (0, import_nestjs_durable_core.attributeColumnFor)(f);
797
+ const valueProperty = (0, import_nestjs_durable_core.attributeColumnFor)(f);
765
798
  const cmp = (0, import_nestjs_durable_core.sqlComparator)(f.op);
766
799
  const keyParam = `attrKey${i}`;
767
800
  const valParam = `attrVal${i}`;
801
+ const resolve = durableColumnResolver(this.dataSource);
802
+ const q = this.idQuote();
803
+ const wrap = /* @__PURE__ */ __name((name) => `${q}${name}${q}`, "wrap");
804
+ const runIdCol = wrap(resolve("durable_run_attributes", "runId"));
805
+ const keyCol = wrap(resolve("durable_run_attributes", "key"));
806
+ const valueCol = wrap(resolve("durable_run_attributes", valueProperty));
807
+ const runPkCol = wrap(resolve("durable_workflow_runs", "id"));
808
+ const table = wrap("durable_run_attributes");
768
809
  const a = `a${i}`;
769
- const sql = `EXISTS (SELECT 1 FROM durable_run_attributes ${a} WHERE ${a}."runId" = r.id AND ${a}."key" = :${keyParam} AND ${a}."${col}" ${cmp} :${valParam})`;
770
- qb.andWhere(sql.replace(/"/g, this.idQuote()), {
810
+ const sql = `EXISTS (SELECT 1 FROM ${table} ${a} WHERE ${a}.${runIdCol} = r.${runPkCol} AND ${a}.${keyCol} = :${keyParam} AND ${a}.${valueCol} ${cmp} :${valParam})`;
811
+ qb.andWhere(sql, {
771
812
  [keyParam]: f.key,
772
813
  [valParam]: (0, import_nestjs_durable_core.attributeOperand)(f)
773
814
  });
@@ -788,6 +829,31 @@ var TypeOrmStateStore = class {
788
829
  });
789
830
  return rows.map(fromCheckpointEntity);
790
831
  }
832
+ async getLatestCheckpointByName(runId, name) {
833
+ const e = await this.checkpoints().findOne({
834
+ where: {
835
+ runId,
836
+ name
837
+ },
838
+ order: {
839
+ seq: "DESC"
840
+ }
841
+ });
842
+ return e ? fromCheckpointEntity(e) : void 0;
843
+ }
844
+ async listCheckpointsByNamePrefix(runId, prefixes) {
845
+ if (prefixes.length === 0) return [];
846
+ const rows = await this.checkpoints().find({
847
+ where: prefixes.map((p) => ({
848
+ runId,
849
+ name: (0, import_typeorm2.Like)(`${p}%`)
850
+ })),
851
+ order: {
852
+ seq: "ASC"
853
+ }
854
+ });
855
+ return rows.map(fromCheckpointEntity);
856
+ }
791
857
  async putSignalWaiter(waiter) {
792
858
  await this.waiters().save({
793
859
  ...waiter
@@ -946,6 +1012,9 @@ __name(fromCheckpointEntity, "fromCheckpointEntity");
946
1012
  TypeOrmStateStore,
947
1013
  WorkflowRunEntity,
948
1014
  buildWidenStatements,
1015
+ columnNamer,
1016
+ durableColumnResolver,
1017
+ durableEntities,
949
1018
  ensureTypeOrmDurableSchema,
950
1019
  jsonBlobColumnType,
951
1020
  parseJsonColumn