@dudousxd/nestjs-durable-store-mikro-orm 0.11.0 → 0.12.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
@@ -351,10 +351,33 @@ var ENTITIES = durableEntities();
351
351
  var import_nestjs_durable_core = require("@dudousxd/nestjs-durable-core");
352
352
 
353
353
  // src/schema.ts
354
+ var DURABLE_TABLE_NAMES = /* @__PURE__ */ new Set([
355
+ "durable_workflow_runs",
356
+ "durable_step_checkpoints",
357
+ "durable_run_attributes",
358
+ "durable_signal_waiters",
359
+ "durable_buffered_signals"
360
+ ]);
361
+ function targetTable(statement) {
362
+ const match = statement.match(/^(?:create|alter)\s+table\s+(?:if\s+not\s+exists\s+)?[`"']?([\w$]+)[`"']?/i);
363
+ return match?.[1]?.toLowerCase();
364
+ }
365
+ __name(targetTable, "targetTable");
354
366
  async function ensureMikroOrmDurableSchema(orm) {
355
- await orm.schema.update({
367
+ const sql = await orm.schema.getUpdateSchemaSQL({
356
368
  safe: true
357
369
  });
370
+ const ours = sql.split(";").map((statement) => statement.trim()).filter((statement) => {
371
+ const table = targetTable(statement);
372
+ return table !== void 0 && DURABLE_TABLE_NAMES.has(table);
373
+ });
374
+ if (ours.length === 0) {
375
+ return;
376
+ }
377
+ const connection = orm.em.getConnection();
378
+ for (const statement of ours) {
379
+ await connection.execute(statement);
380
+ }
358
381
  }
359
382
  __name(ensureMikroOrmDurableSchema, "ensureMikroOrmDurableSchema");
360
383
 
@@ -405,6 +428,21 @@ var MikroOrmStateStore = class {
405
428
  });
406
429
  return entity ? fromRunEntity(entity) : null;
407
430
  }
431
+ async deleteRun(runId) {
432
+ const em = this.orm.em.fork();
433
+ await em.nativeDelete(StepCheckpointEntity, {
434
+ runId
435
+ });
436
+ await em.nativeDelete(SignalWaiterEntity, {
437
+ runId
438
+ });
439
+ await em.nativeDelete(RunAttributeEntity, {
440
+ runId
441
+ });
442
+ await em.nativeDelete(WorkflowRunEntity, {
443
+ id: runId
444
+ });
445
+ }
408
446
  async getCheckpoint(runId, seq) {
409
447
  const em = this.orm.em.fork();
410
448
  const entity = await em.findOne(StepCheckpointEntity, {
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/entities.ts","../src/mikro-orm-state-store.ts","../src/schema.ts"],"sourcesContent":["export * from './entities';\nexport * from './mikro-orm-state-store';\nexport * from './schema';\n","import type { RunStatus, StepKind } from '@dudousxd/nestjs-durable-core';\nimport { EntitySchema } from '@mikro-orm/core';\n\n/**\n * How property names map to physical column names. The durable tables are adapter-agnostic: a run\n * written by one store adapter must be readable by another, so every adapter has to agree on the\n * physical column names. The default is `'snake_case'` (the canonical, matched by the TypeORM,\n * Prisma and Drizzle adapters). `'preserve'` keeps the camelCase property name verbatim (what the\n * old TypeORM/Prisma adapters produced before they were pinned). A function lets you supply any\n * custom mapping.\n *\n * The choice is pinned EXPLICITLY onto the entity schema rather than left to the host ORM's naming\n * strategy — depending on the host strategy is what silently diverged the adapters and broke a store\n * swap against an existing table.\n */\nexport type DurableColumnNaming = 'snake_case' | 'preserve' | ((property: string) => string);\n\nfunction snakeCase(property: string): string {\n return property.replace(/[A-Z]/g, (c) => `_${c.toLowerCase()}`);\n}\n\nfunction columnNamer(naming: DurableColumnNaming): (property: string) => string {\n if (naming === 'snake_case') return snakeCase;\n if (naming === 'preserve') return (property) => property;\n return naming;\n}\n\n// Plain classes (no decorators): the schema/column mapping lives on the EntitySchema built by\n// `durableEntities`, so the same class can be registered under different column names. The store\n// still references these classes for `em.create`/`getMetadata`.\n\nexport class WorkflowRunEntity {\n id!: string;\n workflow!: string;\n workflowVersion!: string;\n status!: RunStatus;\n input?: unknown;\n output?: unknown;\n error?: unknown;\n wakeAt?: Date;\n lockedBy?: string;\n lockedUntil?: Date;\n recoveryAttempts?: number;\n tags?: string[] | null;\n searchAttributes?: Record<string, string | number | boolean> | null;\n createdAt!: Date;\n updatedAt!: Date;\n}\n\nexport class StepCheckpointEntity {\n runId!: string;\n seq!: number;\n name!: string;\n kind!: StepKind;\n stepId!: string;\n status!: 'pending' | 'running' | 'completed' | 'failed';\n input?: unknown;\n output?: unknown;\n error?: unknown;\n events?: unknown;\n attempts!: number;\n workerGroup?: string;\n wakeAt?: Date;\n enqueuedAt?: Date;\n startedAt!: Date;\n finishedAt!: Date;\n}\n\n/**\n * Normalized side-table for search attributes: one row per (run, key), so range/equality predicates\n * push DOWN into SQL (an EXISTS join indexed on `(key, numValue)` / `(key, strValue)`) instead of a\n * coarse scan + in-process filter. Maintained on every createRun/updateRun. Numbers land in\n * `numValue`, strings/booleans in `strValue` (booleans as \"true\"/\"false\"); see normalizeAttributeRows.\n */\nexport class RunAttributeEntity {\n runId!: string;\n key!: string;\n strValue?: string | null;\n numValue?: number | null;\n}\n\nexport class SignalWaiterEntity {\n token!: string;\n runId!: string;\n seq!: number;\n}\n\nexport class BufferedSignalEntity {\n id!: number;\n token!: string;\n payload?: unknown;\n}\n\n/**\n * Build the durable MikroORM entity schemas with column names pinned per `naming` (default\n * `'snake_case'`). Register the result in your MikroORM config / `MikroOrmModule.forFeature`.\n *\n * ```ts\n * entities: durableEntities({ naming: 'snake_case' })\n * ```\n */\nexport function durableEntities(options: { naming?: DurableColumnNaming } = {}): EntitySchema[] {\n const col = columnNamer(options.naming ?? 'snake_case');\n\n const workflowRuns = new EntitySchema<WorkflowRunEntity>({\n class: WorkflowRunEntity,\n tableName: 'durable_workflow_runs',\n properties: {\n id: { type: 'string', primary: true, fieldName: col('id') },\n workflow: { type: 'string', fieldName: col('workflow') },\n workflowVersion: { type: 'string', fieldName: col('workflowVersion') },\n status: { type: 'string', fieldName: col('status') },\n input: { type: 'json', nullable: true, fieldName: col('input') },\n output: { type: 'json', nullable: true, fieldName: col('output') },\n error: { type: 'json', nullable: true, fieldName: col('error') },\n wakeAt: { type: 'Date', nullable: true, fieldName: col('wakeAt') },\n lockedBy: { type: 'string', nullable: true, fieldName: col('lockedBy') },\n lockedUntil: { type: 'Date', nullable: true, fieldName: col('lockedUntil') },\n recoveryAttempts: { type: 'integer', nullable: true, fieldName: col('recoveryAttempts') },\n tags: { type: 'json', nullable: true, fieldName: col('tags') },\n searchAttributes: { type: 'json', nullable: true, fieldName: col('searchAttributes') },\n createdAt: { type: 'Date', fieldName: col('createdAt') },\n updatedAt: { type: 'Date', fieldName: col('updatedAt') },\n },\n });\n\n const stepCheckpoints = new EntitySchema<StepCheckpointEntity>({\n class: StepCheckpointEntity,\n tableName: 'durable_step_checkpoints',\n properties: {\n runId: { type: 'string', primary: true, fieldName: col('runId') },\n seq: { type: 'integer', primary: true, fieldName: col('seq') },\n name: { type: 'string', fieldName: col('name') },\n kind: { type: 'string', fieldName: col('kind') },\n stepId: { type: 'string', fieldName: col('stepId') },\n status: { type: 'string', fieldName: col('status') },\n input: { type: 'json', nullable: true, fieldName: col('input') },\n output: { type: 'json', nullable: true, fieldName: col('output') },\n error: { type: 'json', nullable: true, fieldName: col('error') },\n events: { type: 'json', nullable: true, fieldName: col('events') },\n attempts: { type: 'integer', fieldName: col('attempts') },\n workerGroup: { type: 'string', nullable: true, fieldName: col('workerGroup') },\n wakeAt: { type: 'Date', nullable: true, fieldName: col('wakeAt') },\n enqueuedAt: { type: 'Date', nullable: true, fieldName: col('enqueuedAt') },\n startedAt: { type: 'Date', fieldName: col('startedAt') },\n finishedAt: { type: 'Date', fieldName: col('finishedAt') },\n },\n });\n\n const runAttributes = new EntitySchema<RunAttributeEntity>({\n class: RunAttributeEntity,\n tableName: 'durable_run_attributes',\n properties: {\n runId: { type: 'string', primary: true, fieldName: col('runId') },\n key: { type: 'string', primary: true, fieldName: col('key') },\n strValue: { type: 'string', nullable: true, fieldName: col('strValue') },\n // `float`/`double` is portable across SQLite/MySQL/Postgres for numeric range scans.\n numValue: { type: 'float', nullable: true, fieldName: col('numValue') },\n },\n });\n\n const signalWaiters = new EntitySchema<SignalWaiterEntity>({\n class: SignalWaiterEntity,\n tableName: 'durable_signal_waiters',\n properties: {\n token: { type: 'string', primary: true, fieldName: col('token') },\n runId: { type: 'string', fieldName: col('runId') },\n seq: { type: 'integer', fieldName: col('seq') },\n },\n });\n\n const bufferedSignals = new EntitySchema<BufferedSignalEntity>({\n class: BufferedSignalEntity,\n tableName: 'durable_buffered_signals',\n properties: {\n id: { type: 'integer', primary: true, autoincrement: true, fieldName: col('id') },\n token: { type: 'string', index: true, fieldName: col('token') },\n payload: { type: 'json', nullable: true, fieldName: col('payload') },\n },\n });\n\n return [workflowRuns, stepCheckpoints, runAttributes, signalWaiters, bufferedSignals];\n}\n\n/** Durable entity schemas with the canonical `'snake_case'` column names. */\nexport const ENTITIES = durableEntities();\n","import {\n type AttributeFilter,\n type RunQuery,\n type SignalWaiter,\n type StateStore,\n type StepCheckpoint,\n type StepError,\n type StepEvent,\n type WorkflowRun,\n attributeColumnFor,\n attributeOperand,\n normalizeAttributeRows,\n sqlComparator,\n} from '@dudousxd/nestjs-durable-core';\nimport type { EntityManager, MikroORM } from '@mikro-orm/core';\n\n/** Minimal structural surface of the SQL EntityManager's QueryBuilder (from `@mikro-orm/knex`),\n * typed here so the adapter needn't add a hard dependency on the knex types — a real SQL-driver EM\n * satisfies it at runtime. */\ninterface DurableQueryBuilder<T> {\n where(cond: Record<string, unknown>): DurableQueryBuilder<T>;\n andWhere(cond: string): DurableQueryBuilder<T>;\n orderBy(cond: Record<string, unknown>): DurableQueryBuilder<T>;\n limit(n: number): DurableQueryBuilder<T>;\n offset(n: number): DurableQueryBuilder<T>;\n getResultList(): Promise<T[]>;\n}\ntype SqlEm = EntityManager & {\n createQueryBuilder<T>(entity: unknown, alias: string): DurableQueryBuilder<T>;\n};\n\n/** Resolved side-table column names (per the active naming strategy) for the raw EXISTS pushdown. */\ninterface AttributeColumns {\n table: string;\n /** Side-table FK column (the run id on `durable_run_attributes`). */\n runId: string;\n /** Run table PK column (the `id` on `durable_workflow_runs`) used for the outer correlation. */\n runPk: string;\n key: string;\n strValue: string;\n numValue: string;\n}\nimport {\n BufferedSignalEntity,\n RunAttributeEntity,\n SignalWaiterEntity,\n StepCheckpointEntity,\n WorkflowRunEntity,\n} from './entities';\nimport { ensureMikroOrmDurableSchema } from './schema';\n\n/**\n * MikroORM-backed `StateStore`. Works on any MikroORM driver — Postgres, MySQL, SQLite (tested);\n * timestamps and `wakeAt` use native datetime columns. Each operation runs on a forked\n * EntityManager so it owns its unit of work.\n */\nexport class MikroOrmStateStore implements StateStore {\n constructor(private readonly orm: MikroORM) {}\n\n async ensureSchema(): Promise<void> {\n await ensureMikroOrmDurableSchema(this.orm);\n }\n\n async createRun(run: WorkflowRun): Promise<void> {\n const em = this.orm.em.fork();\n em.create(WorkflowRunEntity, toRunEntity(run));\n await em.flush();\n await this.reindexAttributes(run.id, run.searchAttributes);\n }\n\n async updateRun(runId: string, patch: Partial<WorkflowRun>): Promise<void> {\n const em = this.orm.em.fork();\n const entity = await em.findOneOrFail(WorkflowRunEntity, { id: runId });\n Object.assign(entity, toRunEntity({ ...fromRunEntity(entity), ...patch } as WorkflowRun));\n await em.flush();\n // Keep the side-table in step with the run's attributes whenever they're patched.\n if ('searchAttributes' in patch) await this.reindexAttributes(runId, patch.searchAttributes);\n }\n\n /** Rewrite a run's normalized attribute rows: delete the old set, insert the current one. Mirrors\n * the in-memory store's reindex so the side-table always reflects the run's live searchAttributes. */\n private async reindexAttributes(\n runId: string,\n attributes: WorkflowRun['searchAttributes'],\n forked?: EntityManager,\n ): Promise<void> {\n const em = forked ?? this.orm.em.fork();\n await em.nativeDelete(RunAttributeEntity, { runId });\n const rows = normalizeAttributeRows(runId, attributes);\n if (rows.length) await em.insertMany(RunAttributeEntity, rows);\n }\n\n async getRun(runId: string): Promise<WorkflowRun | null> {\n const em = this.orm.em.fork();\n const entity = await em.findOne(WorkflowRunEntity, { id: runId });\n return entity ? fromRunEntity(entity) : null;\n }\n\n async getCheckpoint(runId: string, seq: number): Promise<StepCheckpoint | null> {\n const em = this.orm.em.fork();\n const entity = await em.findOne(StepCheckpointEntity, { runId, seq });\n return entity ? fromCheckpointEntity(entity) : null;\n }\n\n async saveCheckpoint(checkpoint: StepCheckpoint): Promise<void> {\n const em = this.orm.em.fork();\n await em.upsert(StepCheckpointEntity, toCheckpointEntity(checkpoint));\n await em.flush();\n }\n\n async transaction<T>(\n work: (tx: {\n raw: unknown;\n saveCheckpoint: (cp: StepCheckpoint) => Promise<void>;\n }) => Promise<T>,\n ): Promise<T> {\n return this.orm.em.fork().transactional(async (em) =>\n work({\n raw: em,\n saveCheckpoint: async (cp) => {\n await em.upsert(StepCheckpointEntity, toCheckpointEntity(cp));\n },\n }),\n );\n }\n\n async listIncompleteRuns(): Promise<WorkflowRun[]> {\n const em = this.orm.em.fork();\n const rows = await em.find(WorkflowRunEntity, { status: 'running' });\n return rows.map(fromRunEntity);\n }\n\n async listPendingRuns(limit: number): Promise<WorkflowRun[]> {\n const em = this.orm.em.fork();\n const rows = await em.find(\n WorkflowRunEntity,\n { status: 'pending' },\n { orderBy: { createdAt: 'asc' }, limit }, // FIFO dispatch\n );\n return rows.map(fromRunEntity);\n }\n\n async listDueTimers(nowMs: number): Promise<WorkflowRun[]> {\n const em = this.orm.em.fork();\n const rows = await em.find(WorkflowRunEntity, {\n status: 'suspended',\n wakeAt: { $ne: null, $lte: new Date(nowMs) },\n });\n return rows.map(fromRunEntity);\n }\n\n async tryLockRun(\n runId: string,\n owner: string,\n leaseUntilMs: number,\n nowMs: number,\n ): Promise<boolean> {\n const em = this.orm.em.fork();\n const affected = await em.nativeUpdate(\n WorkflowRunEntity,\n { id: runId, $or: [{ lockedUntil: null }, { lockedUntil: { $lte: new Date(nowMs) } }] },\n { lockedBy: owner, lockedUntil: new Date(leaseUntilMs) },\n );\n return affected === 1;\n }\n\n async releaseRunLock(runId: string): Promise<void> {\n const em = this.orm.em.fork();\n await em.nativeUpdate(WorkflowRunEntity, { id: runId }, { lockedBy: null, lockedUntil: null });\n }\n\n async renewRunLock(runId: string, owner: string, leaseUntilMs: number): Promise<boolean> {\n const em = this.orm.em.fork();\n const affected = await em.nativeUpdate(\n WorkflowRunEntity,\n { id: runId, lockedBy: owner },\n { lockedUntil: new Date(leaseUntilMs) },\n );\n return affected === 1;\n }\n\n async listRuns(query: RunQuery): Promise<WorkflowRun[]> {\n const em = this.orm.em.fork();\n const where: Record<string, unknown> = {};\n if (query.workflow) where.workflow = query.workflow;\n // `status IN (...)`; an empty set matches nothing (mirrors the in-memory store). When both the\n // single `status` and `statuses` are set, AND them so the narrower set wins.\n if (query.status && query.statuses) {\n where.$and = [{ status: query.status }, { status: { $in: query.statuses } }];\n } else if (query.status) {\n where.status = query.status;\n } else if (query.statuses) {\n where.status = { $in: query.statuses };\n }\n const orderBy = { createdAt: 'desc' as const }; // newest first — recent runs on top in the dashboard\n // `tags`/attributes need raw SQL pushed through the QueryBuilder:\n // - tag: `tags` is a JSON column (native json/jsonb on PG/MySQL), and MikroORM JSON-serializes a\n // `{ $like }` operand (wrapping/escaping the LIKE pattern) so a plain where corrupts it to no\n // matches. A raw LIKE on the column-as-text matches the quoted token so `etl` doesn't match\n // `etl-foo`. Postgres `jsonb` rejects `LIKE` directly, so cast to text per dialect.\n // - attributes: each filter becomes a raw EXISTS against the normalized side-table, so the DB\n // filters AND paginates — no full scan + in-process filter (ANDed: one EXISTS per filter).\n // Use a QueryBuilder with a fixed root alias `r` so the raw correlations are stable across drivers.\n if (query.tag || query.attributes?.length) {\n const quote = this.idQuote(em);\n const cols = this.attributeColumns(em);\n const qb = (em as SqlEm)\n .createQueryBuilder<WorkflowRunEntity>(WorkflowRunEntity, 'r')\n .where(where)\n .orderBy(orderBy);\n if (query.tag) {\n const tagsCol = this.tagsColumn(em);\n const pattern = `%\"${query.tag.replace(/'/g, \"''\")}\"%`;\n const colExpr = this.jsonAsText(em, `${quote('r')}.${quote(tagsCol)}`);\n qb.andWhere(`${colExpr} LIKE '${pattern}'`);\n }\n for (const f of query.attributes ?? []) {\n qb.andWhere(this.attributeExistsSql(f, quote, 'r', cols));\n }\n if (query.limit != null) qb.limit(query.limit);\n if (query.offset != null) qb.offset(query.offset);\n const rows = await qb.getResultList();\n return rows.map(fromRunEntity);\n }\n const rows = await em.find(WorkflowRunEntity, where, {\n ...(query.limit != null ? { limit: query.limit } : {}),\n ...(query.offset != null ? { offset: query.offset } : {}),\n orderBy,\n });\n return rows.map(fromRunEntity);\n }\n\n /** One attribute predicate as a raw EXISTS subquery on the side-table, correlated to the outer run\n * alias. `<>` (ne) also excludes runs where the attribute is absent (missing-key-never-matches):\n * EXISTS already requires a present row, so EXISTS(... <> ...) is exactly ne-with-present. Numeric\n * operands compare the num column, everything else the str column. Identifiers are quoted per\n * driver and operands are inlined as literals (string operands are escaped by doubling quotes). */\n private attributeExistsSql(\n f: AttributeFilter,\n quote: (id: string) => string,\n alias: string,\n cols: AttributeColumns,\n ): string {\n const col = attributeColumnFor(f) === 'numValue' ? cols.numValue : cols.strValue;\n const cmp = sqlComparator(f.op);\n const operand = attributeOperand(f);\n const literal =\n typeof operand === 'number' ? String(operand) : `'${String(operand).replace(/'/g, \"''\")}'`;\n const a = quote(cols.table);\n const sub = quote('a');\n const outerId = `${quote(alias)}.${quote(cols.runPk)}`; // run PK column on the outer alias\n return `EXISTS (SELECT 1 FROM ${a} ${sub} WHERE ${sub}.${quote(cols.runId)} = ${outerId} AND ${sub}.${quote(cols.key)} = '${f.key.replace(/'/g, \"''\")}' AND ${sub}.${quote(col)} ${cmp} ${literal})`;\n }\n\n /** Resolve the side-table's actual column names from MikroORM metadata, so the raw EXISTS matches\n * the active naming strategy (underscore vs camelCase) rather than guessing. The run PK column is\n * reused for BOTH the outer correlation and the side-table FK (they share the same fieldName). */\n private attributeColumns(em: EntityManager): AttributeColumns {\n const meta = em.getMetadata().get(RunAttributeEntity);\n const field = (prop: string) =>\n meta.props.find((p) => p.name === prop)?.fieldNames?.[0] ?? prop;\n const runMeta = em.getMetadata().get(WorkflowRunEntity);\n const runPk = runMeta.properties.id?.fieldNames?.[0] ?? 'id';\n return {\n table: meta.tableName,\n runId: field('runId'),\n runPk,\n key: field('key'),\n strValue: field('strValue'),\n numValue: field('numValue'),\n };\n }\n\n /** Resolve the `tags` column name from metadata (per the active naming strategy), for the raw LIKE. */\n private tagsColumn(em: EntityManager): string {\n const runMeta = em.getMetadata().get(WorkflowRunEntity);\n return runMeta.properties.tags?.fieldNames?.[0] ?? 'tags';\n }\n\n /** Wrap a JSON column reference so it can be `LIKE`d as text. Postgres `jsonb`/`json` rejects `LIKE`\n * directly (`operator does not exist: jsonb ~~ unknown`) — cast to `text`; MySQL JSON needs an\n * explicit `CHAR` cast; SQLite stores JSON as text already, so no cast. */\n private jsonAsText(em: EntityManager, colRef: string): string {\n const platform = String(em.getPlatform().constructor.name).toLowerCase();\n if (platform.includes('postgre')) return `${colRef}::text`;\n if (platform.includes('mysql') || platform.includes('mariadb'))\n return `CAST(${colRef} AS CHAR)`;\n return colRef;\n }\n\n /** Quote an identifier per the active SQL driver (MySQL/MariaDB backtick, others double-quote). */\n private idQuote(em: EntityManager): (id: string) => string {\n const platform = String(em.getPlatform().constructor.name).toLowerCase();\n const isMysql = platform.includes('mysql') || platform.includes('mariadb');\n const ch = isMysql ? '`' : '\"';\n return (id: string) => `${ch}${id}${ch}`;\n }\n\n async listCheckpoints(runId: string): Promise<StepCheckpoint[]> {\n const em = this.orm.em.fork();\n const rows = await em.find(StepCheckpointEntity, { runId }, { orderBy: { seq: 'asc' } });\n return rows.map(fromCheckpointEntity);\n }\n\n async getLatestCheckpointByName(\n runId: string,\n name: string,\n ): Promise<StepCheckpoint | undefined> {\n const em = this.orm.em.fork();\n const entity = await em.findOne(\n StepCheckpointEntity,\n { runId, name },\n { orderBy: { seq: 'desc' } },\n );\n return entity ? fromCheckpointEntity(entity) : undefined;\n }\n\n async listCheckpointsByNamePrefix(runId: string, prefixes: string[]): Promise<StepCheckpoint[]> {\n if (prefixes.length === 0) return [];\n const em = this.orm.em.fork();\n const rows = await em.find(\n StepCheckpointEntity,\n { runId, $or: prefixes.map((p) => ({ name: { $like: `${p}%` } })) },\n { orderBy: { seq: 'asc' } },\n );\n return rows.map(fromCheckpointEntity);\n }\n\n async putSignalWaiter(waiter: SignalWaiter): Promise<void> {\n const em = this.orm.em.fork();\n await em.upsert(SignalWaiterEntity, { ...waiter });\n await em.flush();\n }\n\n async takeSignalWaiter(token: string): Promise<SignalWaiter | null> {\n const em = this.orm.em.fork();\n const entity = await em.findOne(SignalWaiterEntity, { token });\n if (!entity) return null;\n const waiter: SignalWaiter = { token: entity.token, runId: entity.runId, seq: entity.seq };\n await em.remove(entity).flush();\n return waiter;\n }\n\n async listSignalWaiters(prefix: string): Promise<SignalWaiter[]> {\n const em = this.orm.em.fork();\n const rows = await em.find(SignalWaiterEntity, { token: { $like: `${prefix}%` } });\n return rows.map((e) => ({ token: e.token, runId: e.runId, seq: e.seq }));\n }\n\n async bufferSignal(token: string, payload: unknown): Promise<void> {\n const em = this.orm.em.fork();\n const e = new BufferedSignalEntity();\n e.token = token;\n e.payload = payload ?? null;\n em.persist(e);\n await em.flush();\n }\n\n async takeBufferedSignal(token: string): Promise<{ payload: unknown } | null> {\n const em = this.orm.em.fork();\n const entity = await em.findOne(BufferedSignalEntity, { token }, { orderBy: { id: 'asc' } });\n if (!entity) return null;\n const payload = entity.payload ?? undefined;\n await em.remove(entity).flush();\n return { payload };\n }\n}\n\nfunction toRunEntity(run: WorkflowRun): WorkflowRunEntity {\n const e = new WorkflowRunEntity();\n e.id = run.id;\n e.workflow = run.workflow;\n e.workflowVersion = run.workflowVersion;\n e.status = run.status;\n e.input = run.input ?? null;\n e.output = run.output ?? null;\n e.error = run.error ?? null;\n if (run.wakeAt != null) e.wakeAt = new Date(run.wakeAt);\n if (run.lockedBy !== undefined) e.lockedBy = run.lockedBy;\n if (run.lockedUntil != null) e.lockedUntil = new Date(run.lockedUntil);\n if (run.recoveryAttempts !== undefined) e.recoveryAttempts = run.recoveryAttempts;\n e.tags = run.tags ?? null;\n e.searchAttributes = run.searchAttributes ?? null;\n e.createdAt = run.createdAt;\n e.updatedAt = run.updatedAt;\n return e;\n}\n\nfunction fromRunEntity(e: WorkflowRunEntity): WorkflowRun {\n return {\n id: e.id,\n workflow: e.workflow,\n workflowVersion: e.workflowVersion,\n status: e.status,\n input: e.input ?? undefined,\n output: e.output ?? undefined,\n error: (e.error ?? undefined) as StepError | undefined,\n wakeAt: e.wakeAt?.getTime(),\n lockedBy: e.lockedBy ?? undefined,\n lockedUntil: e.lockedUntil?.getTime(),\n recoveryAttempts: e.recoveryAttempts ?? undefined,\n tags: e.tags ?? undefined,\n searchAttributes: e.searchAttributes ?? undefined,\n createdAt: e.createdAt,\n updatedAt: e.updatedAt,\n };\n}\n\nfunction toCheckpointEntity(cp: StepCheckpoint): StepCheckpointEntity {\n const e = new StepCheckpointEntity();\n e.runId = cp.runId;\n e.seq = cp.seq;\n e.name = cp.name;\n e.kind = cp.kind;\n e.stepId = cp.stepId;\n e.status = cp.status;\n e.input = cp.input ?? null;\n e.output = cp.output ?? null;\n e.error = cp.error ?? null;\n e.events = cp.events ?? null;\n e.attempts = cp.attempts;\n if (cp.workerGroup !== undefined) e.workerGroup = cp.workerGroup;\n if (cp.wakeAt != null) e.wakeAt = new Date(cp.wakeAt);\n e.enqueuedAt = cp.enqueuedAt;\n e.startedAt = cp.startedAt;\n e.finishedAt = cp.finishedAt;\n return e;\n}\n\nfunction fromCheckpointEntity(e: StepCheckpointEntity): StepCheckpoint {\n return {\n runId: e.runId,\n seq: e.seq,\n name: e.name,\n kind: e.kind,\n stepId: e.stepId,\n status: e.status,\n input: e.input ?? undefined,\n output: e.output ?? undefined,\n error: (e.error ?? undefined) as StepError | undefined,\n events: (e.events ?? undefined) as StepEvent[] | undefined,\n attempts: e.attempts,\n workerGroup: e.workerGroup ?? undefined,\n wakeAt: e.wakeAt?.getTime(),\n enqueuedAt: e.enqueuedAt ?? e.startedAt,\n startedAt: e.startedAt,\n finishedAt: e.finishedAt,\n };\n}\n","import type { MikroORM } from '@mikro-orm/core';\n\n/**\n * Idempotently create/extend the durable tables (additive, never drops). Safe to run on every\n * boot (auto-schema) and the function to call from a MikroORM migration when you disable\n * auto-schema:\n *\n * ```ts\n * export class AddDurableTables extends Migration {\n * async up() { await ensureMikroOrmDurableSchema(this.getEntityManager().getOrm()); }\n * }\n * ```\n */\nexport async function ensureMikroOrmDurableSchema(orm: MikroORM): Promise<void> {\n await orm.schema.update({ safe: true });\n}\n"],"mappings":"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","names":["snakeCase","property","replace","c","toLowerCase","columnNamer","naming","WorkflowRunEntity","id","workflow","workflowVersion","status","input","output","error","wakeAt","lockedBy","lockedUntil","recoveryAttempts","tags","searchAttributes","createdAt","updatedAt","StepCheckpointEntity","runId","seq","name","kind","stepId","events","attempts","workerGroup","enqueuedAt","startedAt","finishedAt","RunAttributeEntity","key","strValue","numValue","SignalWaiterEntity","token","BufferedSignalEntity","payload","durableEntities","options","col","workflowRuns","EntitySchema","class","tableName","properties","type","primary","fieldName","nullable","stepCheckpoints","runAttributes","signalWaiters","bufferedSignals","autoincrement","index","ENTITIES","ensureMikroOrmDurableSchema","orm","schema","update","safe","MikroOrmStateStore","orm","ensureSchema","ensureMikroOrmDurableSchema","createRun","run","em","fork","create","WorkflowRunEntity","toRunEntity","flush","reindexAttributes","id","searchAttributes","updateRun","runId","patch","entity","findOneOrFail","Object","assign","fromRunEntity","attributes","forked","nativeDelete","RunAttributeEntity","rows","normalizeAttributeRows","length","insertMany","getRun","findOne","getCheckpoint","seq","StepCheckpointEntity","fromCheckpointEntity","saveCheckpoint","checkpoint","upsert","toCheckpointEntity","transaction","work","transactional","raw","cp","listIncompleteRuns","find","status","map","listPendingRuns","limit","orderBy","createdAt","listDueTimers","nowMs","wakeAt","$ne","$lte","Date","tryLockRun","owner","leaseUntilMs","affected","nativeUpdate","$or","lockedUntil","lockedBy","releaseRunLock","renewRunLock","listRuns","query","where","workflow","statuses","$and","$in","tag","quote","idQuote","cols","attributeColumns","qb","createQueryBuilder","tagsCol","tagsColumn","pattern","replace","colExpr","jsonAsText","andWhere","f","attributeExistsSql","offset","getResultList","alias","col","attributeColumnFor","numValue","strValue","cmp","sqlComparator","op","operand","attributeOperand","literal","String","a","table","sub","outerId","runPk","key","meta","getMetadata","get","field","prop","props","p","name","fieldNames","runMeta","properties","tableName","tags","colRef","platform","getPlatform","toLowerCase","includes","isMysql","ch","listCheckpoints","getLatestCheckpointByName","undefined","listCheckpointsByNamePrefix","prefixes","$like","putSignalWaiter","waiter","SignalWaiterEntity","takeSignalWaiter","token","remove","listSignalWaiters","prefix","e","bufferSignal","payload","BufferedSignalEntity","persist","takeBufferedSignal","workflowVersion","input","output","error","recoveryAttempts","updatedAt","getTime","kind","stepId","events","attempts","workerGroup","enqueuedAt","startedAt","finishedAt"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/entities.ts","../src/mikro-orm-state-store.ts","../src/schema.ts"],"sourcesContent":["export * from './entities';\nexport * from './mikro-orm-state-store';\nexport * from './schema';\n","import type { RunStatus, StepKind } from '@dudousxd/nestjs-durable-core';\nimport { EntitySchema } from '@mikro-orm/core';\n\n/**\n * How property names map to physical column names. The durable tables are adapter-agnostic: a run\n * written by one store adapter must be readable by another, so every adapter has to agree on the\n * physical column names. The default is `'snake_case'` (the canonical, matched by the TypeORM,\n * Prisma and Drizzle adapters). `'preserve'` keeps the camelCase property name verbatim (what the\n * old TypeORM/Prisma adapters produced before they were pinned). A function lets you supply any\n * custom mapping.\n *\n * The choice is pinned EXPLICITLY onto the entity schema rather than left to the host ORM's naming\n * strategy — depending on the host strategy is what silently diverged the adapters and broke a store\n * swap against an existing table.\n */\nexport type DurableColumnNaming = 'snake_case' | 'preserve' | ((property: string) => string);\n\nfunction snakeCase(property: string): string {\n return property.replace(/[A-Z]/g, (c) => `_${c.toLowerCase()}`);\n}\n\nfunction columnNamer(naming: DurableColumnNaming): (property: string) => string {\n if (naming === 'snake_case') return snakeCase;\n if (naming === 'preserve') return (property) => property;\n return naming;\n}\n\n// Plain classes (no decorators): the schema/column mapping lives on the EntitySchema built by\n// `durableEntities`, so the same class can be registered under different column names. The store\n// still references these classes for `em.create`/`getMetadata`.\n\nexport class WorkflowRunEntity {\n id!: string;\n workflow!: string;\n workflowVersion!: string;\n status!: RunStatus;\n input?: unknown;\n output?: unknown;\n error?: unknown;\n wakeAt?: Date;\n lockedBy?: string;\n lockedUntil?: Date;\n recoveryAttempts?: number;\n tags?: string[] | null;\n searchAttributes?: Record<string, string | number | boolean> | null;\n createdAt!: Date;\n updatedAt!: Date;\n}\n\nexport class StepCheckpointEntity {\n runId!: string;\n seq!: number;\n name!: string;\n kind!: StepKind;\n stepId!: string;\n status!: 'pending' | 'running' | 'completed' | 'failed';\n input?: unknown;\n output?: unknown;\n error?: unknown;\n events?: unknown;\n attempts!: number;\n workerGroup?: string;\n wakeAt?: Date;\n enqueuedAt?: Date;\n startedAt!: Date;\n finishedAt!: Date;\n}\n\n/**\n * Normalized side-table for search attributes: one row per (run, key), so range/equality predicates\n * push DOWN into SQL (an EXISTS join indexed on `(key, numValue)` / `(key, strValue)`) instead of a\n * coarse scan + in-process filter. Maintained on every createRun/updateRun. Numbers land in\n * `numValue`, strings/booleans in `strValue` (booleans as \"true\"/\"false\"); see normalizeAttributeRows.\n */\nexport class RunAttributeEntity {\n runId!: string;\n key!: string;\n strValue?: string | null;\n numValue?: number | null;\n}\n\nexport class SignalWaiterEntity {\n token!: string;\n runId!: string;\n seq!: number;\n}\n\nexport class BufferedSignalEntity {\n id!: number;\n token!: string;\n payload?: unknown;\n}\n\n/**\n * Build the durable MikroORM entity schemas with column names pinned per `naming` (default\n * `'snake_case'`). Register the result in your MikroORM config / `MikroOrmModule.forFeature`.\n *\n * ```ts\n * entities: durableEntities({ naming: 'snake_case' })\n * ```\n */\nexport function durableEntities(options: { naming?: DurableColumnNaming } = {}): EntitySchema[] {\n const col = columnNamer(options.naming ?? 'snake_case');\n\n const workflowRuns = new EntitySchema<WorkflowRunEntity>({\n class: WorkflowRunEntity,\n tableName: 'durable_workflow_runs',\n properties: {\n id: { type: 'string', primary: true, fieldName: col('id') },\n workflow: { type: 'string', fieldName: col('workflow') },\n workflowVersion: { type: 'string', fieldName: col('workflowVersion') },\n status: { type: 'string', fieldName: col('status') },\n input: { type: 'json', nullable: true, fieldName: col('input') },\n output: { type: 'json', nullable: true, fieldName: col('output') },\n error: { type: 'json', nullable: true, fieldName: col('error') },\n wakeAt: { type: 'Date', nullable: true, fieldName: col('wakeAt') },\n lockedBy: { type: 'string', nullable: true, fieldName: col('lockedBy') },\n lockedUntil: { type: 'Date', nullable: true, fieldName: col('lockedUntil') },\n recoveryAttempts: { type: 'integer', nullable: true, fieldName: col('recoveryAttempts') },\n tags: { type: 'json', nullable: true, fieldName: col('tags') },\n searchAttributes: { type: 'json', nullable: true, fieldName: col('searchAttributes') },\n createdAt: { type: 'Date', fieldName: col('createdAt') },\n updatedAt: { type: 'Date', fieldName: col('updatedAt') },\n },\n });\n\n const stepCheckpoints = new EntitySchema<StepCheckpointEntity>({\n class: StepCheckpointEntity,\n tableName: 'durable_step_checkpoints',\n properties: {\n runId: { type: 'string', primary: true, fieldName: col('runId') },\n seq: { type: 'integer', primary: true, fieldName: col('seq') },\n name: { type: 'string', fieldName: col('name') },\n kind: { type: 'string', fieldName: col('kind') },\n stepId: { type: 'string', fieldName: col('stepId') },\n status: { type: 'string', fieldName: col('status') },\n input: { type: 'json', nullable: true, fieldName: col('input') },\n output: { type: 'json', nullable: true, fieldName: col('output') },\n error: { type: 'json', nullable: true, fieldName: col('error') },\n events: { type: 'json', nullable: true, fieldName: col('events') },\n attempts: { type: 'integer', fieldName: col('attempts') },\n workerGroup: { type: 'string', nullable: true, fieldName: col('workerGroup') },\n wakeAt: { type: 'Date', nullable: true, fieldName: col('wakeAt') },\n enqueuedAt: { type: 'Date', nullable: true, fieldName: col('enqueuedAt') },\n startedAt: { type: 'Date', fieldName: col('startedAt') },\n finishedAt: { type: 'Date', fieldName: col('finishedAt') },\n },\n });\n\n const runAttributes = new EntitySchema<RunAttributeEntity>({\n class: RunAttributeEntity,\n tableName: 'durable_run_attributes',\n properties: {\n runId: { type: 'string', primary: true, fieldName: col('runId') },\n key: { type: 'string', primary: true, fieldName: col('key') },\n strValue: { type: 'string', nullable: true, fieldName: col('strValue') },\n // `float`/`double` is portable across SQLite/MySQL/Postgres for numeric range scans.\n numValue: { type: 'float', nullable: true, fieldName: col('numValue') },\n },\n });\n\n const signalWaiters = new EntitySchema<SignalWaiterEntity>({\n class: SignalWaiterEntity,\n tableName: 'durable_signal_waiters',\n properties: {\n token: { type: 'string', primary: true, fieldName: col('token') },\n runId: { type: 'string', fieldName: col('runId') },\n seq: { type: 'integer', fieldName: col('seq') },\n },\n });\n\n const bufferedSignals = new EntitySchema<BufferedSignalEntity>({\n class: BufferedSignalEntity,\n tableName: 'durable_buffered_signals',\n properties: {\n id: { type: 'integer', primary: true, autoincrement: true, fieldName: col('id') },\n token: { type: 'string', index: true, fieldName: col('token') },\n payload: { type: 'json', nullable: true, fieldName: col('payload') },\n },\n });\n\n return [workflowRuns, stepCheckpoints, runAttributes, signalWaiters, bufferedSignals];\n}\n\n/** Durable entity schemas with the canonical `'snake_case'` column names. */\nexport const ENTITIES = durableEntities();\n","import {\n type AttributeFilter,\n type RunQuery,\n type SignalWaiter,\n type StateStore,\n type StepCheckpoint,\n type StepError,\n type StepEvent,\n type WorkflowRun,\n attributeColumnFor,\n attributeOperand,\n normalizeAttributeRows,\n sqlComparator,\n} from '@dudousxd/nestjs-durable-core';\nimport type { EntityManager, MikroORM } from '@mikro-orm/core';\n\n/** Minimal structural surface of the SQL EntityManager's QueryBuilder (from `@mikro-orm/knex`),\n * typed here so the adapter needn't add a hard dependency on the knex types — a real SQL-driver EM\n * satisfies it at runtime. */\ninterface DurableQueryBuilder<T> {\n where(cond: Record<string, unknown>): DurableQueryBuilder<T>;\n andWhere(cond: string): DurableQueryBuilder<T>;\n orderBy(cond: Record<string, unknown>): DurableQueryBuilder<T>;\n limit(n: number): DurableQueryBuilder<T>;\n offset(n: number): DurableQueryBuilder<T>;\n getResultList(): Promise<T[]>;\n}\ntype SqlEm = EntityManager & {\n createQueryBuilder<T>(entity: unknown, alias: string): DurableQueryBuilder<T>;\n};\n\n/** Resolved side-table column names (per the active naming strategy) for the raw EXISTS pushdown. */\ninterface AttributeColumns {\n table: string;\n /** Side-table FK column (the run id on `durable_run_attributes`). */\n runId: string;\n /** Run table PK column (the `id` on `durable_workflow_runs`) used for the outer correlation. */\n runPk: string;\n key: string;\n strValue: string;\n numValue: string;\n}\nimport {\n BufferedSignalEntity,\n RunAttributeEntity,\n SignalWaiterEntity,\n StepCheckpointEntity,\n WorkflowRunEntity,\n} from './entities';\nimport { ensureMikroOrmDurableSchema } from './schema';\n\n/**\n * MikroORM-backed `StateStore`. Works on any MikroORM driver — Postgres, MySQL, SQLite (tested);\n * timestamps and `wakeAt` use native datetime columns. Each operation runs on a forked\n * EntityManager so it owns its unit of work.\n */\nexport class MikroOrmStateStore implements StateStore {\n constructor(private readonly orm: MikroORM) {}\n\n async ensureSchema(): Promise<void> {\n await ensureMikroOrmDurableSchema(this.orm);\n }\n\n async createRun(run: WorkflowRun): Promise<void> {\n const em = this.orm.em.fork();\n em.create(WorkflowRunEntity, toRunEntity(run));\n await em.flush();\n await this.reindexAttributes(run.id, run.searchAttributes);\n }\n\n async updateRun(runId: string, patch: Partial<WorkflowRun>): Promise<void> {\n const em = this.orm.em.fork();\n const entity = await em.findOneOrFail(WorkflowRunEntity, { id: runId });\n Object.assign(entity, toRunEntity({ ...fromRunEntity(entity), ...patch } as WorkflowRun));\n await em.flush();\n // Keep the side-table in step with the run's attributes whenever they're patched.\n if ('searchAttributes' in patch) await this.reindexAttributes(runId, patch.searchAttributes);\n }\n\n /** Rewrite a run's normalized attribute rows: delete the old set, insert the current one. Mirrors\n * the in-memory store's reindex so the side-table always reflects the run's live searchAttributes. */\n private async reindexAttributes(\n runId: string,\n attributes: WorkflowRun['searchAttributes'],\n forked?: EntityManager,\n ): Promise<void> {\n const em = forked ?? this.orm.em.fork();\n await em.nativeDelete(RunAttributeEntity, { runId });\n const rows = normalizeAttributeRows(runId, attributes);\n if (rows.length) await em.insertMany(RunAttributeEntity, rows);\n }\n\n async getRun(runId: string): Promise<WorkflowRun | null> {\n const em = this.orm.em.fork();\n const entity = await em.findOne(WorkflowRunEntity, { id: runId });\n return entity ? fromRunEntity(entity) : null;\n }\n\n async deleteRun(runId: string): Promise<void> {\n const em = this.orm.em.fork();\n // Children first, then the run row — checkpoints, signal waiters, and the normalized\n // attribute side-table, so nothing dangles after the run is gone.\n await em.nativeDelete(StepCheckpointEntity, { runId });\n await em.nativeDelete(SignalWaiterEntity, { runId });\n await em.nativeDelete(RunAttributeEntity, { runId });\n await em.nativeDelete(WorkflowRunEntity, { id: runId });\n }\n\n async getCheckpoint(runId: string, seq: number): Promise<StepCheckpoint | null> {\n const em = this.orm.em.fork();\n const entity = await em.findOne(StepCheckpointEntity, { runId, seq });\n return entity ? fromCheckpointEntity(entity) : null;\n }\n\n async saveCheckpoint(checkpoint: StepCheckpoint): Promise<void> {\n const em = this.orm.em.fork();\n await em.upsert(StepCheckpointEntity, toCheckpointEntity(checkpoint));\n await em.flush();\n }\n\n async transaction<T>(\n work: (tx: {\n raw: unknown;\n saveCheckpoint: (cp: StepCheckpoint) => Promise<void>;\n }) => Promise<T>,\n ): Promise<T> {\n return this.orm.em.fork().transactional(async (em) =>\n work({\n raw: em,\n saveCheckpoint: async (cp) => {\n await em.upsert(StepCheckpointEntity, toCheckpointEntity(cp));\n },\n }),\n );\n }\n\n async listIncompleteRuns(): Promise<WorkflowRun[]> {\n const em = this.orm.em.fork();\n const rows = await em.find(WorkflowRunEntity, { status: 'running' });\n return rows.map(fromRunEntity);\n }\n\n async listPendingRuns(limit: number): Promise<WorkflowRun[]> {\n const em = this.orm.em.fork();\n const rows = await em.find(\n WorkflowRunEntity,\n { status: 'pending' },\n { orderBy: { createdAt: 'asc' }, limit }, // FIFO dispatch\n );\n return rows.map(fromRunEntity);\n }\n\n async listDueTimers(nowMs: number): Promise<WorkflowRun[]> {\n const em = this.orm.em.fork();\n const rows = await em.find(WorkflowRunEntity, {\n status: 'suspended',\n wakeAt: { $ne: null, $lte: new Date(nowMs) },\n });\n return rows.map(fromRunEntity);\n }\n\n async tryLockRun(\n runId: string,\n owner: string,\n leaseUntilMs: number,\n nowMs: number,\n ): Promise<boolean> {\n const em = this.orm.em.fork();\n const affected = await em.nativeUpdate(\n WorkflowRunEntity,\n { id: runId, $or: [{ lockedUntil: null }, { lockedUntil: { $lte: new Date(nowMs) } }] },\n { lockedBy: owner, lockedUntil: new Date(leaseUntilMs) },\n );\n return affected === 1;\n }\n\n async releaseRunLock(runId: string): Promise<void> {\n const em = this.orm.em.fork();\n await em.nativeUpdate(WorkflowRunEntity, { id: runId }, { lockedBy: null, lockedUntil: null });\n }\n\n async renewRunLock(runId: string, owner: string, leaseUntilMs: number): Promise<boolean> {\n const em = this.orm.em.fork();\n const affected = await em.nativeUpdate(\n WorkflowRunEntity,\n { id: runId, lockedBy: owner },\n { lockedUntil: new Date(leaseUntilMs) },\n );\n return affected === 1;\n }\n\n async listRuns(query: RunQuery): Promise<WorkflowRun[]> {\n const em = this.orm.em.fork();\n const where: Record<string, unknown> = {};\n if (query.workflow) where.workflow = query.workflow;\n // `status IN (...)`; an empty set matches nothing (mirrors the in-memory store). When both the\n // single `status` and `statuses` are set, AND them so the narrower set wins.\n if (query.status && query.statuses) {\n where.$and = [{ status: query.status }, { status: { $in: query.statuses } }];\n } else if (query.status) {\n where.status = query.status;\n } else if (query.statuses) {\n where.status = { $in: query.statuses };\n }\n const orderBy = { createdAt: 'desc' as const }; // newest first — recent runs on top in the dashboard\n // `tags`/attributes need raw SQL pushed through the QueryBuilder:\n // - tag: `tags` is a JSON column (native json/jsonb on PG/MySQL), and MikroORM JSON-serializes a\n // `{ $like }` operand (wrapping/escaping the LIKE pattern) so a plain where corrupts it to no\n // matches. A raw LIKE on the column-as-text matches the quoted token so `etl` doesn't match\n // `etl-foo`. Postgres `jsonb` rejects `LIKE` directly, so cast to text per dialect.\n // - attributes: each filter becomes a raw EXISTS against the normalized side-table, so the DB\n // filters AND paginates — no full scan + in-process filter (ANDed: one EXISTS per filter).\n // Use a QueryBuilder with a fixed root alias `r` so the raw correlations are stable across drivers.\n if (query.tag || query.attributes?.length) {\n const quote = this.idQuote(em);\n const cols = this.attributeColumns(em);\n const qb = (em as SqlEm)\n .createQueryBuilder<WorkflowRunEntity>(WorkflowRunEntity, 'r')\n .where(where)\n .orderBy(orderBy);\n if (query.tag) {\n const tagsCol = this.tagsColumn(em);\n const pattern = `%\"${query.tag.replace(/'/g, \"''\")}\"%`;\n const colExpr = this.jsonAsText(em, `${quote('r')}.${quote(tagsCol)}`);\n qb.andWhere(`${colExpr} LIKE '${pattern}'`);\n }\n for (const f of query.attributes ?? []) {\n qb.andWhere(this.attributeExistsSql(f, quote, 'r', cols));\n }\n if (query.limit != null) qb.limit(query.limit);\n if (query.offset != null) qb.offset(query.offset);\n const rows = await qb.getResultList();\n return rows.map(fromRunEntity);\n }\n const rows = await em.find(WorkflowRunEntity, where, {\n ...(query.limit != null ? { limit: query.limit } : {}),\n ...(query.offset != null ? { offset: query.offset } : {}),\n orderBy,\n });\n return rows.map(fromRunEntity);\n }\n\n /** One attribute predicate as a raw EXISTS subquery on the side-table, correlated to the outer run\n * alias. `<>` (ne) also excludes runs where the attribute is absent (missing-key-never-matches):\n * EXISTS already requires a present row, so EXISTS(... <> ...) is exactly ne-with-present. Numeric\n * operands compare the num column, everything else the str column. Identifiers are quoted per\n * driver and operands are inlined as literals (string operands are escaped by doubling quotes). */\n private attributeExistsSql(\n f: AttributeFilter,\n quote: (id: string) => string,\n alias: string,\n cols: AttributeColumns,\n ): string {\n const col = attributeColumnFor(f) === 'numValue' ? cols.numValue : cols.strValue;\n const cmp = sqlComparator(f.op);\n const operand = attributeOperand(f);\n const literal =\n typeof operand === 'number' ? String(operand) : `'${String(operand).replace(/'/g, \"''\")}'`;\n const a = quote(cols.table);\n const sub = quote('a');\n const outerId = `${quote(alias)}.${quote(cols.runPk)}`; // run PK column on the outer alias\n return `EXISTS (SELECT 1 FROM ${a} ${sub} WHERE ${sub}.${quote(cols.runId)} = ${outerId} AND ${sub}.${quote(cols.key)} = '${f.key.replace(/'/g, \"''\")}' AND ${sub}.${quote(col)} ${cmp} ${literal})`;\n }\n\n /** Resolve the side-table's actual column names from MikroORM metadata, so the raw EXISTS matches\n * the active naming strategy (underscore vs camelCase) rather than guessing. The run PK column is\n * reused for BOTH the outer correlation and the side-table FK (they share the same fieldName). */\n private attributeColumns(em: EntityManager): AttributeColumns {\n const meta = em.getMetadata().get(RunAttributeEntity);\n const field = (prop: string) =>\n meta.props.find((p) => p.name === prop)?.fieldNames?.[0] ?? prop;\n const runMeta = em.getMetadata().get(WorkflowRunEntity);\n const runPk = runMeta.properties.id?.fieldNames?.[0] ?? 'id';\n return {\n table: meta.tableName,\n runId: field('runId'),\n runPk,\n key: field('key'),\n strValue: field('strValue'),\n numValue: field('numValue'),\n };\n }\n\n /** Resolve the `tags` column name from metadata (per the active naming strategy), for the raw LIKE. */\n private tagsColumn(em: EntityManager): string {\n const runMeta = em.getMetadata().get(WorkflowRunEntity);\n return runMeta.properties.tags?.fieldNames?.[0] ?? 'tags';\n }\n\n /** Wrap a JSON column reference so it can be `LIKE`d as text. Postgres `jsonb`/`json` rejects `LIKE`\n * directly (`operator does not exist: jsonb ~~ unknown`) — cast to `text`; MySQL JSON needs an\n * explicit `CHAR` cast; SQLite stores JSON as text already, so no cast. */\n private jsonAsText(em: EntityManager, colRef: string): string {\n const platform = String(em.getPlatform().constructor.name).toLowerCase();\n if (platform.includes('postgre')) return `${colRef}::text`;\n if (platform.includes('mysql') || platform.includes('mariadb'))\n return `CAST(${colRef} AS CHAR)`;\n return colRef;\n }\n\n /** Quote an identifier per the active SQL driver (MySQL/MariaDB backtick, others double-quote). */\n private idQuote(em: EntityManager): (id: string) => string {\n const platform = String(em.getPlatform().constructor.name).toLowerCase();\n const isMysql = platform.includes('mysql') || platform.includes('mariadb');\n const ch = isMysql ? '`' : '\"';\n return (id: string) => `${ch}${id}${ch}`;\n }\n\n async listCheckpoints(runId: string): Promise<StepCheckpoint[]> {\n const em = this.orm.em.fork();\n const rows = await em.find(StepCheckpointEntity, { runId }, { orderBy: { seq: 'asc' } });\n return rows.map(fromCheckpointEntity);\n }\n\n async getLatestCheckpointByName(\n runId: string,\n name: string,\n ): Promise<StepCheckpoint | undefined> {\n const em = this.orm.em.fork();\n const entity = await em.findOne(\n StepCheckpointEntity,\n { runId, name },\n { orderBy: { seq: 'desc' } },\n );\n return entity ? fromCheckpointEntity(entity) : undefined;\n }\n\n async listCheckpointsByNamePrefix(runId: string, prefixes: string[]): Promise<StepCheckpoint[]> {\n if (prefixes.length === 0) return [];\n const em = this.orm.em.fork();\n const rows = await em.find(\n StepCheckpointEntity,\n { runId, $or: prefixes.map((p) => ({ name: { $like: `${p}%` } })) },\n { orderBy: { seq: 'asc' } },\n );\n return rows.map(fromCheckpointEntity);\n }\n\n async putSignalWaiter(waiter: SignalWaiter): Promise<void> {\n const em = this.orm.em.fork();\n await em.upsert(SignalWaiterEntity, { ...waiter });\n await em.flush();\n }\n\n async takeSignalWaiter(token: string): Promise<SignalWaiter | null> {\n const em = this.orm.em.fork();\n const entity = await em.findOne(SignalWaiterEntity, { token });\n if (!entity) return null;\n const waiter: SignalWaiter = { token: entity.token, runId: entity.runId, seq: entity.seq };\n await em.remove(entity).flush();\n return waiter;\n }\n\n async listSignalWaiters(prefix: string): Promise<SignalWaiter[]> {\n const em = this.orm.em.fork();\n const rows = await em.find(SignalWaiterEntity, { token: { $like: `${prefix}%` } });\n return rows.map((e) => ({ token: e.token, runId: e.runId, seq: e.seq }));\n }\n\n async bufferSignal(token: string, payload: unknown): Promise<void> {\n const em = this.orm.em.fork();\n const e = new BufferedSignalEntity();\n e.token = token;\n e.payload = payload ?? null;\n em.persist(e);\n await em.flush();\n }\n\n async takeBufferedSignal(token: string): Promise<{ payload: unknown } | null> {\n const em = this.orm.em.fork();\n const entity = await em.findOne(BufferedSignalEntity, { token }, { orderBy: { id: 'asc' } });\n if (!entity) return null;\n const payload = entity.payload ?? undefined;\n await em.remove(entity).flush();\n return { payload };\n }\n}\n\nfunction toRunEntity(run: WorkflowRun): WorkflowRunEntity {\n const e = new WorkflowRunEntity();\n e.id = run.id;\n e.workflow = run.workflow;\n e.workflowVersion = run.workflowVersion;\n e.status = run.status;\n e.input = run.input ?? null;\n e.output = run.output ?? null;\n e.error = run.error ?? null;\n if (run.wakeAt != null) e.wakeAt = new Date(run.wakeAt);\n if (run.lockedBy !== undefined) e.lockedBy = run.lockedBy;\n if (run.lockedUntil != null) e.lockedUntil = new Date(run.lockedUntil);\n if (run.recoveryAttempts !== undefined) e.recoveryAttempts = run.recoveryAttempts;\n e.tags = run.tags ?? null;\n e.searchAttributes = run.searchAttributes ?? null;\n e.createdAt = run.createdAt;\n e.updatedAt = run.updatedAt;\n return e;\n}\n\nfunction fromRunEntity(e: WorkflowRunEntity): WorkflowRun {\n return {\n id: e.id,\n workflow: e.workflow,\n workflowVersion: e.workflowVersion,\n status: e.status,\n input: e.input ?? undefined,\n output: e.output ?? undefined,\n error: (e.error ?? undefined) as StepError | undefined,\n wakeAt: e.wakeAt?.getTime(),\n lockedBy: e.lockedBy ?? undefined,\n lockedUntil: e.lockedUntil?.getTime(),\n recoveryAttempts: e.recoveryAttempts ?? undefined,\n tags: e.tags ?? undefined,\n searchAttributes: e.searchAttributes ?? undefined,\n createdAt: e.createdAt,\n updatedAt: e.updatedAt,\n };\n}\n\nfunction toCheckpointEntity(cp: StepCheckpoint): StepCheckpointEntity {\n const e = new StepCheckpointEntity();\n e.runId = cp.runId;\n e.seq = cp.seq;\n e.name = cp.name;\n e.kind = cp.kind;\n e.stepId = cp.stepId;\n e.status = cp.status;\n e.input = cp.input ?? null;\n e.output = cp.output ?? null;\n e.error = cp.error ?? null;\n e.events = cp.events ?? null;\n e.attempts = cp.attempts;\n if (cp.workerGroup !== undefined) e.workerGroup = cp.workerGroup;\n if (cp.wakeAt != null) e.wakeAt = new Date(cp.wakeAt);\n e.enqueuedAt = cp.enqueuedAt;\n e.startedAt = cp.startedAt;\n e.finishedAt = cp.finishedAt;\n return e;\n}\n\nfunction fromCheckpointEntity(e: StepCheckpointEntity): StepCheckpoint {\n return {\n runId: e.runId,\n seq: e.seq,\n name: e.name,\n kind: e.kind,\n stepId: e.stepId,\n status: e.status,\n input: e.input ?? undefined,\n output: e.output ?? undefined,\n error: (e.error ?? undefined) as StepError | undefined,\n events: (e.events ?? undefined) as StepEvent[] | undefined,\n attempts: e.attempts,\n workerGroup: e.workerGroup ?? undefined,\n wakeAt: e.wakeAt?.getTime(),\n enqueuedAt: e.enqueuedAt ?? e.startedAt,\n startedAt: e.startedAt,\n finishedAt: e.finishedAt,\n };\n}\n","import type { MikroORM } from '@mikro-orm/core';\n\n/**\n * The tables this store owns. Kept in sync with the `tableName`s in `./entities`. Used to scope\n * schema management to our own tables (see {@link ensureMikroOrmDurableSchema}).\n */\nconst DURABLE_TABLE_NAMES = new Set([\n 'durable_workflow_runs',\n 'durable_step_checkpoints',\n 'durable_run_attributes',\n 'durable_signal_waiters',\n 'durable_buffered_signals',\n]);\n\n/** The table a `create table` / `alter table` statement targets, lower-cased; undefined otherwise. */\nfunction targetTable(statement: string): string | undefined {\n const match = statement.match(\n /^(?:create|alter)\\s+table\\s+(?:if\\s+not\\s+exists\\s+)?[`\"']?([\\w$]+)[`\"']?/i,\n );\n return match?.[1]?.toLowerCase();\n}\n\n/**\n * Idempotently create/extend ONLY the durable tables (additive — never drops). Safe to run on every\n * boot (auto-schema) and from a MikroORM migration when you disable auto-schema:\n *\n * ```ts\n * export class AddDurableTables extends Migration {\n * async up() { await ensureMikroOrmDurableSchema(this.getEntityManager().getOrm()); }\n * }\n * ```\n *\n * It does NOT run a whole-ORM `schema.update()`. When the store shares the host app's ORM (the\n * recommended setup — a single ORM avoids MikroORM's global-metadata clobber between instances),\n * a full `schema.update()` would try to reconcile EVERY app table to the entity metadata: on a\n * migration-managed schema that means recreating the migrations table and dropping app foreign keys.\n * Instead we compute the safe additive diff and execute only the statements that target our own\n * `durable_*` tables. `getUpdateSchemaSQL` already emits a `create table` only for a missing table\n * and `alter table ... add` only for missing columns, so existing tables — and the entire rest of\n * the host schema — are left untouched.\n */\nexport async function ensureMikroOrmDurableSchema(orm: MikroORM): Promise<void> {\n const sql = await orm.schema.getUpdateSchemaSQL({ safe: true });\n const ours = sql\n .split(';')\n .map((statement) => statement.trim())\n .filter((statement) => {\n const table = targetTable(statement);\n return table !== undefined && DURABLE_TABLE_NAMES.has(table);\n });\n if (ours.length === 0) {\n return;\n }\n const connection = orm.em.getConnection();\n for (const statement of ours) {\n await connection.execute(statement);\n }\n}\n"],"mappings":"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","names":["snakeCase","property","replace","c","toLowerCase","columnNamer","naming","WorkflowRunEntity","id","workflow","workflowVersion","status","input","output","error","wakeAt","lockedBy","lockedUntil","recoveryAttempts","tags","searchAttributes","createdAt","updatedAt","StepCheckpointEntity","runId","seq","name","kind","stepId","events","attempts","workerGroup","enqueuedAt","startedAt","finishedAt","RunAttributeEntity","key","strValue","numValue","SignalWaiterEntity","token","BufferedSignalEntity","payload","durableEntities","options","col","workflowRuns","EntitySchema","class","tableName","properties","type","primary","fieldName","nullable","stepCheckpoints","runAttributes","signalWaiters","bufferedSignals","autoincrement","index","ENTITIES","DURABLE_TABLE_NAMES","Set","targetTable","statement","match","toLowerCase","ensureMikroOrmDurableSchema","orm","sql","schema","getUpdateSchemaSQL","safe","ours","split","map","trim","filter","table","undefined","has","length","connection","em","getConnection","execute","MikroOrmStateStore","orm","ensureSchema","ensureMikroOrmDurableSchema","createRun","run","em","fork","create","WorkflowRunEntity","toRunEntity","flush","reindexAttributes","id","searchAttributes","updateRun","runId","patch","entity","findOneOrFail","Object","assign","fromRunEntity","attributes","forked","nativeDelete","RunAttributeEntity","rows","normalizeAttributeRows","length","insertMany","getRun","findOne","deleteRun","StepCheckpointEntity","SignalWaiterEntity","getCheckpoint","seq","fromCheckpointEntity","saveCheckpoint","checkpoint","upsert","toCheckpointEntity","transaction","work","transactional","raw","cp","listIncompleteRuns","find","status","map","listPendingRuns","limit","orderBy","createdAt","listDueTimers","nowMs","wakeAt","$ne","$lte","Date","tryLockRun","owner","leaseUntilMs","affected","nativeUpdate","$or","lockedUntil","lockedBy","releaseRunLock","renewRunLock","listRuns","query","where","workflow","statuses","$and","$in","tag","quote","idQuote","cols","attributeColumns","qb","createQueryBuilder","tagsCol","tagsColumn","pattern","replace","colExpr","jsonAsText","andWhere","f","attributeExistsSql","offset","getResultList","alias","col","attributeColumnFor","numValue","strValue","cmp","sqlComparator","op","operand","attributeOperand","literal","String","a","table","sub","outerId","runPk","key","meta","getMetadata","get","field","prop","props","p","name","fieldNames","runMeta","properties","tableName","tags","colRef","platform","getPlatform","toLowerCase","includes","isMysql","ch","listCheckpoints","getLatestCheckpointByName","undefined","listCheckpointsByNamePrefix","prefixes","$like","putSignalWaiter","waiter","takeSignalWaiter","token","remove","listSignalWaiters","prefix","e","bufferSignal","payload","BufferedSignalEntity","persist","takeBufferedSignal","workflowVersion","input","output","error","recoveryAttempts","updatedAt","getTime","kind","stepId","events","attempts","workerGroup","enqueuedAt","startedAt","finishedAt"]}
package/dist/index.d.cts CHANGED
@@ -101,6 +101,7 @@ declare class MikroOrmStateStore implements StateStore {
101
101
  * the in-memory store's reindex so the side-table always reflects the run's live searchAttributes. */
102
102
  private reindexAttributes;
103
103
  getRun(runId: string): Promise<WorkflowRun | null>;
104
+ deleteRun(runId: string): Promise<void>;
104
105
  getCheckpoint(runId: string, seq: number): Promise<StepCheckpoint | null>;
105
106
  saveCheckpoint(checkpoint: StepCheckpoint): Promise<void>;
106
107
  transaction<T>(work: (tx: {
@@ -145,15 +146,23 @@ declare class MikroOrmStateStore implements StateStore {
145
146
  }
146
147
 
147
148
  /**
148
- * Idempotently create/extend the durable tables (additive, never drops). Safe to run on every
149
- * boot (auto-schema) and the function to call from a MikroORM migration when you disable
150
- * auto-schema:
149
+ * Idempotently create/extend ONLY the durable tables (additive — never drops). Safe to run on every
150
+ * boot (auto-schema) and from a MikroORM migration when you disable auto-schema:
151
151
  *
152
152
  * ```ts
153
153
  * export class AddDurableTables extends Migration {
154
154
  * async up() { await ensureMikroOrmDurableSchema(this.getEntityManager().getOrm()); }
155
155
  * }
156
156
  * ```
157
+ *
158
+ * It does NOT run a whole-ORM `schema.update()`. When the store shares the host app's ORM (the
159
+ * recommended setup — a single ORM avoids MikroORM's global-metadata clobber between instances),
160
+ * a full `schema.update()` would try to reconcile EVERY app table to the entity metadata: on a
161
+ * migration-managed schema that means recreating the migrations table and dropping app foreign keys.
162
+ * Instead we compute the safe additive diff and execute only the statements that target our own
163
+ * `durable_*` tables. `getUpdateSchemaSQL` already emits a `create table` only for a missing table
164
+ * and `alter table ... add` only for missing columns, so existing tables — and the entire rest of
165
+ * the host schema — are left untouched.
157
166
  */
158
167
  declare function ensureMikroOrmDurableSchema(orm: MikroORM): Promise<void>;
159
168
 
package/dist/index.d.ts CHANGED
@@ -101,6 +101,7 @@ declare class MikroOrmStateStore implements StateStore {
101
101
  * the in-memory store's reindex so the side-table always reflects the run's live searchAttributes. */
102
102
  private reindexAttributes;
103
103
  getRun(runId: string): Promise<WorkflowRun | null>;
104
+ deleteRun(runId: string): Promise<void>;
104
105
  getCheckpoint(runId: string, seq: number): Promise<StepCheckpoint | null>;
105
106
  saveCheckpoint(checkpoint: StepCheckpoint): Promise<void>;
106
107
  transaction<T>(work: (tx: {
@@ -145,15 +146,23 @@ declare class MikroOrmStateStore implements StateStore {
145
146
  }
146
147
 
147
148
  /**
148
- * Idempotently create/extend the durable tables (additive, never drops). Safe to run on every
149
- * boot (auto-schema) and the function to call from a MikroORM migration when you disable
150
- * auto-schema:
149
+ * Idempotently create/extend ONLY the durable tables (additive — never drops). Safe to run on every
150
+ * boot (auto-schema) and from a MikroORM migration when you disable auto-schema:
151
151
  *
152
152
  * ```ts
153
153
  * export class AddDurableTables extends Migration {
154
154
  * async up() { await ensureMikroOrmDurableSchema(this.getEntityManager().getOrm()); }
155
155
  * }
156
156
  * ```
157
+ *
158
+ * It does NOT run a whole-ORM `schema.update()`. When the store shares the host app's ORM (the
159
+ * recommended setup — a single ORM avoids MikroORM's global-metadata clobber between instances),
160
+ * a full `schema.update()` would try to reconcile EVERY app table to the entity metadata: on a
161
+ * migration-managed schema that means recreating the migrations table and dropping app foreign keys.
162
+ * Instead we compute the safe additive diff and execute only the statements that target our own
163
+ * `durable_*` tables. `getUpdateSchemaSQL` already emits a `create table` only for a missing table
164
+ * and `alter table ... add` only for missing columns, so existing tables — and the entire rest of
165
+ * the host schema — are left untouched.
157
166
  */
158
167
  declare function ensureMikroOrmDurableSchema(orm: MikroORM): Promise<void>;
159
168
 
package/dist/index.js CHANGED
@@ -319,10 +319,33 @@ var ENTITIES = durableEntities();
319
319
  import { attributeColumnFor, attributeOperand, normalizeAttributeRows, sqlComparator } from "@dudousxd/nestjs-durable-core";
320
320
 
321
321
  // src/schema.ts
322
+ var DURABLE_TABLE_NAMES = /* @__PURE__ */ new Set([
323
+ "durable_workflow_runs",
324
+ "durable_step_checkpoints",
325
+ "durable_run_attributes",
326
+ "durable_signal_waiters",
327
+ "durable_buffered_signals"
328
+ ]);
329
+ function targetTable(statement) {
330
+ const match = statement.match(/^(?:create|alter)\s+table\s+(?:if\s+not\s+exists\s+)?[`"']?([\w$]+)[`"']?/i);
331
+ return match?.[1]?.toLowerCase();
332
+ }
333
+ __name(targetTable, "targetTable");
322
334
  async function ensureMikroOrmDurableSchema(orm) {
323
- await orm.schema.update({
335
+ const sql = await orm.schema.getUpdateSchemaSQL({
324
336
  safe: true
325
337
  });
338
+ const ours = sql.split(";").map((statement) => statement.trim()).filter((statement) => {
339
+ const table = targetTable(statement);
340
+ return table !== void 0 && DURABLE_TABLE_NAMES.has(table);
341
+ });
342
+ if (ours.length === 0) {
343
+ return;
344
+ }
345
+ const connection = orm.em.getConnection();
346
+ for (const statement of ours) {
347
+ await connection.execute(statement);
348
+ }
326
349
  }
327
350
  __name(ensureMikroOrmDurableSchema, "ensureMikroOrmDurableSchema");
328
351
 
@@ -373,6 +396,21 @@ var MikroOrmStateStore = class {
373
396
  });
374
397
  return entity ? fromRunEntity(entity) : null;
375
398
  }
399
+ async deleteRun(runId) {
400
+ const em = this.orm.em.fork();
401
+ await em.nativeDelete(StepCheckpointEntity, {
402
+ runId
403
+ });
404
+ await em.nativeDelete(SignalWaiterEntity, {
405
+ runId
406
+ });
407
+ await em.nativeDelete(RunAttributeEntity, {
408
+ runId
409
+ });
410
+ await em.nativeDelete(WorkflowRunEntity, {
411
+ id: runId
412
+ });
413
+ }
376
414
  async getCheckpoint(runId, seq) {
377
415
  const em = this.orm.em.fork();
378
416
  const entity = await em.findOne(StepCheckpointEntity, {
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/entities.ts","../src/mikro-orm-state-store.ts","../src/schema.ts"],"sourcesContent":["import type { RunStatus, StepKind } from '@dudousxd/nestjs-durable-core';\nimport { EntitySchema } from '@mikro-orm/core';\n\n/**\n * How property names map to physical column names. The durable tables are adapter-agnostic: a run\n * written by one store adapter must be readable by another, so every adapter has to agree on the\n * physical column names. The default is `'snake_case'` (the canonical, matched by the TypeORM,\n * Prisma and Drizzle adapters). `'preserve'` keeps the camelCase property name verbatim (what the\n * old TypeORM/Prisma adapters produced before they were pinned). A function lets you supply any\n * custom mapping.\n *\n * The choice is pinned EXPLICITLY onto the entity schema rather than left to the host ORM's naming\n * strategy — depending on the host strategy is what silently diverged the adapters and broke a store\n * swap against an existing table.\n */\nexport type DurableColumnNaming = 'snake_case' | 'preserve' | ((property: string) => string);\n\nfunction snakeCase(property: string): string {\n return property.replace(/[A-Z]/g, (c) => `_${c.toLowerCase()}`);\n}\n\nfunction columnNamer(naming: DurableColumnNaming): (property: string) => string {\n if (naming === 'snake_case') return snakeCase;\n if (naming === 'preserve') return (property) => property;\n return naming;\n}\n\n// Plain classes (no decorators): the schema/column mapping lives on the EntitySchema built by\n// `durableEntities`, so the same class can be registered under different column names. The store\n// still references these classes for `em.create`/`getMetadata`.\n\nexport class WorkflowRunEntity {\n id!: string;\n workflow!: string;\n workflowVersion!: string;\n status!: RunStatus;\n input?: unknown;\n output?: unknown;\n error?: unknown;\n wakeAt?: Date;\n lockedBy?: string;\n lockedUntil?: Date;\n recoveryAttempts?: number;\n tags?: string[] | null;\n searchAttributes?: Record<string, string | number | boolean> | null;\n createdAt!: Date;\n updatedAt!: Date;\n}\n\nexport class StepCheckpointEntity {\n runId!: string;\n seq!: number;\n name!: string;\n kind!: StepKind;\n stepId!: string;\n status!: 'pending' | 'running' | 'completed' | 'failed';\n input?: unknown;\n output?: unknown;\n error?: unknown;\n events?: unknown;\n attempts!: number;\n workerGroup?: string;\n wakeAt?: Date;\n enqueuedAt?: Date;\n startedAt!: Date;\n finishedAt!: Date;\n}\n\n/**\n * Normalized side-table for search attributes: one row per (run, key), so range/equality predicates\n * push DOWN into SQL (an EXISTS join indexed on `(key, numValue)` / `(key, strValue)`) instead of a\n * coarse scan + in-process filter. Maintained on every createRun/updateRun. Numbers land in\n * `numValue`, strings/booleans in `strValue` (booleans as \"true\"/\"false\"); see normalizeAttributeRows.\n */\nexport class RunAttributeEntity {\n runId!: string;\n key!: string;\n strValue?: string | null;\n numValue?: number | null;\n}\n\nexport class SignalWaiterEntity {\n token!: string;\n runId!: string;\n seq!: number;\n}\n\nexport class BufferedSignalEntity {\n id!: number;\n token!: string;\n payload?: unknown;\n}\n\n/**\n * Build the durable MikroORM entity schemas with column names pinned per `naming` (default\n * `'snake_case'`). Register the result in your MikroORM config / `MikroOrmModule.forFeature`.\n *\n * ```ts\n * entities: durableEntities({ naming: 'snake_case' })\n * ```\n */\nexport function durableEntities(options: { naming?: DurableColumnNaming } = {}): EntitySchema[] {\n const col = columnNamer(options.naming ?? 'snake_case');\n\n const workflowRuns = new EntitySchema<WorkflowRunEntity>({\n class: WorkflowRunEntity,\n tableName: 'durable_workflow_runs',\n properties: {\n id: { type: 'string', primary: true, fieldName: col('id') },\n workflow: { type: 'string', fieldName: col('workflow') },\n workflowVersion: { type: 'string', fieldName: col('workflowVersion') },\n status: { type: 'string', fieldName: col('status') },\n input: { type: 'json', nullable: true, fieldName: col('input') },\n output: { type: 'json', nullable: true, fieldName: col('output') },\n error: { type: 'json', nullable: true, fieldName: col('error') },\n wakeAt: { type: 'Date', nullable: true, fieldName: col('wakeAt') },\n lockedBy: { type: 'string', nullable: true, fieldName: col('lockedBy') },\n lockedUntil: { type: 'Date', nullable: true, fieldName: col('lockedUntil') },\n recoveryAttempts: { type: 'integer', nullable: true, fieldName: col('recoveryAttempts') },\n tags: { type: 'json', nullable: true, fieldName: col('tags') },\n searchAttributes: { type: 'json', nullable: true, fieldName: col('searchAttributes') },\n createdAt: { type: 'Date', fieldName: col('createdAt') },\n updatedAt: { type: 'Date', fieldName: col('updatedAt') },\n },\n });\n\n const stepCheckpoints = new EntitySchema<StepCheckpointEntity>({\n class: StepCheckpointEntity,\n tableName: 'durable_step_checkpoints',\n properties: {\n runId: { type: 'string', primary: true, fieldName: col('runId') },\n seq: { type: 'integer', primary: true, fieldName: col('seq') },\n name: { type: 'string', fieldName: col('name') },\n kind: { type: 'string', fieldName: col('kind') },\n stepId: { type: 'string', fieldName: col('stepId') },\n status: { type: 'string', fieldName: col('status') },\n input: { type: 'json', nullable: true, fieldName: col('input') },\n output: { type: 'json', nullable: true, fieldName: col('output') },\n error: { type: 'json', nullable: true, fieldName: col('error') },\n events: { type: 'json', nullable: true, fieldName: col('events') },\n attempts: { type: 'integer', fieldName: col('attempts') },\n workerGroup: { type: 'string', nullable: true, fieldName: col('workerGroup') },\n wakeAt: { type: 'Date', nullable: true, fieldName: col('wakeAt') },\n enqueuedAt: { type: 'Date', nullable: true, fieldName: col('enqueuedAt') },\n startedAt: { type: 'Date', fieldName: col('startedAt') },\n finishedAt: { type: 'Date', fieldName: col('finishedAt') },\n },\n });\n\n const runAttributes = new EntitySchema<RunAttributeEntity>({\n class: RunAttributeEntity,\n tableName: 'durable_run_attributes',\n properties: {\n runId: { type: 'string', primary: true, fieldName: col('runId') },\n key: { type: 'string', primary: true, fieldName: col('key') },\n strValue: { type: 'string', nullable: true, fieldName: col('strValue') },\n // `float`/`double` is portable across SQLite/MySQL/Postgres for numeric range scans.\n numValue: { type: 'float', nullable: true, fieldName: col('numValue') },\n },\n });\n\n const signalWaiters = new EntitySchema<SignalWaiterEntity>({\n class: SignalWaiterEntity,\n tableName: 'durable_signal_waiters',\n properties: {\n token: { type: 'string', primary: true, fieldName: col('token') },\n runId: { type: 'string', fieldName: col('runId') },\n seq: { type: 'integer', fieldName: col('seq') },\n },\n });\n\n const bufferedSignals = new EntitySchema<BufferedSignalEntity>({\n class: BufferedSignalEntity,\n tableName: 'durable_buffered_signals',\n properties: {\n id: { type: 'integer', primary: true, autoincrement: true, fieldName: col('id') },\n token: { type: 'string', index: true, fieldName: col('token') },\n payload: { type: 'json', nullable: true, fieldName: col('payload') },\n },\n });\n\n return [workflowRuns, stepCheckpoints, runAttributes, signalWaiters, bufferedSignals];\n}\n\n/** Durable entity schemas with the canonical `'snake_case'` column names. */\nexport const ENTITIES = durableEntities();\n","import {\n type AttributeFilter,\n type RunQuery,\n type SignalWaiter,\n type StateStore,\n type StepCheckpoint,\n type StepError,\n type StepEvent,\n type WorkflowRun,\n attributeColumnFor,\n attributeOperand,\n normalizeAttributeRows,\n sqlComparator,\n} from '@dudousxd/nestjs-durable-core';\nimport type { EntityManager, MikroORM } from '@mikro-orm/core';\n\n/** Minimal structural surface of the SQL EntityManager's QueryBuilder (from `@mikro-orm/knex`),\n * typed here so the adapter needn't add a hard dependency on the knex types — a real SQL-driver EM\n * satisfies it at runtime. */\ninterface DurableQueryBuilder<T> {\n where(cond: Record<string, unknown>): DurableQueryBuilder<T>;\n andWhere(cond: string): DurableQueryBuilder<T>;\n orderBy(cond: Record<string, unknown>): DurableQueryBuilder<T>;\n limit(n: number): DurableQueryBuilder<T>;\n offset(n: number): DurableQueryBuilder<T>;\n getResultList(): Promise<T[]>;\n}\ntype SqlEm = EntityManager & {\n createQueryBuilder<T>(entity: unknown, alias: string): DurableQueryBuilder<T>;\n};\n\n/** Resolved side-table column names (per the active naming strategy) for the raw EXISTS pushdown. */\ninterface AttributeColumns {\n table: string;\n /** Side-table FK column (the run id on `durable_run_attributes`). */\n runId: string;\n /** Run table PK column (the `id` on `durable_workflow_runs`) used for the outer correlation. */\n runPk: string;\n key: string;\n strValue: string;\n numValue: string;\n}\nimport {\n BufferedSignalEntity,\n RunAttributeEntity,\n SignalWaiterEntity,\n StepCheckpointEntity,\n WorkflowRunEntity,\n} from './entities';\nimport { ensureMikroOrmDurableSchema } from './schema';\n\n/**\n * MikroORM-backed `StateStore`. Works on any MikroORM driver — Postgres, MySQL, SQLite (tested);\n * timestamps and `wakeAt` use native datetime columns. Each operation runs on a forked\n * EntityManager so it owns its unit of work.\n */\nexport class MikroOrmStateStore implements StateStore {\n constructor(private readonly orm: MikroORM) {}\n\n async ensureSchema(): Promise<void> {\n await ensureMikroOrmDurableSchema(this.orm);\n }\n\n async createRun(run: WorkflowRun): Promise<void> {\n const em = this.orm.em.fork();\n em.create(WorkflowRunEntity, toRunEntity(run));\n await em.flush();\n await this.reindexAttributes(run.id, run.searchAttributes);\n }\n\n async updateRun(runId: string, patch: Partial<WorkflowRun>): Promise<void> {\n const em = this.orm.em.fork();\n const entity = await em.findOneOrFail(WorkflowRunEntity, { id: runId });\n Object.assign(entity, toRunEntity({ ...fromRunEntity(entity), ...patch } as WorkflowRun));\n await em.flush();\n // Keep the side-table in step with the run's attributes whenever they're patched.\n if ('searchAttributes' in patch) await this.reindexAttributes(runId, patch.searchAttributes);\n }\n\n /** Rewrite a run's normalized attribute rows: delete the old set, insert the current one. Mirrors\n * the in-memory store's reindex so the side-table always reflects the run's live searchAttributes. */\n private async reindexAttributes(\n runId: string,\n attributes: WorkflowRun['searchAttributes'],\n forked?: EntityManager,\n ): Promise<void> {\n const em = forked ?? this.orm.em.fork();\n await em.nativeDelete(RunAttributeEntity, { runId });\n const rows = normalizeAttributeRows(runId, attributes);\n if (rows.length) await em.insertMany(RunAttributeEntity, rows);\n }\n\n async getRun(runId: string): Promise<WorkflowRun | null> {\n const em = this.orm.em.fork();\n const entity = await em.findOne(WorkflowRunEntity, { id: runId });\n return entity ? fromRunEntity(entity) : null;\n }\n\n async getCheckpoint(runId: string, seq: number): Promise<StepCheckpoint | null> {\n const em = this.orm.em.fork();\n const entity = await em.findOne(StepCheckpointEntity, { runId, seq });\n return entity ? fromCheckpointEntity(entity) : null;\n }\n\n async saveCheckpoint(checkpoint: StepCheckpoint): Promise<void> {\n const em = this.orm.em.fork();\n await em.upsert(StepCheckpointEntity, toCheckpointEntity(checkpoint));\n await em.flush();\n }\n\n async transaction<T>(\n work: (tx: {\n raw: unknown;\n saveCheckpoint: (cp: StepCheckpoint) => Promise<void>;\n }) => Promise<T>,\n ): Promise<T> {\n return this.orm.em.fork().transactional(async (em) =>\n work({\n raw: em,\n saveCheckpoint: async (cp) => {\n await em.upsert(StepCheckpointEntity, toCheckpointEntity(cp));\n },\n }),\n );\n }\n\n async listIncompleteRuns(): Promise<WorkflowRun[]> {\n const em = this.orm.em.fork();\n const rows = await em.find(WorkflowRunEntity, { status: 'running' });\n return rows.map(fromRunEntity);\n }\n\n async listPendingRuns(limit: number): Promise<WorkflowRun[]> {\n const em = this.orm.em.fork();\n const rows = await em.find(\n WorkflowRunEntity,\n { status: 'pending' },\n { orderBy: { createdAt: 'asc' }, limit }, // FIFO dispatch\n );\n return rows.map(fromRunEntity);\n }\n\n async listDueTimers(nowMs: number): Promise<WorkflowRun[]> {\n const em = this.orm.em.fork();\n const rows = await em.find(WorkflowRunEntity, {\n status: 'suspended',\n wakeAt: { $ne: null, $lte: new Date(nowMs) },\n });\n return rows.map(fromRunEntity);\n }\n\n async tryLockRun(\n runId: string,\n owner: string,\n leaseUntilMs: number,\n nowMs: number,\n ): Promise<boolean> {\n const em = this.orm.em.fork();\n const affected = await em.nativeUpdate(\n WorkflowRunEntity,\n { id: runId, $or: [{ lockedUntil: null }, { lockedUntil: { $lte: new Date(nowMs) } }] },\n { lockedBy: owner, lockedUntil: new Date(leaseUntilMs) },\n );\n return affected === 1;\n }\n\n async releaseRunLock(runId: string): Promise<void> {\n const em = this.orm.em.fork();\n await em.nativeUpdate(WorkflowRunEntity, { id: runId }, { lockedBy: null, lockedUntil: null });\n }\n\n async renewRunLock(runId: string, owner: string, leaseUntilMs: number): Promise<boolean> {\n const em = this.orm.em.fork();\n const affected = await em.nativeUpdate(\n WorkflowRunEntity,\n { id: runId, lockedBy: owner },\n { lockedUntil: new Date(leaseUntilMs) },\n );\n return affected === 1;\n }\n\n async listRuns(query: RunQuery): Promise<WorkflowRun[]> {\n const em = this.orm.em.fork();\n const where: Record<string, unknown> = {};\n if (query.workflow) where.workflow = query.workflow;\n // `status IN (...)`; an empty set matches nothing (mirrors the in-memory store). When both the\n // single `status` and `statuses` are set, AND them so the narrower set wins.\n if (query.status && query.statuses) {\n where.$and = [{ status: query.status }, { status: { $in: query.statuses } }];\n } else if (query.status) {\n where.status = query.status;\n } else if (query.statuses) {\n where.status = { $in: query.statuses };\n }\n const orderBy = { createdAt: 'desc' as const }; // newest first — recent runs on top in the dashboard\n // `tags`/attributes need raw SQL pushed through the QueryBuilder:\n // - tag: `tags` is a JSON column (native json/jsonb on PG/MySQL), and MikroORM JSON-serializes a\n // `{ $like }` operand (wrapping/escaping the LIKE pattern) so a plain where corrupts it to no\n // matches. A raw LIKE on the column-as-text matches the quoted token so `etl` doesn't match\n // `etl-foo`. Postgres `jsonb` rejects `LIKE` directly, so cast to text per dialect.\n // - attributes: each filter becomes a raw EXISTS against the normalized side-table, so the DB\n // filters AND paginates — no full scan + in-process filter (ANDed: one EXISTS per filter).\n // Use a QueryBuilder with a fixed root alias `r` so the raw correlations are stable across drivers.\n if (query.tag || query.attributes?.length) {\n const quote = this.idQuote(em);\n const cols = this.attributeColumns(em);\n const qb = (em as SqlEm)\n .createQueryBuilder<WorkflowRunEntity>(WorkflowRunEntity, 'r')\n .where(where)\n .orderBy(orderBy);\n if (query.tag) {\n const tagsCol = this.tagsColumn(em);\n const pattern = `%\"${query.tag.replace(/'/g, \"''\")}\"%`;\n const colExpr = this.jsonAsText(em, `${quote('r')}.${quote(tagsCol)}`);\n qb.andWhere(`${colExpr} LIKE '${pattern}'`);\n }\n for (const f of query.attributes ?? []) {\n qb.andWhere(this.attributeExistsSql(f, quote, 'r', cols));\n }\n if (query.limit != null) qb.limit(query.limit);\n if (query.offset != null) qb.offset(query.offset);\n const rows = await qb.getResultList();\n return rows.map(fromRunEntity);\n }\n const rows = await em.find(WorkflowRunEntity, where, {\n ...(query.limit != null ? { limit: query.limit } : {}),\n ...(query.offset != null ? { offset: query.offset } : {}),\n orderBy,\n });\n return rows.map(fromRunEntity);\n }\n\n /** One attribute predicate as a raw EXISTS subquery on the side-table, correlated to the outer run\n * alias. `<>` (ne) also excludes runs where the attribute is absent (missing-key-never-matches):\n * EXISTS already requires a present row, so EXISTS(... <> ...) is exactly ne-with-present. Numeric\n * operands compare the num column, everything else the str column. Identifiers are quoted per\n * driver and operands are inlined as literals (string operands are escaped by doubling quotes). */\n private attributeExistsSql(\n f: AttributeFilter,\n quote: (id: string) => string,\n alias: string,\n cols: AttributeColumns,\n ): string {\n const col = attributeColumnFor(f) === 'numValue' ? cols.numValue : cols.strValue;\n const cmp = sqlComparator(f.op);\n const operand = attributeOperand(f);\n const literal =\n typeof operand === 'number' ? String(operand) : `'${String(operand).replace(/'/g, \"''\")}'`;\n const a = quote(cols.table);\n const sub = quote('a');\n const outerId = `${quote(alias)}.${quote(cols.runPk)}`; // run PK column on the outer alias\n return `EXISTS (SELECT 1 FROM ${a} ${sub} WHERE ${sub}.${quote(cols.runId)} = ${outerId} AND ${sub}.${quote(cols.key)} = '${f.key.replace(/'/g, \"''\")}' AND ${sub}.${quote(col)} ${cmp} ${literal})`;\n }\n\n /** Resolve the side-table's actual column names from MikroORM metadata, so the raw EXISTS matches\n * the active naming strategy (underscore vs camelCase) rather than guessing. The run PK column is\n * reused for BOTH the outer correlation and the side-table FK (they share the same fieldName). */\n private attributeColumns(em: EntityManager): AttributeColumns {\n const meta = em.getMetadata().get(RunAttributeEntity);\n const field = (prop: string) =>\n meta.props.find((p) => p.name === prop)?.fieldNames?.[0] ?? prop;\n const runMeta = em.getMetadata().get(WorkflowRunEntity);\n const runPk = runMeta.properties.id?.fieldNames?.[0] ?? 'id';\n return {\n table: meta.tableName,\n runId: field('runId'),\n runPk,\n key: field('key'),\n strValue: field('strValue'),\n numValue: field('numValue'),\n };\n }\n\n /** Resolve the `tags` column name from metadata (per the active naming strategy), for the raw LIKE. */\n private tagsColumn(em: EntityManager): string {\n const runMeta = em.getMetadata().get(WorkflowRunEntity);\n return runMeta.properties.tags?.fieldNames?.[0] ?? 'tags';\n }\n\n /** Wrap a JSON column reference so it can be `LIKE`d as text. Postgres `jsonb`/`json` rejects `LIKE`\n * directly (`operator does not exist: jsonb ~~ unknown`) — cast to `text`; MySQL JSON needs an\n * explicit `CHAR` cast; SQLite stores JSON as text already, so no cast. */\n private jsonAsText(em: EntityManager, colRef: string): string {\n const platform = String(em.getPlatform().constructor.name).toLowerCase();\n if (platform.includes('postgre')) return `${colRef}::text`;\n if (platform.includes('mysql') || platform.includes('mariadb'))\n return `CAST(${colRef} AS CHAR)`;\n return colRef;\n }\n\n /** Quote an identifier per the active SQL driver (MySQL/MariaDB backtick, others double-quote). */\n private idQuote(em: EntityManager): (id: string) => string {\n const platform = String(em.getPlatform().constructor.name).toLowerCase();\n const isMysql = platform.includes('mysql') || platform.includes('mariadb');\n const ch = isMysql ? '`' : '\"';\n return (id: string) => `${ch}${id}${ch}`;\n }\n\n async listCheckpoints(runId: string): Promise<StepCheckpoint[]> {\n const em = this.orm.em.fork();\n const rows = await em.find(StepCheckpointEntity, { runId }, { orderBy: { seq: 'asc' } });\n return rows.map(fromCheckpointEntity);\n }\n\n async getLatestCheckpointByName(\n runId: string,\n name: string,\n ): Promise<StepCheckpoint | undefined> {\n const em = this.orm.em.fork();\n const entity = await em.findOne(\n StepCheckpointEntity,\n { runId, name },\n { orderBy: { seq: 'desc' } },\n );\n return entity ? fromCheckpointEntity(entity) : undefined;\n }\n\n async listCheckpointsByNamePrefix(runId: string, prefixes: string[]): Promise<StepCheckpoint[]> {\n if (prefixes.length === 0) return [];\n const em = this.orm.em.fork();\n const rows = await em.find(\n StepCheckpointEntity,\n { runId, $or: prefixes.map((p) => ({ name: { $like: `${p}%` } })) },\n { orderBy: { seq: 'asc' } },\n );\n return rows.map(fromCheckpointEntity);\n }\n\n async putSignalWaiter(waiter: SignalWaiter): Promise<void> {\n const em = this.orm.em.fork();\n await em.upsert(SignalWaiterEntity, { ...waiter });\n await em.flush();\n }\n\n async takeSignalWaiter(token: string): Promise<SignalWaiter | null> {\n const em = this.orm.em.fork();\n const entity = await em.findOne(SignalWaiterEntity, { token });\n if (!entity) return null;\n const waiter: SignalWaiter = { token: entity.token, runId: entity.runId, seq: entity.seq };\n await em.remove(entity).flush();\n return waiter;\n }\n\n async listSignalWaiters(prefix: string): Promise<SignalWaiter[]> {\n const em = this.orm.em.fork();\n const rows = await em.find(SignalWaiterEntity, { token: { $like: `${prefix}%` } });\n return rows.map((e) => ({ token: e.token, runId: e.runId, seq: e.seq }));\n }\n\n async bufferSignal(token: string, payload: unknown): Promise<void> {\n const em = this.orm.em.fork();\n const e = new BufferedSignalEntity();\n e.token = token;\n e.payload = payload ?? null;\n em.persist(e);\n await em.flush();\n }\n\n async takeBufferedSignal(token: string): Promise<{ payload: unknown } | null> {\n const em = this.orm.em.fork();\n const entity = await em.findOne(BufferedSignalEntity, { token }, { orderBy: { id: 'asc' } });\n if (!entity) return null;\n const payload = entity.payload ?? undefined;\n await em.remove(entity).flush();\n return { payload };\n }\n}\n\nfunction toRunEntity(run: WorkflowRun): WorkflowRunEntity {\n const e = new WorkflowRunEntity();\n e.id = run.id;\n e.workflow = run.workflow;\n e.workflowVersion = run.workflowVersion;\n e.status = run.status;\n e.input = run.input ?? null;\n e.output = run.output ?? null;\n e.error = run.error ?? null;\n if (run.wakeAt != null) e.wakeAt = new Date(run.wakeAt);\n if (run.lockedBy !== undefined) e.lockedBy = run.lockedBy;\n if (run.lockedUntil != null) e.lockedUntil = new Date(run.lockedUntil);\n if (run.recoveryAttempts !== undefined) e.recoveryAttempts = run.recoveryAttempts;\n e.tags = run.tags ?? null;\n e.searchAttributes = run.searchAttributes ?? null;\n e.createdAt = run.createdAt;\n e.updatedAt = run.updatedAt;\n return e;\n}\n\nfunction fromRunEntity(e: WorkflowRunEntity): WorkflowRun {\n return {\n id: e.id,\n workflow: e.workflow,\n workflowVersion: e.workflowVersion,\n status: e.status,\n input: e.input ?? undefined,\n output: e.output ?? undefined,\n error: (e.error ?? undefined) as StepError | undefined,\n wakeAt: e.wakeAt?.getTime(),\n lockedBy: e.lockedBy ?? undefined,\n lockedUntil: e.lockedUntil?.getTime(),\n recoveryAttempts: e.recoveryAttempts ?? undefined,\n tags: e.tags ?? undefined,\n searchAttributes: e.searchAttributes ?? undefined,\n createdAt: e.createdAt,\n updatedAt: e.updatedAt,\n };\n}\n\nfunction toCheckpointEntity(cp: StepCheckpoint): StepCheckpointEntity {\n const e = new StepCheckpointEntity();\n e.runId = cp.runId;\n e.seq = cp.seq;\n e.name = cp.name;\n e.kind = cp.kind;\n e.stepId = cp.stepId;\n e.status = cp.status;\n e.input = cp.input ?? null;\n e.output = cp.output ?? null;\n e.error = cp.error ?? null;\n e.events = cp.events ?? null;\n e.attempts = cp.attempts;\n if (cp.workerGroup !== undefined) e.workerGroup = cp.workerGroup;\n if (cp.wakeAt != null) e.wakeAt = new Date(cp.wakeAt);\n e.enqueuedAt = cp.enqueuedAt;\n e.startedAt = cp.startedAt;\n e.finishedAt = cp.finishedAt;\n return e;\n}\n\nfunction fromCheckpointEntity(e: StepCheckpointEntity): StepCheckpoint {\n return {\n runId: e.runId,\n seq: e.seq,\n name: e.name,\n kind: e.kind,\n stepId: e.stepId,\n status: e.status,\n input: e.input ?? undefined,\n output: e.output ?? undefined,\n error: (e.error ?? undefined) as StepError | undefined,\n events: (e.events ?? undefined) as StepEvent[] | undefined,\n attempts: e.attempts,\n workerGroup: e.workerGroup ?? undefined,\n wakeAt: e.wakeAt?.getTime(),\n enqueuedAt: e.enqueuedAt ?? e.startedAt,\n startedAt: e.startedAt,\n finishedAt: e.finishedAt,\n };\n}\n","import type { MikroORM } from '@mikro-orm/core';\n\n/**\n * Idempotently create/extend the durable tables (additive, never drops). Safe to run on every\n * boot (auto-schema) and the function to call from a MikroORM migration when you disable\n * auto-schema:\n *\n * ```ts\n * export class AddDurableTables extends Migration {\n * async up() { await ensureMikroOrmDurableSchema(this.getEntityManager().getOrm()); }\n * }\n * ```\n */\nexport async function ensureMikroOrmDurableSchema(orm: MikroORM): Promise<void> {\n await orm.schema.update({ safe: true });\n}\n"],"mappings":"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","names":["EntitySchema","snakeCase","property","replace","c","toLowerCase","columnNamer","naming","WorkflowRunEntity","id","workflow","workflowVersion","status","input","output","error","wakeAt","lockedBy","lockedUntil","recoveryAttempts","tags","searchAttributes","createdAt","updatedAt","StepCheckpointEntity","runId","seq","name","kind","stepId","events","attempts","workerGroup","enqueuedAt","startedAt","finishedAt","RunAttributeEntity","key","strValue","numValue","SignalWaiterEntity","token","BufferedSignalEntity","payload","durableEntities","options","col","workflowRuns","EntitySchema","class","tableName","properties","type","primary","fieldName","nullable","stepCheckpoints","runAttributes","signalWaiters","bufferedSignals","autoincrement","index","ENTITIES","attributeColumnFor","attributeOperand","normalizeAttributeRows","sqlComparator","ensureMikroOrmDurableSchema","orm","schema","update","safe","MikroOrmStateStore","orm","ensureSchema","ensureMikroOrmDurableSchema","createRun","run","em","fork","create","WorkflowRunEntity","toRunEntity","flush","reindexAttributes","id","searchAttributes","updateRun","runId","patch","entity","findOneOrFail","Object","assign","fromRunEntity","attributes","forked","nativeDelete","RunAttributeEntity","rows","normalizeAttributeRows","length","insertMany","getRun","findOne","getCheckpoint","seq","StepCheckpointEntity","fromCheckpointEntity","saveCheckpoint","checkpoint","upsert","toCheckpointEntity","transaction","work","transactional","raw","cp","listIncompleteRuns","find","status","map","listPendingRuns","limit","orderBy","createdAt","listDueTimers","nowMs","wakeAt","$ne","$lte","Date","tryLockRun","owner","leaseUntilMs","affected","nativeUpdate","$or","lockedUntil","lockedBy","releaseRunLock","renewRunLock","listRuns","query","where","workflow","statuses","$and","$in","tag","quote","idQuote","cols","attributeColumns","qb","createQueryBuilder","tagsCol","tagsColumn","pattern","replace","colExpr","jsonAsText","andWhere","f","attributeExistsSql","offset","getResultList","alias","col","attributeColumnFor","numValue","strValue","cmp","sqlComparator","op","operand","attributeOperand","literal","String","a","table","sub","outerId","runPk","key","meta","getMetadata","get","field","prop","props","p","name","fieldNames","runMeta","properties","tableName","tags","colRef","platform","getPlatform","toLowerCase","includes","isMysql","ch","listCheckpoints","getLatestCheckpointByName","undefined","listCheckpointsByNamePrefix","prefixes","$like","putSignalWaiter","waiter","SignalWaiterEntity","takeSignalWaiter","token","remove","listSignalWaiters","prefix","e","bufferSignal","payload","BufferedSignalEntity","persist","takeBufferedSignal","workflowVersion","input","output","error","recoveryAttempts","updatedAt","getTime","kind","stepId","events","attempts","workerGroup","enqueuedAt","startedAt","finishedAt"]}
1
+ {"version":3,"sources":["../src/entities.ts","../src/mikro-orm-state-store.ts","../src/schema.ts"],"sourcesContent":["import type { RunStatus, StepKind } from '@dudousxd/nestjs-durable-core';\nimport { EntitySchema } from '@mikro-orm/core';\n\n/**\n * How property names map to physical column names. The durable tables are adapter-agnostic: a run\n * written by one store adapter must be readable by another, so every adapter has to agree on the\n * physical column names. The default is `'snake_case'` (the canonical, matched by the TypeORM,\n * Prisma and Drizzle adapters). `'preserve'` keeps the camelCase property name verbatim (what the\n * old TypeORM/Prisma adapters produced before they were pinned). A function lets you supply any\n * custom mapping.\n *\n * The choice is pinned EXPLICITLY onto the entity schema rather than left to the host ORM's naming\n * strategy — depending on the host strategy is what silently diverged the adapters and broke a store\n * swap against an existing table.\n */\nexport type DurableColumnNaming = 'snake_case' | 'preserve' | ((property: string) => string);\n\nfunction snakeCase(property: string): string {\n return property.replace(/[A-Z]/g, (c) => `_${c.toLowerCase()}`);\n}\n\nfunction columnNamer(naming: DurableColumnNaming): (property: string) => string {\n if (naming === 'snake_case') return snakeCase;\n if (naming === 'preserve') return (property) => property;\n return naming;\n}\n\n// Plain classes (no decorators): the schema/column mapping lives on the EntitySchema built by\n// `durableEntities`, so the same class can be registered under different column names. The store\n// still references these classes for `em.create`/`getMetadata`.\n\nexport class WorkflowRunEntity {\n id!: string;\n workflow!: string;\n workflowVersion!: string;\n status!: RunStatus;\n input?: unknown;\n output?: unknown;\n error?: unknown;\n wakeAt?: Date;\n lockedBy?: string;\n lockedUntil?: Date;\n recoveryAttempts?: number;\n tags?: string[] | null;\n searchAttributes?: Record<string, string | number | boolean> | null;\n createdAt!: Date;\n updatedAt!: Date;\n}\n\nexport class StepCheckpointEntity {\n runId!: string;\n seq!: number;\n name!: string;\n kind!: StepKind;\n stepId!: string;\n status!: 'pending' | 'running' | 'completed' | 'failed';\n input?: unknown;\n output?: unknown;\n error?: unknown;\n events?: unknown;\n attempts!: number;\n workerGroup?: string;\n wakeAt?: Date;\n enqueuedAt?: Date;\n startedAt!: Date;\n finishedAt!: Date;\n}\n\n/**\n * Normalized side-table for search attributes: one row per (run, key), so range/equality predicates\n * push DOWN into SQL (an EXISTS join indexed on `(key, numValue)` / `(key, strValue)`) instead of a\n * coarse scan + in-process filter. Maintained on every createRun/updateRun. Numbers land in\n * `numValue`, strings/booleans in `strValue` (booleans as \"true\"/\"false\"); see normalizeAttributeRows.\n */\nexport class RunAttributeEntity {\n runId!: string;\n key!: string;\n strValue?: string | null;\n numValue?: number | null;\n}\n\nexport class SignalWaiterEntity {\n token!: string;\n runId!: string;\n seq!: number;\n}\n\nexport class BufferedSignalEntity {\n id!: number;\n token!: string;\n payload?: unknown;\n}\n\n/**\n * Build the durable MikroORM entity schemas with column names pinned per `naming` (default\n * `'snake_case'`). Register the result in your MikroORM config / `MikroOrmModule.forFeature`.\n *\n * ```ts\n * entities: durableEntities({ naming: 'snake_case' })\n * ```\n */\nexport function durableEntities(options: { naming?: DurableColumnNaming } = {}): EntitySchema[] {\n const col = columnNamer(options.naming ?? 'snake_case');\n\n const workflowRuns = new EntitySchema<WorkflowRunEntity>({\n class: WorkflowRunEntity,\n tableName: 'durable_workflow_runs',\n properties: {\n id: { type: 'string', primary: true, fieldName: col('id') },\n workflow: { type: 'string', fieldName: col('workflow') },\n workflowVersion: { type: 'string', fieldName: col('workflowVersion') },\n status: { type: 'string', fieldName: col('status') },\n input: { type: 'json', nullable: true, fieldName: col('input') },\n output: { type: 'json', nullable: true, fieldName: col('output') },\n error: { type: 'json', nullable: true, fieldName: col('error') },\n wakeAt: { type: 'Date', nullable: true, fieldName: col('wakeAt') },\n lockedBy: { type: 'string', nullable: true, fieldName: col('lockedBy') },\n lockedUntil: { type: 'Date', nullable: true, fieldName: col('lockedUntil') },\n recoveryAttempts: { type: 'integer', nullable: true, fieldName: col('recoveryAttempts') },\n tags: { type: 'json', nullable: true, fieldName: col('tags') },\n searchAttributes: { type: 'json', nullable: true, fieldName: col('searchAttributes') },\n createdAt: { type: 'Date', fieldName: col('createdAt') },\n updatedAt: { type: 'Date', fieldName: col('updatedAt') },\n },\n });\n\n const stepCheckpoints = new EntitySchema<StepCheckpointEntity>({\n class: StepCheckpointEntity,\n tableName: 'durable_step_checkpoints',\n properties: {\n runId: { type: 'string', primary: true, fieldName: col('runId') },\n seq: { type: 'integer', primary: true, fieldName: col('seq') },\n name: { type: 'string', fieldName: col('name') },\n kind: { type: 'string', fieldName: col('kind') },\n stepId: { type: 'string', fieldName: col('stepId') },\n status: { type: 'string', fieldName: col('status') },\n input: { type: 'json', nullable: true, fieldName: col('input') },\n output: { type: 'json', nullable: true, fieldName: col('output') },\n error: { type: 'json', nullable: true, fieldName: col('error') },\n events: { type: 'json', nullable: true, fieldName: col('events') },\n attempts: { type: 'integer', fieldName: col('attempts') },\n workerGroup: { type: 'string', nullable: true, fieldName: col('workerGroup') },\n wakeAt: { type: 'Date', nullable: true, fieldName: col('wakeAt') },\n enqueuedAt: { type: 'Date', nullable: true, fieldName: col('enqueuedAt') },\n startedAt: { type: 'Date', fieldName: col('startedAt') },\n finishedAt: { type: 'Date', fieldName: col('finishedAt') },\n },\n });\n\n const runAttributes = new EntitySchema<RunAttributeEntity>({\n class: RunAttributeEntity,\n tableName: 'durable_run_attributes',\n properties: {\n runId: { type: 'string', primary: true, fieldName: col('runId') },\n key: { type: 'string', primary: true, fieldName: col('key') },\n strValue: { type: 'string', nullable: true, fieldName: col('strValue') },\n // `float`/`double` is portable across SQLite/MySQL/Postgres for numeric range scans.\n numValue: { type: 'float', nullable: true, fieldName: col('numValue') },\n },\n });\n\n const signalWaiters = new EntitySchema<SignalWaiterEntity>({\n class: SignalWaiterEntity,\n tableName: 'durable_signal_waiters',\n properties: {\n token: { type: 'string', primary: true, fieldName: col('token') },\n runId: { type: 'string', fieldName: col('runId') },\n seq: { type: 'integer', fieldName: col('seq') },\n },\n });\n\n const bufferedSignals = new EntitySchema<BufferedSignalEntity>({\n class: BufferedSignalEntity,\n tableName: 'durable_buffered_signals',\n properties: {\n id: { type: 'integer', primary: true, autoincrement: true, fieldName: col('id') },\n token: { type: 'string', index: true, fieldName: col('token') },\n payload: { type: 'json', nullable: true, fieldName: col('payload') },\n },\n });\n\n return [workflowRuns, stepCheckpoints, runAttributes, signalWaiters, bufferedSignals];\n}\n\n/** Durable entity schemas with the canonical `'snake_case'` column names. */\nexport const ENTITIES = durableEntities();\n","import {\n type AttributeFilter,\n type RunQuery,\n type SignalWaiter,\n type StateStore,\n type StepCheckpoint,\n type StepError,\n type StepEvent,\n type WorkflowRun,\n attributeColumnFor,\n attributeOperand,\n normalizeAttributeRows,\n sqlComparator,\n} from '@dudousxd/nestjs-durable-core';\nimport type { EntityManager, MikroORM } from '@mikro-orm/core';\n\n/** Minimal structural surface of the SQL EntityManager's QueryBuilder (from `@mikro-orm/knex`),\n * typed here so the adapter needn't add a hard dependency on the knex types — a real SQL-driver EM\n * satisfies it at runtime. */\ninterface DurableQueryBuilder<T> {\n where(cond: Record<string, unknown>): DurableQueryBuilder<T>;\n andWhere(cond: string): DurableQueryBuilder<T>;\n orderBy(cond: Record<string, unknown>): DurableQueryBuilder<T>;\n limit(n: number): DurableQueryBuilder<T>;\n offset(n: number): DurableQueryBuilder<T>;\n getResultList(): Promise<T[]>;\n}\ntype SqlEm = EntityManager & {\n createQueryBuilder<T>(entity: unknown, alias: string): DurableQueryBuilder<T>;\n};\n\n/** Resolved side-table column names (per the active naming strategy) for the raw EXISTS pushdown. */\ninterface AttributeColumns {\n table: string;\n /** Side-table FK column (the run id on `durable_run_attributes`). */\n runId: string;\n /** Run table PK column (the `id` on `durable_workflow_runs`) used for the outer correlation. */\n runPk: string;\n key: string;\n strValue: string;\n numValue: string;\n}\nimport {\n BufferedSignalEntity,\n RunAttributeEntity,\n SignalWaiterEntity,\n StepCheckpointEntity,\n WorkflowRunEntity,\n} from './entities';\nimport { ensureMikroOrmDurableSchema } from './schema';\n\n/**\n * MikroORM-backed `StateStore`. Works on any MikroORM driver — Postgres, MySQL, SQLite (tested);\n * timestamps and `wakeAt` use native datetime columns. Each operation runs on a forked\n * EntityManager so it owns its unit of work.\n */\nexport class MikroOrmStateStore implements StateStore {\n constructor(private readonly orm: MikroORM) {}\n\n async ensureSchema(): Promise<void> {\n await ensureMikroOrmDurableSchema(this.orm);\n }\n\n async createRun(run: WorkflowRun): Promise<void> {\n const em = this.orm.em.fork();\n em.create(WorkflowRunEntity, toRunEntity(run));\n await em.flush();\n await this.reindexAttributes(run.id, run.searchAttributes);\n }\n\n async updateRun(runId: string, patch: Partial<WorkflowRun>): Promise<void> {\n const em = this.orm.em.fork();\n const entity = await em.findOneOrFail(WorkflowRunEntity, { id: runId });\n Object.assign(entity, toRunEntity({ ...fromRunEntity(entity), ...patch } as WorkflowRun));\n await em.flush();\n // Keep the side-table in step with the run's attributes whenever they're patched.\n if ('searchAttributes' in patch) await this.reindexAttributes(runId, patch.searchAttributes);\n }\n\n /** Rewrite a run's normalized attribute rows: delete the old set, insert the current one. Mirrors\n * the in-memory store's reindex so the side-table always reflects the run's live searchAttributes. */\n private async reindexAttributes(\n runId: string,\n attributes: WorkflowRun['searchAttributes'],\n forked?: EntityManager,\n ): Promise<void> {\n const em = forked ?? this.orm.em.fork();\n await em.nativeDelete(RunAttributeEntity, { runId });\n const rows = normalizeAttributeRows(runId, attributes);\n if (rows.length) await em.insertMany(RunAttributeEntity, rows);\n }\n\n async getRun(runId: string): Promise<WorkflowRun | null> {\n const em = this.orm.em.fork();\n const entity = await em.findOne(WorkflowRunEntity, { id: runId });\n return entity ? fromRunEntity(entity) : null;\n }\n\n async deleteRun(runId: string): Promise<void> {\n const em = this.orm.em.fork();\n // Children first, then the run row — checkpoints, signal waiters, and the normalized\n // attribute side-table, so nothing dangles after the run is gone.\n await em.nativeDelete(StepCheckpointEntity, { runId });\n await em.nativeDelete(SignalWaiterEntity, { runId });\n await em.nativeDelete(RunAttributeEntity, { runId });\n await em.nativeDelete(WorkflowRunEntity, { id: runId });\n }\n\n async getCheckpoint(runId: string, seq: number): Promise<StepCheckpoint | null> {\n const em = this.orm.em.fork();\n const entity = await em.findOne(StepCheckpointEntity, { runId, seq });\n return entity ? fromCheckpointEntity(entity) : null;\n }\n\n async saveCheckpoint(checkpoint: StepCheckpoint): Promise<void> {\n const em = this.orm.em.fork();\n await em.upsert(StepCheckpointEntity, toCheckpointEntity(checkpoint));\n await em.flush();\n }\n\n async transaction<T>(\n work: (tx: {\n raw: unknown;\n saveCheckpoint: (cp: StepCheckpoint) => Promise<void>;\n }) => Promise<T>,\n ): Promise<T> {\n return this.orm.em.fork().transactional(async (em) =>\n work({\n raw: em,\n saveCheckpoint: async (cp) => {\n await em.upsert(StepCheckpointEntity, toCheckpointEntity(cp));\n },\n }),\n );\n }\n\n async listIncompleteRuns(): Promise<WorkflowRun[]> {\n const em = this.orm.em.fork();\n const rows = await em.find(WorkflowRunEntity, { status: 'running' });\n return rows.map(fromRunEntity);\n }\n\n async listPendingRuns(limit: number): Promise<WorkflowRun[]> {\n const em = this.orm.em.fork();\n const rows = await em.find(\n WorkflowRunEntity,\n { status: 'pending' },\n { orderBy: { createdAt: 'asc' }, limit }, // FIFO dispatch\n );\n return rows.map(fromRunEntity);\n }\n\n async listDueTimers(nowMs: number): Promise<WorkflowRun[]> {\n const em = this.orm.em.fork();\n const rows = await em.find(WorkflowRunEntity, {\n status: 'suspended',\n wakeAt: { $ne: null, $lte: new Date(nowMs) },\n });\n return rows.map(fromRunEntity);\n }\n\n async tryLockRun(\n runId: string,\n owner: string,\n leaseUntilMs: number,\n nowMs: number,\n ): Promise<boolean> {\n const em = this.orm.em.fork();\n const affected = await em.nativeUpdate(\n WorkflowRunEntity,\n { id: runId, $or: [{ lockedUntil: null }, { lockedUntil: { $lte: new Date(nowMs) } }] },\n { lockedBy: owner, lockedUntil: new Date(leaseUntilMs) },\n );\n return affected === 1;\n }\n\n async releaseRunLock(runId: string): Promise<void> {\n const em = this.orm.em.fork();\n await em.nativeUpdate(WorkflowRunEntity, { id: runId }, { lockedBy: null, lockedUntil: null });\n }\n\n async renewRunLock(runId: string, owner: string, leaseUntilMs: number): Promise<boolean> {\n const em = this.orm.em.fork();\n const affected = await em.nativeUpdate(\n WorkflowRunEntity,\n { id: runId, lockedBy: owner },\n { lockedUntil: new Date(leaseUntilMs) },\n );\n return affected === 1;\n }\n\n async listRuns(query: RunQuery): Promise<WorkflowRun[]> {\n const em = this.orm.em.fork();\n const where: Record<string, unknown> = {};\n if (query.workflow) where.workflow = query.workflow;\n // `status IN (...)`; an empty set matches nothing (mirrors the in-memory store). When both the\n // single `status` and `statuses` are set, AND them so the narrower set wins.\n if (query.status && query.statuses) {\n where.$and = [{ status: query.status }, { status: { $in: query.statuses } }];\n } else if (query.status) {\n where.status = query.status;\n } else if (query.statuses) {\n where.status = { $in: query.statuses };\n }\n const orderBy = { createdAt: 'desc' as const }; // newest first — recent runs on top in the dashboard\n // `tags`/attributes need raw SQL pushed through the QueryBuilder:\n // - tag: `tags` is a JSON column (native json/jsonb on PG/MySQL), and MikroORM JSON-serializes a\n // `{ $like }` operand (wrapping/escaping the LIKE pattern) so a plain where corrupts it to no\n // matches. A raw LIKE on the column-as-text matches the quoted token so `etl` doesn't match\n // `etl-foo`. Postgres `jsonb` rejects `LIKE` directly, so cast to text per dialect.\n // - attributes: each filter becomes a raw EXISTS against the normalized side-table, so the DB\n // filters AND paginates — no full scan + in-process filter (ANDed: one EXISTS per filter).\n // Use a QueryBuilder with a fixed root alias `r` so the raw correlations are stable across drivers.\n if (query.tag || query.attributes?.length) {\n const quote = this.idQuote(em);\n const cols = this.attributeColumns(em);\n const qb = (em as SqlEm)\n .createQueryBuilder<WorkflowRunEntity>(WorkflowRunEntity, 'r')\n .where(where)\n .orderBy(orderBy);\n if (query.tag) {\n const tagsCol = this.tagsColumn(em);\n const pattern = `%\"${query.tag.replace(/'/g, \"''\")}\"%`;\n const colExpr = this.jsonAsText(em, `${quote('r')}.${quote(tagsCol)}`);\n qb.andWhere(`${colExpr} LIKE '${pattern}'`);\n }\n for (const f of query.attributes ?? []) {\n qb.andWhere(this.attributeExistsSql(f, quote, 'r', cols));\n }\n if (query.limit != null) qb.limit(query.limit);\n if (query.offset != null) qb.offset(query.offset);\n const rows = await qb.getResultList();\n return rows.map(fromRunEntity);\n }\n const rows = await em.find(WorkflowRunEntity, where, {\n ...(query.limit != null ? { limit: query.limit } : {}),\n ...(query.offset != null ? { offset: query.offset } : {}),\n orderBy,\n });\n return rows.map(fromRunEntity);\n }\n\n /** One attribute predicate as a raw EXISTS subquery on the side-table, correlated to the outer run\n * alias. `<>` (ne) also excludes runs where the attribute is absent (missing-key-never-matches):\n * EXISTS already requires a present row, so EXISTS(... <> ...) is exactly ne-with-present. Numeric\n * operands compare the num column, everything else the str column. Identifiers are quoted per\n * driver and operands are inlined as literals (string operands are escaped by doubling quotes). */\n private attributeExistsSql(\n f: AttributeFilter,\n quote: (id: string) => string,\n alias: string,\n cols: AttributeColumns,\n ): string {\n const col = attributeColumnFor(f) === 'numValue' ? cols.numValue : cols.strValue;\n const cmp = sqlComparator(f.op);\n const operand = attributeOperand(f);\n const literal =\n typeof operand === 'number' ? String(operand) : `'${String(operand).replace(/'/g, \"''\")}'`;\n const a = quote(cols.table);\n const sub = quote('a');\n const outerId = `${quote(alias)}.${quote(cols.runPk)}`; // run PK column on the outer alias\n return `EXISTS (SELECT 1 FROM ${a} ${sub} WHERE ${sub}.${quote(cols.runId)} = ${outerId} AND ${sub}.${quote(cols.key)} = '${f.key.replace(/'/g, \"''\")}' AND ${sub}.${quote(col)} ${cmp} ${literal})`;\n }\n\n /** Resolve the side-table's actual column names from MikroORM metadata, so the raw EXISTS matches\n * the active naming strategy (underscore vs camelCase) rather than guessing. The run PK column is\n * reused for BOTH the outer correlation and the side-table FK (they share the same fieldName). */\n private attributeColumns(em: EntityManager): AttributeColumns {\n const meta = em.getMetadata().get(RunAttributeEntity);\n const field = (prop: string) =>\n meta.props.find((p) => p.name === prop)?.fieldNames?.[0] ?? prop;\n const runMeta = em.getMetadata().get(WorkflowRunEntity);\n const runPk = runMeta.properties.id?.fieldNames?.[0] ?? 'id';\n return {\n table: meta.tableName,\n runId: field('runId'),\n runPk,\n key: field('key'),\n strValue: field('strValue'),\n numValue: field('numValue'),\n };\n }\n\n /** Resolve the `tags` column name from metadata (per the active naming strategy), for the raw LIKE. */\n private tagsColumn(em: EntityManager): string {\n const runMeta = em.getMetadata().get(WorkflowRunEntity);\n return runMeta.properties.tags?.fieldNames?.[0] ?? 'tags';\n }\n\n /** Wrap a JSON column reference so it can be `LIKE`d as text. Postgres `jsonb`/`json` rejects `LIKE`\n * directly (`operator does not exist: jsonb ~~ unknown`) — cast to `text`; MySQL JSON needs an\n * explicit `CHAR` cast; SQLite stores JSON as text already, so no cast. */\n private jsonAsText(em: EntityManager, colRef: string): string {\n const platform = String(em.getPlatform().constructor.name).toLowerCase();\n if (platform.includes('postgre')) return `${colRef}::text`;\n if (platform.includes('mysql') || platform.includes('mariadb'))\n return `CAST(${colRef} AS CHAR)`;\n return colRef;\n }\n\n /** Quote an identifier per the active SQL driver (MySQL/MariaDB backtick, others double-quote). */\n private idQuote(em: EntityManager): (id: string) => string {\n const platform = String(em.getPlatform().constructor.name).toLowerCase();\n const isMysql = platform.includes('mysql') || platform.includes('mariadb');\n const ch = isMysql ? '`' : '\"';\n return (id: string) => `${ch}${id}${ch}`;\n }\n\n async listCheckpoints(runId: string): Promise<StepCheckpoint[]> {\n const em = this.orm.em.fork();\n const rows = await em.find(StepCheckpointEntity, { runId }, { orderBy: { seq: 'asc' } });\n return rows.map(fromCheckpointEntity);\n }\n\n async getLatestCheckpointByName(\n runId: string,\n name: string,\n ): Promise<StepCheckpoint | undefined> {\n const em = this.orm.em.fork();\n const entity = await em.findOne(\n StepCheckpointEntity,\n { runId, name },\n { orderBy: { seq: 'desc' } },\n );\n return entity ? fromCheckpointEntity(entity) : undefined;\n }\n\n async listCheckpointsByNamePrefix(runId: string, prefixes: string[]): Promise<StepCheckpoint[]> {\n if (prefixes.length === 0) return [];\n const em = this.orm.em.fork();\n const rows = await em.find(\n StepCheckpointEntity,\n { runId, $or: prefixes.map((p) => ({ name: { $like: `${p}%` } })) },\n { orderBy: { seq: 'asc' } },\n );\n return rows.map(fromCheckpointEntity);\n }\n\n async putSignalWaiter(waiter: SignalWaiter): Promise<void> {\n const em = this.orm.em.fork();\n await em.upsert(SignalWaiterEntity, { ...waiter });\n await em.flush();\n }\n\n async takeSignalWaiter(token: string): Promise<SignalWaiter | null> {\n const em = this.orm.em.fork();\n const entity = await em.findOne(SignalWaiterEntity, { token });\n if (!entity) return null;\n const waiter: SignalWaiter = { token: entity.token, runId: entity.runId, seq: entity.seq };\n await em.remove(entity).flush();\n return waiter;\n }\n\n async listSignalWaiters(prefix: string): Promise<SignalWaiter[]> {\n const em = this.orm.em.fork();\n const rows = await em.find(SignalWaiterEntity, { token: { $like: `${prefix}%` } });\n return rows.map((e) => ({ token: e.token, runId: e.runId, seq: e.seq }));\n }\n\n async bufferSignal(token: string, payload: unknown): Promise<void> {\n const em = this.orm.em.fork();\n const e = new BufferedSignalEntity();\n e.token = token;\n e.payload = payload ?? null;\n em.persist(e);\n await em.flush();\n }\n\n async takeBufferedSignal(token: string): Promise<{ payload: unknown } | null> {\n const em = this.orm.em.fork();\n const entity = await em.findOne(BufferedSignalEntity, { token }, { orderBy: { id: 'asc' } });\n if (!entity) return null;\n const payload = entity.payload ?? undefined;\n await em.remove(entity).flush();\n return { payload };\n }\n}\n\nfunction toRunEntity(run: WorkflowRun): WorkflowRunEntity {\n const e = new WorkflowRunEntity();\n e.id = run.id;\n e.workflow = run.workflow;\n e.workflowVersion = run.workflowVersion;\n e.status = run.status;\n e.input = run.input ?? null;\n e.output = run.output ?? null;\n e.error = run.error ?? null;\n if (run.wakeAt != null) e.wakeAt = new Date(run.wakeAt);\n if (run.lockedBy !== undefined) e.lockedBy = run.lockedBy;\n if (run.lockedUntil != null) e.lockedUntil = new Date(run.lockedUntil);\n if (run.recoveryAttempts !== undefined) e.recoveryAttempts = run.recoveryAttempts;\n e.tags = run.tags ?? null;\n e.searchAttributes = run.searchAttributes ?? null;\n e.createdAt = run.createdAt;\n e.updatedAt = run.updatedAt;\n return e;\n}\n\nfunction fromRunEntity(e: WorkflowRunEntity): WorkflowRun {\n return {\n id: e.id,\n workflow: e.workflow,\n workflowVersion: e.workflowVersion,\n status: e.status,\n input: e.input ?? undefined,\n output: e.output ?? undefined,\n error: (e.error ?? undefined) as StepError | undefined,\n wakeAt: e.wakeAt?.getTime(),\n lockedBy: e.lockedBy ?? undefined,\n lockedUntil: e.lockedUntil?.getTime(),\n recoveryAttempts: e.recoveryAttempts ?? undefined,\n tags: e.tags ?? undefined,\n searchAttributes: e.searchAttributes ?? undefined,\n createdAt: e.createdAt,\n updatedAt: e.updatedAt,\n };\n}\n\nfunction toCheckpointEntity(cp: StepCheckpoint): StepCheckpointEntity {\n const e = new StepCheckpointEntity();\n e.runId = cp.runId;\n e.seq = cp.seq;\n e.name = cp.name;\n e.kind = cp.kind;\n e.stepId = cp.stepId;\n e.status = cp.status;\n e.input = cp.input ?? null;\n e.output = cp.output ?? null;\n e.error = cp.error ?? null;\n e.events = cp.events ?? null;\n e.attempts = cp.attempts;\n if (cp.workerGroup !== undefined) e.workerGroup = cp.workerGroup;\n if (cp.wakeAt != null) e.wakeAt = new Date(cp.wakeAt);\n e.enqueuedAt = cp.enqueuedAt;\n e.startedAt = cp.startedAt;\n e.finishedAt = cp.finishedAt;\n return e;\n}\n\nfunction fromCheckpointEntity(e: StepCheckpointEntity): StepCheckpoint {\n return {\n runId: e.runId,\n seq: e.seq,\n name: e.name,\n kind: e.kind,\n stepId: e.stepId,\n status: e.status,\n input: e.input ?? undefined,\n output: e.output ?? undefined,\n error: (e.error ?? undefined) as StepError | undefined,\n events: (e.events ?? undefined) as StepEvent[] | undefined,\n attempts: e.attempts,\n workerGroup: e.workerGroup ?? undefined,\n wakeAt: e.wakeAt?.getTime(),\n enqueuedAt: e.enqueuedAt ?? e.startedAt,\n startedAt: e.startedAt,\n finishedAt: e.finishedAt,\n };\n}\n","import type { MikroORM } from '@mikro-orm/core';\n\n/**\n * The tables this store owns. Kept in sync with the `tableName`s in `./entities`. Used to scope\n * schema management to our own tables (see {@link ensureMikroOrmDurableSchema}).\n */\nconst DURABLE_TABLE_NAMES = new Set([\n 'durable_workflow_runs',\n 'durable_step_checkpoints',\n 'durable_run_attributes',\n 'durable_signal_waiters',\n 'durable_buffered_signals',\n]);\n\n/** The table a `create table` / `alter table` statement targets, lower-cased; undefined otherwise. */\nfunction targetTable(statement: string): string | undefined {\n const match = statement.match(\n /^(?:create|alter)\\s+table\\s+(?:if\\s+not\\s+exists\\s+)?[`\"']?([\\w$]+)[`\"']?/i,\n );\n return match?.[1]?.toLowerCase();\n}\n\n/**\n * Idempotently create/extend ONLY the durable tables (additive — never drops). Safe to run on every\n * boot (auto-schema) and from a MikroORM migration when you disable auto-schema:\n *\n * ```ts\n * export class AddDurableTables extends Migration {\n * async up() { await ensureMikroOrmDurableSchema(this.getEntityManager().getOrm()); }\n * }\n * ```\n *\n * It does NOT run a whole-ORM `schema.update()`. When the store shares the host app's ORM (the\n * recommended setup — a single ORM avoids MikroORM's global-metadata clobber between instances),\n * a full `schema.update()` would try to reconcile EVERY app table to the entity metadata: on a\n * migration-managed schema that means recreating the migrations table and dropping app foreign keys.\n * Instead we compute the safe additive diff and execute only the statements that target our own\n * `durable_*` tables. `getUpdateSchemaSQL` already emits a `create table` only for a missing table\n * and `alter table ... add` only for missing columns, so existing tables — and the entire rest of\n * the host schema — are left untouched.\n */\nexport async function ensureMikroOrmDurableSchema(orm: MikroORM): Promise<void> {\n const sql = await orm.schema.getUpdateSchemaSQL({ safe: true });\n const ours = sql\n .split(';')\n .map((statement) => statement.trim())\n .filter((statement) => {\n const table = targetTable(statement);\n return table !== undefined && DURABLE_TABLE_NAMES.has(table);\n });\n if (ours.length === 0) {\n return;\n }\n const connection = orm.em.getConnection();\n for (const statement of ours) {\n await connection.execute(statement);\n }\n}\n"],"mappings":"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","names":["EntitySchema","snakeCase","property","replace","c","toLowerCase","columnNamer","naming","WorkflowRunEntity","id","workflow","workflowVersion","status","input","output","error","wakeAt","lockedBy","lockedUntil","recoveryAttempts","tags","searchAttributes","createdAt","updatedAt","StepCheckpointEntity","runId","seq","name","kind","stepId","events","attempts","workerGroup","enqueuedAt","startedAt","finishedAt","RunAttributeEntity","key","strValue","numValue","SignalWaiterEntity","token","BufferedSignalEntity","payload","durableEntities","options","col","workflowRuns","EntitySchema","class","tableName","properties","type","primary","fieldName","nullable","stepCheckpoints","runAttributes","signalWaiters","bufferedSignals","autoincrement","index","ENTITIES","attributeColumnFor","attributeOperand","normalizeAttributeRows","sqlComparator","DURABLE_TABLE_NAMES","Set","targetTable","statement","match","toLowerCase","ensureMikroOrmDurableSchema","orm","sql","schema","getUpdateSchemaSQL","safe","ours","split","map","trim","filter","table","undefined","has","length","connection","em","getConnection","execute","MikroOrmStateStore","orm","ensureSchema","ensureMikroOrmDurableSchema","createRun","run","em","fork","create","WorkflowRunEntity","toRunEntity","flush","reindexAttributes","id","searchAttributes","updateRun","runId","patch","entity","findOneOrFail","Object","assign","fromRunEntity","attributes","forked","nativeDelete","RunAttributeEntity","rows","normalizeAttributeRows","length","insertMany","getRun","findOne","deleteRun","StepCheckpointEntity","SignalWaiterEntity","getCheckpoint","seq","fromCheckpointEntity","saveCheckpoint","checkpoint","upsert","toCheckpointEntity","transaction","work","transactional","raw","cp","listIncompleteRuns","find","status","map","listPendingRuns","limit","orderBy","createdAt","listDueTimers","nowMs","wakeAt","$ne","$lte","Date","tryLockRun","owner","leaseUntilMs","affected","nativeUpdate","$or","lockedUntil","lockedBy","releaseRunLock","renewRunLock","listRuns","query","where","workflow","statuses","$and","$in","tag","quote","idQuote","cols","attributeColumns","qb","createQueryBuilder","tagsCol","tagsColumn","pattern","replace","colExpr","jsonAsText","andWhere","f","attributeExistsSql","offset","getResultList","alias","col","attributeColumnFor","numValue","strValue","cmp","sqlComparator","op","operand","attributeOperand","literal","String","a","table","sub","outerId","runPk","key","meta","getMetadata","get","field","prop","props","p","name","fieldNames","runMeta","properties","tableName","tags","colRef","platform","getPlatform","toLowerCase","includes","isMysql","ch","listCheckpoints","getLatestCheckpointByName","undefined","listCheckpointsByNamePrefix","prefixes","$like","putSignalWaiter","waiter","takeSignalWaiter","token","remove","listSignalWaiters","prefix","e","bufferSignal","payload","BufferedSignalEntity","persist","takeBufferedSignal","workflowVersion","input","output","error","recoveryAttempts","updatedAt","getTime","kind","stepId","events","attempts","workerGroup","enqueuedAt","startedAt","finishedAt"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dudousxd/nestjs-durable-store-mikro-orm",
3
- "version": "0.11.0",
3
+ "version": "0.12.0",
4
4
  "description": "MikroORM adapter for the nestjs-durable StateStore (reference ORM adapter)",
5
5
  "license": "MIT",
6
6
  "author": "Davide Carvalho",
@@ -31,8 +31,8 @@
31
31
  "reflect-metadata": "0.2.2",
32
32
  "tsup": "8.3.5",
33
33
  "typescript": "5.9.3",
34
- "@dudousxd/nestjs-durable-core": "^0.28.2",
35
- "@dudousxd/nestjs-durable-testing": "^0.5.0"
34
+ "@dudousxd/nestjs-durable-core": "^0.30.0",
35
+ "@dudousxd/nestjs-durable-testing": "^0.6.0"
36
36
  },
37
37
  "module": "./dist/index.js",
38
38
  "exports": {