@dudousxd/nestjs-durable-store-prisma 0.10.0 → 0.11.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -138,7 +138,12 @@ var PrismaStateStore = class {
138
138
  async listIncompleteRuns() {
139
139
  const rows = await this.db.durableWorkflowRun.findMany({
140
140
  where: {
141
- status: "running"
141
+ status: {
142
+ in: [
143
+ "running",
144
+ "cancelling"
145
+ ]
146
+ }
142
147
  }
143
148
  });
144
149
  return rows.map(fromRunRow);
@@ -404,6 +409,7 @@ function toRunData(run) {
404
409
  recoveryAttempts: run.recoveryAttempts ?? null,
405
410
  tags: jsonOrNull(run.tags),
406
411
  searchAttributes: jsonOrNull(run.searchAttributes),
412
+ priority: run.priority ?? null,
407
413
  createdAt: run.createdAt,
408
414
  updatedAt: run.updatedAt
409
415
  };
@@ -423,6 +429,7 @@ function toRunPatch(patch) {
423
429
  if ("recoveryAttempts" in patch) data.recoveryAttempts = patch.recoveryAttempts ?? null;
424
430
  if ("tags" in patch) data.tags = jsonOrNull(patch.tags);
425
431
  if ("searchAttributes" in patch) data.searchAttributes = jsonOrNull(patch.searchAttributes);
432
+ if ("priority" in patch) data.priority = patch.priority ?? null;
426
433
  if (patch.createdAt != null) data.createdAt = patch.createdAt;
427
434
  if (patch.updatedAt != null) data.updatedAt = patch.updatedAt;
428
435
  return data;
@@ -443,6 +450,7 @@ function fromRunRow(row) {
443
450
  recoveryAttempts: row.recoveryAttempts ?? void 0,
444
451
  tags: row.tags ?? void 0,
445
452
  searchAttributes: row.searchAttributes ?? void 0,
453
+ priority: row.priority ?? void 0,
446
454
  createdAt: row.createdAt,
447
455
  updatedAt: row.updatedAt
448
456
  };
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/prisma-state-store.ts"],"sourcesContent":["export * from './prisma-state-store';\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} from '@dudousxd/nestjs-durable-core';\n\n/* The Prisma client is generated per-schema, so the adapter can't import a concrete one. Instead\n it depends on this structural surface — the three model delegates and the methods it uses. A\n real `PrismaClient` (with the models from prisma/schema.prisma added) satisfies it. Query-arg\n shapes are Prisma's own generics, so they're left as `any` at this single boundary; the row\n return types are precise, which is what the mapping code below relies on. */\n\ninterface RunRow {\n id: string;\n workflow: string;\n workflowVersion: string;\n status: string;\n input: unknown;\n output: unknown;\n error: unknown;\n wakeAt: bigint | null;\n lockedBy: string | null;\n lockedUntil: Date | null;\n recoveryAttempts: number | null;\n tags: unknown;\n searchAttributes: unknown;\n createdAt: Date;\n updatedAt: Date;\n}\n\ninterface CheckpointRow {\n runId: string;\n seq: number;\n name: string;\n kind: string;\n stepId: string;\n status: string;\n input: unknown;\n output: unknown;\n error: unknown;\n events: unknown;\n attempts: number;\n workerGroup: string | null;\n wakeAt: bigint | null;\n enqueuedAt: Date | null;\n startedAt: Date;\n finishedAt: Date;\n}\n\ninterface WaiterRow {\n token: string;\n runId: string;\n seq: number;\n}\n\ninterface RunAttributeRow {\n runId: string;\n key: string;\n strValue: string | null;\n numValue: number | null;\n}\n\ninterface BufferedSignalRow {\n id: bigint;\n token: string;\n payload: unknown;\n}\n\n// Prisma's per-model query args are generated generics; left as `any` at this single boundary.\ntype Args = any;\n\ninterface Delegate<Row> {\n create(args: Args): Promise<Row>;\n createMany(args: Args): Promise<{ count: number }>;\n findUnique(args: Args): Promise<Row | null>;\n findFirst(args?: Args): Promise<Row | null>;\n findMany(args?: Args): Promise<Row[]>;\n update(args: Args): Promise<Row>;\n updateMany(args: Args): Promise<{ count: number }>;\n upsert(args: Args): Promise<Row>;\n delete(args: Args): Promise<Row>;\n deleteMany(args?: Args): Promise<{ count: number }>;\n}\n\nexport interface DurablePrismaTx {\n durableWorkflowRun: Delegate<RunRow>;\n durableStepCheckpoint: Delegate<CheckpointRow>;\n durableRunAttribute: Delegate<RunAttributeRow>;\n durableSignalWaiter: Delegate<WaiterRow>;\n durableBufferedSignal: Delegate<BufferedSignalRow>;\n}\n\nexport interface DurablePrismaClient extends DurablePrismaTx {\n /** Prisma's interactive-transaction form: runs `fn` with a tx-scoped client and commits on resolve. */\n $transaction<T>(fn: (tx: DurablePrismaTx) => Promise<T>): Promise<T>;\n}\n\n/**\n * Prisma-backed `StateStore`. Pass your `PrismaClient` after adding the models from\n * `prisma/schema.prisma` to your schema. JSON columns carry the run/step payloads directly;\n * `wakeAt` is a `BigInt` (epoch ms).\n */\nexport class PrismaStateStore implements StateStore {\n constructor(private readonly db: DurablePrismaClient) {}\n\n async createRun(run: WorkflowRun): Promise<void> {\n await this.db.durableWorkflowRun.create({ data: toRunData(run) });\n await this.reindexAttributes(run.id, run.searchAttributes);\n }\n\n async updateRun(runId: string, patch: Partial<WorkflowRun>): Promise<void> {\n await this.db.durableWorkflowRun.update({ where: { id: runId }, data: toRunPatch(patch) });\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 ): Promise<void> {\n await this.db.durableRunAttribute.deleteMany({ where: { runId } });\n const rows = normalizeAttributeRows(runId, attributes);\n if (rows.length) await this.db.durableRunAttribute.createMany({ data: rows });\n }\n\n async getRun(runId: string): Promise<WorkflowRun | null> {\n const row = await this.db.durableWorkflowRun.findUnique({ where: { id: runId } });\n return row ? fromRunRow(row) : null;\n }\n\n async deleteRun(runId: string): Promise<void> {\n // Child rows first, then the run — checkpoints, signal waiters, attribute rows.\n await this.db.durableStepCheckpoint.deleteMany({ where: { runId } });\n await this.db.durableSignalWaiter.deleteMany({ where: { runId } });\n await this.db.durableRunAttribute.deleteMany({ where: { runId } });\n await this.db.durableWorkflowRun.deleteMany({ where: { id: runId } });\n }\n\n async getCheckpoint(runId: string, seq: number): Promise<StepCheckpoint | null> {\n const row = await this.db.durableStepCheckpoint.findUnique({\n where: { runId_seq: { runId, seq } },\n });\n return row ? fromCheckpointRow(row) : null;\n }\n\n async saveCheckpoint(checkpoint: StepCheckpoint): Promise<void> {\n const data = toCheckpointData(checkpoint);\n await this.db.durableStepCheckpoint.upsert({\n where: { runId_seq: { runId: checkpoint.runId, seq: checkpoint.seq } },\n create: data,\n update: data,\n });\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.db.$transaction(async (tx) =>\n work({\n raw: tx,\n saveCheckpoint: async (cp) => {\n const data = toCheckpointData(cp);\n await tx.durableStepCheckpoint.upsert({\n where: { runId_seq: { runId: cp.runId, seq: cp.seq } },\n create: data,\n update: data,\n });\n },\n }),\n );\n }\n\n async listIncompleteRuns(): Promise<WorkflowRun[]> {\n const rows = await this.db.durableWorkflowRun.findMany({ where: { status: 'running' } });\n return rows.map(fromRunRow);\n }\n\n async listPendingRuns(limit: number): Promise<WorkflowRun[]> {\n const rows = await this.db.durableWorkflowRun.findMany({\n where: { status: 'pending' },\n orderBy: { createdAt: 'asc' }, // FIFO dispatch\n take: limit,\n });\n return rows.map(fromRunRow);\n }\n\n async listDueTimers(nowMs: number): Promise<WorkflowRun[]> {\n const rows = await this.db.durableWorkflowRun.findMany({\n where: { status: 'suspended', wakeAt: { not: null, lte: BigInt(nowMs) } },\n });\n return rows.map(fromRunRow);\n }\n\n async tryLockRun(\n runId: string,\n owner: string,\n leaseUntilMs: number,\n nowMs: number,\n ): Promise<boolean> {\n const result = await this.db.durableWorkflowRun.updateMany({\n where: {\n id: runId,\n OR: [{ lockedUntil: null }, { lockedUntil: { lte: new Date(nowMs) } }],\n },\n data: { lockedBy: owner, lockedUntil: new Date(leaseUntilMs) },\n });\n return result.count === 1;\n }\n\n async releaseRunLock(runId: string): Promise<void> {\n await this.db.durableWorkflowRun.update({\n where: { id: runId },\n data: { lockedBy: null, lockedUntil: null },\n });\n }\n\n async renewRunLock(runId: string, owner: string, leaseUntilMs: number): Promise<boolean> {\n const result = await this.db.durableWorkflowRun.updateMany({\n where: { id: runId, lockedBy: owner },\n data: { lockedUntil: new Date(leaseUntilMs) },\n });\n return result.count === 1;\n }\n\n async listRuns(query: RunQuery): Promise<WorkflowRun[]> {\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). Combined with the\n // single-value `status` via AND when both are present, 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 if (query.tag) where.tags = { array_contains: query.tag };\n // Typed/range attribute predicates push DOWN into SQL: each filter becomes a relation `some`\n // (EXISTS) on the normalized `durable_run_attributes` side-table, so the DB filters AND paginates\n // — no full scan + in-process filter. ANDed: a run must match every filter, so one `some` each.\n if (query.attributes?.length) {\n const existing = (where.AND as unknown[] | undefined) ?? [];\n where.AND = [...existing, ...query.attributes.map((f) => attributeSome(f))];\n }\n const orderBy = { createdAt: 'desc' as const }; // newest first — recent runs on top in the dashboard\n const rows = await this.db.durableWorkflowRun.findMany({\n where,\n take: query.limit,\n skip: query.offset,\n orderBy,\n });\n return rows.map(fromRunRow);\n }\n\n async listCheckpoints(runId: string): Promise<StepCheckpoint[]> {\n const rows = await this.db.durableStepCheckpoint.findMany({\n where: { runId },\n orderBy: { seq: 'asc' },\n });\n return rows.map(fromCheckpointRow);\n }\n\n async getLatestCheckpointByName(\n runId: string,\n name: string,\n ): Promise<StepCheckpoint | undefined> {\n const row = await this.db.durableStepCheckpoint.findFirst({\n where: { runId, name },\n orderBy: { seq: 'desc' },\n });\n return row ? fromCheckpointRow(row) : undefined;\n }\n\n async listCheckpointsByNamePrefix(runId: string, prefixes: string[]): Promise<StepCheckpoint[]> {\n if (prefixes.length === 0) return [];\n const rows = await this.db.durableStepCheckpoint.findMany({\n where: { runId, OR: prefixes.map((p) => ({ name: { startsWith: p } })) },\n orderBy: { seq: 'asc' },\n });\n return rows.map(fromCheckpointRow);\n }\n\n async putSignalWaiter(waiter: SignalWaiter): Promise<void> {\n await this.db.durableSignalWaiter.upsert({\n where: { token: waiter.token },\n create: { ...waiter },\n update: { runId: waiter.runId, seq: waiter.seq },\n });\n }\n\n async takeSignalWaiter(token: string): Promise<SignalWaiter | null> {\n const row = await this.db.durableSignalWaiter.findUnique({ where: { token } });\n if (!row) return null;\n await this.db.durableSignalWaiter.delete({ where: { token } });\n return { token: row.token, runId: row.runId, seq: row.seq };\n }\n\n async listSignalWaiters(prefix: string): Promise<SignalWaiter[]> {\n const rows = await this.db.durableSignalWaiter.findMany({\n where: { token: { startsWith: prefix } },\n });\n return rows.map((r) => ({ token: r.token, runId: r.runId, seq: r.seq }));\n }\n\n async bufferSignal(token: string, payload: unknown): Promise<void> {\n await this.db.durableBufferedSignal.create({ data: { token, payload: jsonOrNull(payload) } });\n }\n\n async takeBufferedSignal(token: string): Promise<{ payload: unknown } | null> {\n const row = await this.db.durableBufferedSignal.findFirst({\n where: { token },\n orderBy: { id: 'asc' },\n });\n if (!row) return null;\n await this.db.durableBufferedSignal.delete({ where: { id: row.id } });\n return { payload: row.payload ?? undefined };\n }\n}\n\n/**\n * One attribute predicate as a Prisma relation `some` filter on the side-table — compiles to an\n * EXISTS, so the predicate runs in SQL. `<>` (ne) maps to `{ not }`, which under `some` also excludes\n * runs where the attribute is absent (the missing-key-never-matches contract): `some` already\n * requires a matching row to exist. Numeric operands compare `numValue`, everything else `strValue`.\n */\nfunction attributeSome(f: AttributeFilter): { attributes: { some: Record<string, unknown> } } {\n const col = attributeColumnFor(f); // 'numValue' | 'strValue'\n const operand = attributeOperand(f);\n const condition =\n f.op === 'eq' ? operand : f.op === 'ne' ? { not: operand } : { [f.op]: operand }; // gt/gte/lt/lte map 1:1 to Prisma operators\n return { attributes: { some: { key: f.key, [col]: condition } } };\n}\n\nconst bigOrNull = (n: number | undefined) => (n == null ? null : BigInt(n));\nconst numOrUndef = (n: bigint | null) => (n == null ? undefined : Number(n));\nconst jsonOrNull = (v: unknown) => v ?? null;\n\nfunction toRunData(run: WorkflowRun) {\n return {\n id: run.id,\n workflow: run.workflow,\n workflowVersion: run.workflowVersion,\n status: run.status,\n input: jsonOrNull(run.input),\n output: jsonOrNull(run.output),\n error: jsonOrNull(run.error),\n wakeAt: bigOrNull(run.wakeAt),\n lockedBy: run.lockedBy ?? null,\n lockedUntil: run.lockedUntil == null ? null : new Date(run.lockedUntil),\n recoveryAttempts: run.recoveryAttempts ?? null,\n tags: jsonOrNull(run.tags),\n searchAttributes: jsonOrNull(run.searchAttributes),\n createdAt: run.createdAt,\n updatedAt: run.updatedAt,\n };\n}\n\nfunction toRunPatch(patch: Partial<WorkflowRun>) {\n // Map EVERY patchable field, using presence (`'x' in patch`) semantics for the nullable ones so a\n // patch can CLEAR a column (e.g. `{ error: undefined }` on completion sets it to NULL — matching\n // the TypeORM / MikroORM / in-memory stores). The two non-null Date fields use a defined-guard\n // since they are never cleared. Previously only 7 fields were mapped, so `updateRun({ tags })` /\n // `{ lockedBy }` / clearing `error` silently no-opped on this adapter.\n const data: Record<string, unknown> = {};\n if ('workflow' in patch) data.workflow = patch.workflow;\n if ('workflowVersion' in patch) data.workflowVersion = patch.workflowVersion;\n if ('status' in patch) data.status = patch.status;\n if ('input' in patch) data.input = jsonOrNull(patch.input);\n if ('output' in patch) data.output = jsonOrNull(patch.output);\n if ('error' in patch) data.error = jsonOrNull(patch.error);\n if ('wakeAt' in patch) data.wakeAt = bigOrNull(patch.wakeAt);\n if ('lockedBy' in patch) data.lockedBy = patch.lockedBy ?? null;\n if ('lockedUntil' in patch)\n data.lockedUntil = patch.lockedUntil == null ? null : new Date(patch.lockedUntil);\n if ('recoveryAttempts' in patch) data.recoveryAttempts = patch.recoveryAttempts ?? null;\n if ('tags' in patch) data.tags = jsonOrNull(patch.tags);\n if ('searchAttributes' in patch) data.searchAttributes = jsonOrNull(patch.searchAttributes);\n if (patch.createdAt != null) data.createdAt = patch.createdAt;\n if (patch.updatedAt != null) data.updatedAt = patch.updatedAt;\n return data;\n}\n\nfunction fromRunRow(row: RunRow): WorkflowRun {\n return {\n id: row.id,\n workflow: row.workflow,\n workflowVersion: row.workflowVersion,\n status: row.status as WorkflowRun['status'],\n input: row.input ?? undefined,\n output: row.output ?? undefined,\n error: (row.error ?? undefined) as StepError | undefined,\n wakeAt: numOrUndef(row.wakeAt),\n lockedBy: row.lockedBy ?? undefined,\n lockedUntil: row.lockedUntil == null ? undefined : row.lockedUntil.getTime(),\n recoveryAttempts: row.recoveryAttempts ?? undefined,\n tags: (row.tags as string[] | null) ?? undefined,\n searchAttributes:\n (row.searchAttributes as Record<string, string | number | boolean> | null) ?? undefined,\n createdAt: row.createdAt,\n updatedAt: row.updatedAt,\n };\n}\n\nfunction toCheckpointData(cp: StepCheckpoint) {\n return {\n runId: cp.runId,\n seq: cp.seq,\n name: cp.name,\n kind: cp.kind,\n stepId: cp.stepId,\n status: cp.status,\n input: jsonOrNull(cp.input),\n output: jsonOrNull(cp.output),\n error: jsonOrNull(cp.error),\n events: jsonOrNull(cp.events),\n attempts: cp.attempts,\n workerGroup: cp.workerGroup ?? null,\n wakeAt: bigOrNull(cp.wakeAt),\n enqueuedAt: cp.enqueuedAt,\n startedAt: cp.startedAt,\n finishedAt: cp.finishedAt,\n };\n}\n\nfunction fromCheckpointRow(row: CheckpointRow): StepCheckpoint {\n return {\n runId: row.runId,\n seq: row.seq,\n name: row.name,\n kind: row.kind as StepCheckpoint['kind'],\n stepId: row.stepId,\n status: row.status as StepCheckpoint['status'],\n input: row.input ?? undefined,\n output: row.output ?? undefined,\n error: (row.error ?? undefined) as StepError | undefined,\n events: (row.events ?? undefined) as StepEvent[] | undefined,\n attempts: row.attempts,\n workerGroup: row.workerGroup ?? undefined,\n wakeAt: numOrUndef(row.wakeAt),\n enqueuedAt: row.enqueuedAt ?? row.startedAt,\n startedAt: row.startedAt,\n finishedAt: row.finishedAt,\n };\n}\n"],"mappings":"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","names":["PrismaStateStore","db","createRun","run","durableWorkflowRun","create","data","toRunData","reindexAttributes","id","searchAttributes","updateRun","runId","patch","update","where","toRunPatch","attributes","durableRunAttribute","deleteMany","rows","normalizeAttributeRows","length","createMany","getRun","row","findUnique","fromRunRow","deleteRun","durableStepCheckpoint","durableSignalWaiter","getCheckpoint","seq","runId_seq","fromCheckpointRow","saveCheckpoint","checkpoint","toCheckpointData","upsert","transaction","work","$transaction","tx","raw","cp","listIncompleteRuns","findMany","status","map","listPendingRuns","limit","orderBy","createdAt","take","listDueTimers","nowMs","wakeAt","not","lte","BigInt","tryLockRun","owner","leaseUntilMs","result","updateMany","OR","lockedUntil","Date","lockedBy","count","releaseRunLock","renewRunLock","listRuns","query","workflow","statuses","AND","in","tag","tags","array_contains","existing","f","attributeSome","skip","offset","listCheckpoints","getLatestCheckpointByName","name","findFirst","undefined","listCheckpointsByNamePrefix","prefixes","p","startsWith","putSignalWaiter","waiter","token","takeSignalWaiter","delete","listSignalWaiters","prefix","r","bufferSignal","payload","durableBufferedSignal","jsonOrNull","takeBufferedSignal","col","attributeColumnFor","operand","attributeOperand","condition","op","some","key","bigOrNull","n","numOrUndef","Number","v","workflowVersion","input","output","error","recoveryAttempts","updatedAt","getTime","kind","stepId","events","attempts","workerGroup","enqueuedAt","startedAt","finishedAt"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/prisma-state-store.ts"],"sourcesContent":["export * from './prisma-state-store';\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} from '@dudousxd/nestjs-durable-core';\n\n/* The Prisma client is generated per-schema, so the adapter can't import a concrete one. Instead\n it depends on this structural surface — the three model delegates and the methods it uses. A\n real `PrismaClient` (with the models from prisma/schema.prisma added) satisfies it. Query-arg\n shapes are Prisma's own generics, so they're left as `any` at this single boundary; the row\n return types are precise, which is what the mapping code below relies on. */\n\ninterface RunRow {\n id: string;\n workflow: string;\n workflowVersion: string;\n status: string;\n input: unknown;\n output: unknown;\n error: unknown;\n wakeAt: bigint | null;\n lockedBy: string | null;\n lockedUntil: Date | null;\n recoveryAttempts: number | null;\n tags: unknown;\n searchAttributes: unknown;\n priority: number | null;\n createdAt: Date;\n updatedAt: Date;\n}\n\ninterface CheckpointRow {\n runId: string;\n seq: number;\n name: string;\n kind: string;\n stepId: string;\n status: string;\n input: unknown;\n output: unknown;\n error: unknown;\n events: unknown;\n attempts: number;\n workerGroup: string | null;\n wakeAt: bigint | null;\n enqueuedAt: Date | null;\n startedAt: Date;\n finishedAt: Date;\n}\n\ninterface WaiterRow {\n token: string;\n runId: string;\n seq: number;\n}\n\ninterface RunAttributeRow {\n runId: string;\n key: string;\n strValue: string | null;\n numValue: number | null;\n}\n\ninterface BufferedSignalRow {\n id: bigint;\n token: string;\n payload: unknown;\n}\n\n// Prisma's per-model query args are generated generics; left as `any` at this single boundary.\ntype Args = any;\n\ninterface Delegate<Row> {\n create(args: Args): Promise<Row>;\n createMany(args: Args): Promise<{ count: number }>;\n findUnique(args: Args): Promise<Row | null>;\n findFirst(args?: Args): Promise<Row | null>;\n findMany(args?: Args): Promise<Row[]>;\n update(args: Args): Promise<Row>;\n updateMany(args: Args): Promise<{ count: number }>;\n upsert(args: Args): Promise<Row>;\n delete(args: Args): Promise<Row>;\n deleteMany(args?: Args): Promise<{ count: number }>;\n}\n\nexport interface DurablePrismaTx {\n durableWorkflowRun: Delegate<RunRow>;\n durableStepCheckpoint: Delegate<CheckpointRow>;\n durableRunAttribute: Delegate<RunAttributeRow>;\n durableSignalWaiter: Delegate<WaiterRow>;\n durableBufferedSignal: Delegate<BufferedSignalRow>;\n}\n\nexport interface DurablePrismaClient extends DurablePrismaTx {\n /** Prisma's interactive-transaction form: runs `fn` with a tx-scoped client and commits on resolve. */\n $transaction<T>(fn: (tx: DurablePrismaTx) => Promise<T>): Promise<T>;\n}\n\n/**\n * Prisma-backed `StateStore`. Pass your `PrismaClient` after adding the models from\n * `prisma/schema.prisma` to your schema. JSON columns carry the run/step payloads directly;\n * `wakeAt` is a `BigInt` (epoch ms).\n */\nexport class PrismaStateStore implements StateStore {\n constructor(private readonly db: DurablePrismaClient) {}\n\n async createRun(run: WorkflowRun): Promise<void> {\n await this.db.durableWorkflowRun.create({ data: toRunData(run) });\n await this.reindexAttributes(run.id, run.searchAttributes);\n }\n\n async updateRun(runId: string, patch: Partial<WorkflowRun>): Promise<void> {\n await this.db.durableWorkflowRun.update({ where: { id: runId }, data: toRunPatch(patch) });\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 ): Promise<void> {\n await this.db.durableRunAttribute.deleteMany({ where: { runId } });\n const rows = normalizeAttributeRows(runId, attributes);\n if (rows.length) await this.db.durableRunAttribute.createMany({ data: rows });\n }\n\n async getRun(runId: string): Promise<WorkflowRun | null> {\n const row = await this.db.durableWorkflowRun.findUnique({ where: { id: runId } });\n return row ? fromRunRow(row) : null;\n }\n\n async deleteRun(runId: string): Promise<void> {\n // Child rows first, then the run — checkpoints, signal waiters, attribute rows.\n await this.db.durableStepCheckpoint.deleteMany({ where: { runId } });\n await this.db.durableSignalWaiter.deleteMany({ where: { runId } });\n await this.db.durableRunAttribute.deleteMany({ where: { runId } });\n await this.db.durableWorkflowRun.deleteMany({ where: { id: runId } });\n }\n\n async getCheckpoint(runId: string, seq: number): Promise<StepCheckpoint | null> {\n const row = await this.db.durableStepCheckpoint.findUnique({\n where: { runId_seq: { runId, seq } },\n });\n return row ? fromCheckpointRow(row) : null;\n }\n\n async saveCheckpoint(checkpoint: StepCheckpoint): Promise<void> {\n const data = toCheckpointData(checkpoint);\n await this.db.durableStepCheckpoint.upsert({\n where: { runId_seq: { runId: checkpoint.runId, seq: checkpoint.seq } },\n create: data,\n update: data,\n });\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.db.$transaction(async (tx) =>\n work({\n raw: tx,\n saveCheckpoint: async (cp) => {\n const data = toCheckpointData(cp);\n await tx.durableStepCheckpoint.upsert({\n where: { runId_seq: { runId: cp.runId, seq: cp.seq } },\n create: data,\n update: data,\n });\n },\n }),\n );\n }\n\n async listIncompleteRuns(): Promise<WorkflowRun[]> {\n const rows = await this.db.durableWorkflowRun.findMany({\n where: { status: { in: ['running', 'cancelling'] } },\n });\n return rows.map(fromRunRow);\n }\n\n async listPendingRuns(limit: number): Promise<WorkflowRun[]> {\n const rows = await this.db.durableWorkflowRun.findMany({\n where: { status: 'pending' },\n orderBy: { createdAt: 'asc' }, // FIFO dispatch\n take: limit,\n });\n return rows.map(fromRunRow);\n }\n\n async listDueTimers(nowMs: number): Promise<WorkflowRun[]> {\n const rows = await this.db.durableWorkflowRun.findMany({\n where: { status: 'suspended', wakeAt: { not: null, lte: BigInt(nowMs) } },\n });\n return rows.map(fromRunRow);\n }\n\n async tryLockRun(\n runId: string,\n owner: string,\n leaseUntilMs: number,\n nowMs: number,\n ): Promise<boolean> {\n const result = await this.db.durableWorkflowRun.updateMany({\n where: {\n id: runId,\n OR: [{ lockedUntil: null }, { lockedUntil: { lte: new Date(nowMs) } }],\n },\n data: { lockedBy: owner, lockedUntil: new Date(leaseUntilMs) },\n });\n return result.count === 1;\n }\n\n async releaseRunLock(runId: string): Promise<void> {\n await this.db.durableWorkflowRun.update({\n where: { id: runId },\n data: { lockedBy: null, lockedUntil: null },\n });\n }\n\n async renewRunLock(runId: string, owner: string, leaseUntilMs: number): Promise<boolean> {\n const result = await this.db.durableWorkflowRun.updateMany({\n where: { id: runId, lockedBy: owner },\n data: { lockedUntil: new Date(leaseUntilMs) },\n });\n return result.count === 1;\n }\n\n async listRuns(query: RunQuery): Promise<WorkflowRun[]> {\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). Combined with the\n // single-value `status` via AND when both are present, 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 if (query.tag) where.tags = { array_contains: query.tag };\n // Typed/range attribute predicates push DOWN into SQL: each filter becomes a relation `some`\n // (EXISTS) on the normalized `durable_run_attributes` side-table, so the DB filters AND paginates\n // — no full scan + in-process filter. ANDed: a run must match every filter, so one `some` each.\n if (query.attributes?.length) {\n const existing = (where.AND as unknown[] | undefined) ?? [];\n where.AND = [...existing, ...query.attributes.map((f) => attributeSome(f))];\n }\n const orderBy = { createdAt: 'desc' as const }; // newest first — recent runs on top in the dashboard\n const rows = await this.db.durableWorkflowRun.findMany({\n where,\n take: query.limit,\n skip: query.offset,\n orderBy,\n });\n return rows.map(fromRunRow);\n }\n\n async listCheckpoints(runId: string): Promise<StepCheckpoint[]> {\n const rows = await this.db.durableStepCheckpoint.findMany({\n where: { runId },\n orderBy: { seq: 'asc' },\n });\n return rows.map(fromCheckpointRow);\n }\n\n async getLatestCheckpointByName(\n runId: string,\n name: string,\n ): Promise<StepCheckpoint | undefined> {\n const row = await this.db.durableStepCheckpoint.findFirst({\n where: { runId, name },\n orderBy: { seq: 'desc' },\n });\n return row ? fromCheckpointRow(row) : undefined;\n }\n\n async listCheckpointsByNamePrefix(runId: string, prefixes: string[]): Promise<StepCheckpoint[]> {\n if (prefixes.length === 0) return [];\n const rows = await this.db.durableStepCheckpoint.findMany({\n where: { runId, OR: prefixes.map((p) => ({ name: { startsWith: p } })) },\n orderBy: { seq: 'asc' },\n });\n return rows.map(fromCheckpointRow);\n }\n\n async putSignalWaiter(waiter: SignalWaiter): Promise<void> {\n await this.db.durableSignalWaiter.upsert({\n where: { token: waiter.token },\n create: { ...waiter },\n update: { runId: waiter.runId, seq: waiter.seq },\n });\n }\n\n async takeSignalWaiter(token: string): Promise<SignalWaiter | null> {\n const row = await this.db.durableSignalWaiter.findUnique({ where: { token } });\n if (!row) return null;\n await this.db.durableSignalWaiter.delete({ where: { token } });\n return { token: row.token, runId: row.runId, seq: row.seq };\n }\n\n async listSignalWaiters(prefix: string): Promise<SignalWaiter[]> {\n const rows = await this.db.durableSignalWaiter.findMany({\n where: { token: { startsWith: prefix } },\n });\n return rows.map((r) => ({ token: r.token, runId: r.runId, seq: r.seq }));\n }\n\n async bufferSignal(token: string, payload: unknown): Promise<void> {\n await this.db.durableBufferedSignal.create({ data: { token, payload: jsonOrNull(payload) } });\n }\n\n async takeBufferedSignal(token: string): Promise<{ payload: unknown } | null> {\n const row = await this.db.durableBufferedSignal.findFirst({\n where: { token },\n orderBy: { id: 'asc' },\n });\n if (!row) return null;\n await this.db.durableBufferedSignal.delete({ where: { id: row.id } });\n return { payload: row.payload ?? undefined };\n }\n}\n\n/**\n * One attribute predicate as a Prisma relation `some` filter on the side-table — compiles to an\n * EXISTS, so the predicate runs in SQL. `<>` (ne) maps to `{ not }`, which under `some` also excludes\n * runs where the attribute is absent (the missing-key-never-matches contract): `some` already\n * requires a matching row to exist. Numeric operands compare `numValue`, everything else `strValue`.\n */\nfunction attributeSome(f: AttributeFilter): { attributes: { some: Record<string, unknown> } } {\n const col = attributeColumnFor(f); // 'numValue' | 'strValue'\n const operand = attributeOperand(f);\n const condition =\n f.op === 'eq' ? operand : f.op === 'ne' ? { not: operand } : { [f.op]: operand }; // gt/gte/lt/lte map 1:1 to Prisma operators\n return { attributes: { some: { key: f.key, [col]: condition } } };\n}\n\nconst bigOrNull = (n: number | undefined) => (n == null ? null : BigInt(n));\nconst numOrUndef = (n: bigint | null) => (n == null ? undefined : Number(n));\nconst jsonOrNull = (v: unknown) => v ?? null;\n\nfunction toRunData(run: WorkflowRun) {\n return {\n id: run.id,\n workflow: run.workflow,\n workflowVersion: run.workflowVersion,\n status: run.status,\n input: jsonOrNull(run.input),\n output: jsonOrNull(run.output),\n error: jsonOrNull(run.error),\n wakeAt: bigOrNull(run.wakeAt),\n lockedBy: run.lockedBy ?? null,\n lockedUntil: run.lockedUntil == null ? null : new Date(run.lockedUntil),\n recoveryAttempts: run.recoveryAttempts ?? null,\n tags: jsonOrNull(run.tags),\n searchAttributes: jsonOrNull(run.searchAttributes),\n priority: run.priority ?? null,\n createdAt: run.createdAt,\n updatedAt: run.updatedAt,\n };\n}\n\nfunction toRunPatch(patch: Partial<WorkflowRun>) {\n // Map EVERY patchable field, using presence (`'x' in patch`) semantics for the nullable ones so a\n // patch can CLEAR a column (e.g. `{ error: undefined }` on completion sets it to NULL — matching\n // the TypeORM / MikroORM / in-memory stores). The two non-null Date fields use a defined-guard\n // since they are never cleared. Previously only 7 fields were mapped, so `updateRun({ tags })` /\n // `{ lockedBy }` / clearing `error` silently no-opped on this adapter.\n const data: Record<string, unknown> = {};\n if ('workflow' in patch) data.workflow = patch.workflow;\n if ('workflowVersion' in patch) data.workflowVersion = patch.workflowVersion;\n if ('status' in patch) data.status = patch.status;\n if ('input' in patch) data.input = jsonOrNull(patch.input);\n if ('output' in patch) data.output = jsonOrNull(patch.output);\n if ('error' in patch) data.error = jsonOrNull(patch.error);\n if ('wakeAt' in patch) data.wakeAt = bigOrNull(patch.wakeAt);\n if ('lockedBy' in patch) data.lockedBy = patch.lockedBy ?? null;\n if ('lockedUntil' in patch)\n data.lockedUntil = patch.lockedUntil == null ? null : new Date(patch.lockedUntil);\n if ('recoveryAttempts' in patch) data.recoveryAttempts = patch.recoveryAttempts ?? null;\n if ('tags' in patch) data.tags = jsonOrNull(patch.tags);\n if ('searchAttributes' in patch) data.searchAttributes = jsonOrNull(patch.searchAttributes);\n if ('priority' in patch) data.priority = patch.priority ?? null;\n if (patch.createdAt != null) data.createdAt = patch.createdAt;\n if (patch.updatedAt != null) data.updatedAt = patch.updatedAt;\n return data;\n}\n\nfunction fromRunRow(row: RunRow): WorkflowRun {\n return {\n id: row.id,\n workflow: row.workflow,\n workflowVersion: row.workflowVersion,\n status: row.status as WorkflowRun['status'],\n input: row.input ?? undefined,\n output: row.output ?? undefined,\n error: (row.error ?? undefined) as StepError | undefined,\n wakeAt: numOrUndef(row.wakeAt),\n lockedBy: row.lockedBy ?? undefined,\n lockedUntil: row.lockedUntil == null ? undefined : row.lockedUntil.getTime(),\n recoveryAttempts: row.recoveryAttempts ?? undefined,\n tags: (row.tags as string[] | null) ?? undefined,\n searchAttributes:\n (row.searchAttributes as Record<string, string | number | boolean> | null) ?? undefined,\n priority: row.priority ?? undefined,\n createdAt: row.createdAt,\n updatedAt: row.updatedAt,\n };\n}\n\nfunction toCheckpointData(cp: StepCheckpoint) {\n return {\n runId: cp.runId,\n seq: cp.seq,\n name: cp.name,\n kind: cp.kind,\n stepId: cp.stepId,\n status: cp.status,\n input: jsonOrNull(cp.input),\n output: jsonOrNull(cp.output),\n error: jsonOrNull(cp.error),\n events: jsonOrNull(cp.events),\n attempts: cp.attempts,\n workerGroup: cp.workerGroup ?? null,\n wakeAt: bigOrNull(cp.wakeAt),\n enqueuedAt: cp.enqueuedAt,\n startedAt: cp.startedAt,\n finishedAt: cp.finishedAt,\n };\n}\n\nfunction fromCheckpointRow(row: CheckpointRow): StepCheckpoint {\n return {\n runId: row.runId,\n seq: row.seq,\n name: row.name,\n kind: row.kind as StepCheckpoint['kind'],\n stepId: row.stepId,\n status: row.status as StepCheckpoint['status'],\n input: row.input ?? undefined,\n output: row.output ?? undefined,\n error: (row.error ?? undefined) as StepError | undefined,\n events: (row.events ?? undefined) as StepEvent[] | undefined,\n attempts: row.attempts,\n workerGroup: row.workerGroup ?? undefined,\n wakeAt: numOrUndef(row.wakeAt),\n enqueuedAt: row.enqueuedAt ?? row.startedAt,\n startedAt: row.startedAt,\n finishedAt: row.finishedAt,\n };\n}\n"],"mappings":"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","names":["PrismaStateStore","db","createRun","run","durableWorkflowRun","create","data","toRunData","reindexAttributes","id","searchAttributes","updateRun","runId","patch","update","where","toRunPatch","attributes","durableRunAttribute","deleteMany","rows","normalizeAttributeRows","length","createMany","getRun","row","findUnique","fromRunRow","deleteRun","durableStepCheckpoint","durableSignalWaiter","getCheckpoint","seq","runId_seq","fromCheckpointRow","saveCheckpoint","checkpoint","toCheckpointData","upsert","transaction","work","$transaction","tx","raw","cp","listIncompleteRuns","findMany","status","in","map","listPendingRuns","limit","orderBy","createdAt","take","listDueTimers","nowMs","wakeAt","not","lte","BigInt","tryLockRun","owner","leaseUntilMs","result","updateMany","OR","lockedUntil","Date","lockedBy","count","releaseRunLock","renewRunLock","listRuns","query","workflow","statuses","AND","tag","tags","array_contains","existing","f","attributeSome","skip","offset","listCheckpoints","getLatestCheckpointByName","name","findFirst","undefined","listCheckpointsByNamePrefix","prefixes","p","startsWith","putSignalWaiter","waiter","token","takeSignalWaiter","delete","listSignalWaiters","prefix","r","bufferSignal","payload","durableBufferedSignal","jsonOrNull","takeBufferedSignal","col","attributeColumnFor","operand","attributeOperand","condition","op","some","key","bigOrNull","n","numOrUndef","Number","v","workflowVersion","input","output","error","recoveryAttempts","priority","updatedAt","getTime","kind","stepId","events","attempts","workerGroup","enqueuedAt","startedAt","finishedAt"]}
package/dist/index.d.cts CHANGED
@@ -14,6 +14,7 @@ interface RunRow {
14
14
  recoveryAttempts: number | null;
15
15
  tags: unknown;
16
16
  searchAttributes: unknown;
17
+ priority: number | null;
17
18
  createdAt: Date;
18
19
  updatedAt: Date;
19
20
  }
package/dist/index.d.ts CHANGED
@@ -14,6 +14,7 @@ interface RunRow {
14
14
  recoveryAttempts: number | null;
15
15
  tags: unknown;
16
16
  searchAttributes: unknown;
17
+ priority: number | null;
17
18
  createdAt: Date;
18
19
  updatedAt: Date;
19
20
  }
package/dist/index.js CHANGED
@@ -114,7 +114,12 @@ var PrismaStateStore = class {
114
114
  async listIncompleteRuns() {
115
115
  const rows = await this.db.durableWorkflowRun.findMany({
116
116
  where: {
117
- status: "running"
117
+ status: {
118
+ in: [
119
+ "running",
120
+ "cancelling"
121
+ ]
122
+ }
118
123
  }
119
124
  });
120
125
  return rows.map(fromRunRow);
@@ -380,6 +385,7 @@ function toRunData(run) {
380
385
  recoveryAttempts: run.recoveryAttempts ?? null,
381
386
  tags: jsonOrNull(run.tags),
382
387
  searchAttributes: jsonOrNull(run.searchAttributes),
388
+ priority: run.priority ?? null,
383
389
  createdAt: run.createdAt,
384
390
  updatedAt: run.updatedAt
385
391
  };
@@ -399,6 +405,7 @@ function toRunPatch(patch) {
399
405
  if ("recoveryAttempts" in patch) data.recoveryAttempts = patch.recoveryAttempts ?? null;
400
406
  if ("tags" in patch) data.tags = jsonOrNull(patch.tags);
401
407
  if ("searchAttributes" in patch) data.searchAttributes = jsonOrNull(patch.searchAttributes);
408
+ if ("priority" in patch) data.priority = patch.priority ?? null;
402
409
  if (patch.createdAt != null) data.createdAt = patch.createdAt;
403
410
  if (patch.updatedAt != null) data.updatedAt = patch.updatedAt;
404
411
  return data;
@@ -419,6 +426,7 @@ function fromRunRow(row) {
419
426
  recoveryAttempts: row.recoveryAttempts ?? void 0,
420
427
  tags: row.tags ?? void 0,
421
428
  searchAttributes: row.searchAttributes ?? void 0,
429
+ priority: row.priority ?? void 0,
422
430
  createdAt: row.createdAt,
423
431
  updatedAt: row.updatedAt
424
432
  };
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/prisma-state-store.ts"],"sourcesContent":["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} from '@dudousxd/nestjs-durable-core';\n\n/* The Prisma client is generated per-schema, so the adapter can't import a concrete one. Instead\n it depends on this structural surface — the three model delegates and the methods it uses. A\n real `PrismaClient` (with the models from prisma/schema.prisma added) satisfies it. Query-arg\n shapes are Prisma's own generics, so they're left as `any` at this single boundary; the row\n return types are precise, which is what the mapping code below relies on. */\n\ninterface RunRow {\n id: string;\n workflow: string;\n workflowVersion: string;\n status: string;\n input: unknown;\n output: unknown;\n error: unknown;\n wakeAt: bigint | null;\n lockedBy: string | null;\n lockedUntil: Date | null;\n recoveryAttempts: number | null;\n tags: unknown;\n searchAttributes: unknown;\n createdAt: Date;\n updatedAt: Date;\n}\n\ninterface CheckpointRow {\n runId: string;\n seq: number;\n name: string;\n kind: string;\n stepId: string;\n status: string;\n input: unknown;\n output: unknown;\n error: unknown;\n events: unknown;\n attempts: number;\n workerGroup: string | null;\n wakeAt: bigint | null;\n enqueuedAt: Date | null;\n startedAt: Date;\n finishedAt: Date;\n}\n\ninterface WaiterRow {\n token: string;\n runId: string;\n seq: number;\n}\n\ninterface RunAttributeRow {\n runId: string;\n key: string;\n strValue: string | null;\n numValue: number | null;\n}\n\ninterface BufferedSignalRow {\n id: bigint;\n token: string;\n payload: unknown;\n}\n\n// Prisma's per-model query args are generated generics; left as `any` at this single boundary.\ntype Args = any;\n\ninterface Delegate<Row> {\n create(args: Args): Promise<Row>;\n createMany(args: Args): Promise<{ count: number }>;\n findUnique(args: Args): Promise<Row | null>;\n findFirst(args?: Args): Promise<Row | null>;\n findMany(args?: Args): Promise<Row[]>;\n update(args: Args): Promise<Row>;\n updateMany(args: Args): Promise<{ count: number }>;\n upsert(args: Args): Promise<Row>;\n delete(args: Args): Promise<Row>;\n deleteMany(args?: Args): Promise<{ count: number }>;\n}\n\nexport interface DurablePrismaTx {\n durableWorkflowRun: Delegate<RunRow>;\n durableStepCheckpoint: Delegate<CheckpointRow>;\n durableRunAttribute: Delegate<RunAttributeRow>;\n durableSignalWaiter: Delegate<WaiterRow>;\n durableBufferedSignal: Delegate<BufferedSignalRow>;\n}\n\nexport interface DurablePrismaClient extends DurablePrismaTx {\n /** Prisma's interactive-transaction form: runs `fn` with a tx-scoped client and commits on resolve. */\n $transaction<T>(fn: (tx: DurablePrismaTx) => Promise<T>): Promise<T>;\n}\n\n/**\n * Prisma-backed `StateStore`. Pass your `PrismaClient` after adding the models from\n * `prisma/schema.prisma` to your schema. JSON columns carry the run/step payloads directly;\n * `wakeAt` is a `BigInt` (epoch ms).\n */\nexport class PrismaStateStore implements StateStore {\n constructor(private readonly db: DurablePrismaClient) {}\n\n async createRun(run: WorkflowRun): Promise<void> {\n await this.db.durableWorkflowRun.create({ data: toRunData(run) });\n await this.reindexAttributes(run.id, run.searchAttributes);\n }\n\n async updateRun(runId: string, patch: Partial<WorkflowRun>): Promise<void> {\n await this.db.durableWorkflowRun.update({ where: { id: runId }, data: toRunPatch(patch) });\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 ): Promise<void> {\n await this.db.durableRunAttribute.deleteMany({ where: { runId } });\n const rows = normalizeAttributeRows(runId, attributes);\n if (rows.length) await this.db.durableRunAttribute.createMany({ data: rows });\n }\n\n async getRun(runId: string): Promise<WorkflowRun | null> {\n const row = await this.db.durableWorkflowRun.findUnique({ where: { id: runId } });\n return row ? fromRunRow(row) : null;\n }\n\n async deleteRun(runId: string): Promise<void> {\n // Child rows first, then the run — checkpoints, signal waiters, attribute rows.\n await this.db.durableStepCheckpoint.deleteMany({ where: { runId } });\n await this.db.durableSignalWaiter.deleteMany({ where: { runId } });\n await this.db.durableRunAttribute.deleteMany({ where: { runId } });\n await this.db.durableWorkflowRun.deleteMany({ where: { id: runId } });\n }\n\n async getCheckpoint(runId: string, seq: number): Promise<StepCheckpoint | null> {\n const row = await this.db.durableStepCheckpoint.findUnique({\n where: { runId_seq: { runId, seq } },\n });\n return row ? fromCheckpointRow(row) : null;\n }\n\n async saveCheckpoint(checkpoint: StepCheckpoint): Promise<void> {\n const data = toCheckpointData(checkpoint);\n await this.db.durableStepCheckpoint.upsert({\n where: { runId_seq: { runId: checkpoint.runId, seq: checkpoint.seq } },\n create: data,\n update: data,\n });\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.db.$transaction(async (tx) =>\n work({\n raw: tx,\n saveCheckpoint: async (cp) => {\n const data = toCheckpointData(cp);\n await tx.durableStepCheckpoint.upsert({\n where: { runId_seq: { runId: cp.runId, seq: cp.seq } },\n create: data,\n update: data,\n });\n },\n }),\n );\n }\n\n async listIncompleteRuns(): Promise<WorkflowRun[]> {\n const rows = await this.db.durableWorkflowRun.findMany({ where: { status: 'running' } });\n return rows.map(fromRunRow);\n }\n\n async listPendingRuns(limit: number): Promise<WorkflowRun[]> {\n const rows = await this.db.durableWorkflowRun.findMany({\n where: { status: 'pending' },\n orderBy: { createdAt: 'asc' }, // FIFO dispatch\n take: limit,\n });\n return rows.map(fromRunRow);\n }\n\n async listDueTimers(nowMs: number): Promise<WorkflowRun[]> {\n const rows = await this.db.durableWorkflowRun.findMany({\n where: { status: 'suspended', wakeAt: { not: null, lte: BigInt(nowMs) } },\n });\n return rows.map(fromRunRow);\n }\n\n async tryLockRun(\n runId: string,\n owner: string,\n leaseUntilMs: number,\n nowMs: number,\n ): Promise<boolean> {\n const result = await this.db.durableWorkflowRun.updateMany({\n where: {\n id: runId,\n OR: [{ lockedUntil: null }, { lockedUntil: { lte: new Date(nowMs) } }],\n },\n data: { lockedBy: owner, lockedUntil: new Date(leaseUntilMs) },\n });\n return result.count === 1;\n }\n\n async releaseRunLock(runId: string): Promise<void> {\n await this.db.durableWorkflowRun.update({\n where: { id: runId },\n data: { lockedBy: null, lockedUntil: null },\n });\n }\n\n async renewRunLock(runId: string, owner: string, leaseUntilMs: number): Promise<boolean> {\n const result = await this.db.durableWorkflowRun.updateMany({\n where: { id: runId, lockedBy: owner },\n data: { lockedUntil: new Date(leaseUntilMs) },\n });\n return result.count === 1;\n }\n\n async listRuns(query: RunQuery): Promise<WorkflowRun[]> {\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). Combined with the\n // single-value `status` via AND when both are present, 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 if (query.tag) where.tags = { array_contains: query.tag };\n // Typed/range attribute predicates push DOWN into SQL: each filter becomes a relation `some`\n // (EXISTS) on the normalized `durable_run_attributes` side-table, so the DB filters AND paginates\n // — no full scan + in-process filter. ANDed: a run must match every filter, so one `some` each.\n if (query.attributes?.length) {\n const existing = (where.AND as unknown[] | undefined) ?? [];\n where.AND = [...existing, ...query.attributes.map((f) => attributeSome(f))];\n }\n const orderBy = { createdAt: 'desc' as const }; // newest first — recent runs on top in the dashboard\n const rows = await this.db.durableWorkflowRun.findMany({\n where,\n take: query.limit,\n skip: query.offset,\n orderBy,\n });\n return rows.map(fromRunRow);\n }\n\n async listCheckpoints(runId: string): Promise<StepCheckpoint[]> {\n const rows = await this.db.durableStepCheckpoint.findMany({\n where: { runId },\n orderBy: { seq: 'asc' },\n });\n return rows.map(fromCheckpointRow);\n }\n\n async getLatestCheckpointByName(\n runId: string,\n name: string,\n ): Promise<StepCheckpoint | undefined> {\n const row = await this.db.durableStepCheckpoint.findFirst({\n where: { runId, name },\n orderBy: { seq: 'desc' },\n });\n return row ? fromCheckpointRow(row) : undefined;\n }\n\n async listCheckpointsByNamePrefix(runId: string, prefixes: string[]): Promise<StepCheckpoint[]> {\n if (prefixes.length === 0) return [];\n const rows = await this.db.durableStepCheckpoint.findMany({\n where: { runId, OR: prefixes.map((p) => ({ name: { startsWith: p } })) },\n orderBy: { seq: 'asc' },\n });\n return rows.map(fromCheckpointRow);\n }\n\n async putSignalWaiter(waiter: SignalWaiter): Promise<void> {\n await this.db.durableSignalWaiter.upsert({\n where: { token: waiter.token },\n create: { ...waiter },\n update: { runId: waiter.runId, seq: waiter.seq },\n });\n }\n\n async takeSignalWaiter(token: string): Promise<SignalWaiter | null> {\n const row = await this.db.durableSignalWaiter.findUnique({ where: { token } });\n if (!row) return null;\n await this.db.durableSignalWaiter.delete({ where: { token } });\n return { token: row.token, runId: row.runId, seq: row.seq };\n }\n\n async listSignalWaiters(prefix: string): Promise<SignalWaiter[]> {\n const rows = await this.db.durableSignalWaiter.findMany({\n where: { token: { startsWith: prefix } },\n });\n return rows.map((r) => ({ token: r.token, runId: r.runId, seq: r.seq }));\n }\n\n async bufferSignal(token: string, payload: unknown): Promise<void> {\n await this.db.durableBufferedSignal.create({ data: { token, payload: jsonOrNull(payload) } });\n }\n\n async takeBufferedSignal(token: string): Promise<{ payload: unknown } | null> {\n const row = await this.db.durableBufferedSignal.findFirst({\n where: { token },\n orderBy: { id: 'asc' },\n });\n if (!row) return null;\n await this.db.durableBufferedSignal.delete({ where: { id: row.id } });\n return { payload: row.payload ?? undefined };\n }\n}\n\n/**\n * One attribute predicate as a Prisma relation `some` filter on the side-table — compiles to an\n * EXISTS, so the predicate runs in SQL. `<>` (ne) maps to `{ not }`, which under `some` also excludes\n * runs where the attribute is absent (the missing-key-never-matches contract): `some` already\n * requires a matching row to exist. Numeric operands compare `numValue`, everything else `strValue`.\n */\nfunction attributeSome(f: AttributeFilter): { attributes: { some: Record<string, unknown> } } {\n const col = attributeColumnFor(f); // 'numValue' | 'strValue'\n const operand = attributeOperand(f);\n const condition =\n f.op === 'eq' ? operand : f.op === 'ne' ? { not: operand } : { [f.op]: operand }; // gt/gte/lt/lte map 1:1 to Prisma operators\n return { attributes: { some: { key: f.key, [col]: condition } } };\n}\n\nconst bigOrNull = (n: number | undefined) => (n == null ? null : BigInt(n));\nconst numOrUndef = (n: bigint | null) => (n == null ? undefined : Number(n));\nconst jsonOrNull = (v: unknown) => v ?? null;\n\nfunction toRunData(run: WorkflowRun) {\n return {\n id: run.id,\n workflow: run.workflow,\n workflowVersion: run.workflowVersion,\n status: run.status,\n input: jsonOrNull(run.input),\n output: jsonOrNull(run.output),\n error: jsonOrNull(run.error),\n wakeAt: bigOrNull(run.wakeAt),\n lockedBy: run.lockedBy ?? null,\n lockedUntil: run.lockedUntil == null ? null : new Date(run.lockedUntil),\n recoveryAttempts: run.recoveryAttempts ?? null,\n tags: jsonOrNull(run.tags),\n searchAttributes: jsonOrNull(run.searchAttributes),\n createdAt: run.createdAt,\n updatedAt: run.updatedAt,\n };\n}\n\nfunction toRunPatch(patch: Partial<WorkflowRun>) {\n // Map EVERY patchable field, using presence (`'x' in patch`) semantics for the nullable ones so a\n // patch can CLEAR a column (e.g. `{ error: undefined }` on completion sets it to NULL — matching\n // the TypeORM / MikroORM / in-memory stores). The two non-null Date fields use a defined-guard\n // since they are never cleared. Previously only 7 fields were mapped, so `updateRun({ tags })` /\n // `{ lockedBy }` / clearing `error` silently no-opped on this adapter.\n const data: Record<string, unknown> = {};\n if ('workflow' in patch) data.workflow = patch.workflow;\n if ('workflowVersion' in patch) data.workflowVersion = patch.workflowVersion;\n if ('status' in patch) data.status = patch.status;\n if ('input' in patch) data.input = jsonOrNull(patch.input);\n if ('output' in patch) data.output = jsonOrNull(patch.output);\n if ('error' in patch) data.error = jsonOrNull(patch.error);\n if ('wakeAt' in patch) data.wakeAt = bigOrNull(patch.wakeAt);\n if ('lockedBy' in patch) data.lockedBy = patch.lockedBy ?? null;\n if ('lockedUntil' in patch)\n data.lockedUntil = patch.lockedUntil == null ? null : new Date(patch.lockedUntil);\n if ('recoveryAttempts' in patch) data.recoveryAttempts = patch.recoveryAttempts ?? null;\n if ('tags' in patch) data.tags = jsonOrNull(patch.tags);\n if ('searchAttributes' in patch) data.searchAttributes = jsonOrNull(patch.searchAttributes);\n if (patch.createdAt != null) data.createdAt = patch.createdAt;\n if (patch.updatedAt != null) data.updatedAt = patch.updatedAt;\n return data;\n}\n\nfunction fromRunRow(row: RunRow): WorkflowRun {\n return {\n id: row.id,\n workflow: row.workflow,\n workflowVersion: row.workflowVersion,\n status: row.status as WorkflowRun['status'],\n input: row.input ?? undefined,\n output: row.output ?? undefined,\n error: (row.error ?? undefined) as StepError | undefined,\n wakeAt: numOrUndef(row.wakeAt),\n lockedBy: row.lockedBy ?? undefined,\n lockedUntil: row.lockedUntil == null ? undefined : row.lockedUntil.getTime(),\n recoveryAttempts: row.recoveryAttempts ?? undefined,\n tags: (row.tags as string[] | null) ?? undefined,\n searchAttributes:\n (row.searchAttributes as Record<string, string | number | boolean> | null) ?? undefined,\n createdAt: row.createdAt,\n updatedAt: row.updatedAt,\n };\n}\n\nfunction toCheckpointData(cp: StepCheckpoint) {\n return {\n runId: cp.runId,\n seq: cp.seq,\n name: cp.name,\n kind: cp.kind,\n stepId: cp.stepId,\n status: cp.status,\n input: jsonOrNull(cp.input),\n output: jsonOrNull(cp.output),\n error: jsonOrNull(cp.error),\n events: jsonOrNull(cp.events),\n attempts: cp.attempts,\n workerGroup: cp.workerGroup ?? null,\n wakeAt: bigOrNull(cp.wakeAt),\n enqueuedAt: cp.enqueuedAt,\n startedAt: cp.startedAt,\n finishedAt: cp.finishedAt,\n };\n}\n\nfunction fromCheckpointRow(row: CheckpointRow): StepCheckpoint {\n return {\n runId: row.runId,\n seq: row.seq,\n name: row.name,\n kind: row.kind as StepCheckpoint['kind'],\n stepId: row.stepId,\n status: row.status as StepCheckpoint['status'],\n input: row.input ?? undefined,\n output: row.output ?? undefined,\n error: (row.error ?? undefined) as StepError | undefined,\n events: (row.events ?? undefined) as StepEvent[] | undefined,\n attempts: row.attempts,\n workerGroup: row.workerGroup ?? undefined,\n wakeAt: numOrUndef(row.wakeAt),\n enqueuedAt: row.enqueuedAt ?? row.startedAt,\n startedAt: row.startedAt,\n finishedAt: row.finishedAt,\n };\n}\n"],"mappings":"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","names":["attributeColumnFor","attributeOperand","normalizeAttributeRows","PrismaStateStore","db","createRun","run","durableWorkflowRun","create","data","toRunData","reindexAttributes","id","searchAttributes","updateRun","runId","patch","update","where","toRunPatch","attributes","durableRunAttribute","deleteMany","rows","normalizeAttributeRows","length","createMany","getRun","row","findUnique","fromRunRow","deleteRun","durableStepCheckpoint","durableSignalWaiter","getCheckpoint","seq","runId_seq","fromCheckpointRow","saveCheckpoint","checkpoint","toCheckpointData","upsert","transaction","work","$transaction","tx","raw","cp","listIncompleteRuns","findMany","status","map","listPendingRuns","limit","orderBy","createdAt","take","listDueTimers","nowMs","wakeAt","not","lte","BigInt","tryLockRun","owner","leaseUntilMs","result","updateMany","OR","lockedUntil","Date","lockedBy","count","releaseRunLock","renewRunLock","listRuns","query","workflow","statuses","AND","in","tag","tags","array_contains","existing","f","attributeSome","skip","offset","listCheckpoints","getLatestCheckpointByName","name","findFirst","undefined","listCheckpointsByNamePrefix","prefixes","p","startsWith","putSignalWaiter","waiter","token","takeSignalWaiter","delete","listSignalWaiters","prefix","r","bufferSignal","payload","durableBufferedSignal","jsonOrNull","takeBufferedSignal","col","attributeColumnFor","operand","attributeOperand","condition","op","some","key","bigOrNull","n","numOrUndef","Number","v","workflowVersion","input","output","error","recoveryAttempts","updatedAt","getTime","kind","stepId","events","attempts","workerGroup","enqueuedAt","startedAt","finishedAt"]}
1
+ {"version":3,"sources":["../src/prisma-state-store.ts"],"sourcesContent":["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} from '@dudousxd/nestjs-durable-core';\n\n/* The Prisma client is generated per-schema, so the adapter can't import a concrete one. Instead\n it depends on this structural surface — the three model delegates and the methods it uses. A\n real `PrismaClient` (with the models from prisma/schema.prisma added) satisfies it. Query-arg\n shapes are Prisma's own generics, so they're left as `any` at this single boundary; the row\n return types are precise, which is what the mapping code below relies on. */\n\ninterface RunRow {\n id: string;\n workflow: string;\n workflowVersion: string;\n status: string;\n input: unknown;\n output: unknown;\n error: unknown;\n wakeAt: bigint | null;\n lockedBy: string | null;\n lockedUntil: Date | null;\n recoveryAttempts: number | null;\n tags: unknown;\n searchAttributes: unknown;\n priority: number | null;\n createdAt: Date;\n updatedAt: Date;\n}\n\ninterface CheckpointRow {\n runId: string;\n seq: number;\n name: string;\n kind: string;\n stepId: string;\n status: string;\n input: unknown;\n output: unknown;\n error: unknown;\n events: unknown;\n attempts: number;\n workerGroup: string | null;\n wakeAt: bigint | null;\n enqueuedAt: Date | null;\n startedAt: Date;\n finishedAt: Date;\n}\n\ninterface WaiterRow {\n token: string;\n runId: string;\n seq: number;\n}\n\ninterface RunAttributeRow {\n runId: string;\n key: string;\n strValue: string | null;\n numValue: number | null;\n}\n\ninterface BufferedSignalRow {\n id: bigint;\n token: string;\n payload: unknown;\n}\n\n// Prisma's per-model query args are generated generics; left as `any` at this single boundary.\ntype Args = any;\n\ninterface Delegate<Row> {\n create(args: Args): Promise<Row>;\n createMany(args: Args): Promise<{ count: number }>;\n findUnique(args: Args): Promise<Row | null>;\n findFirst(args?: Args): Promise<Row | null>;\n findMany(args?: Args): Promise<Row[]>;\n update(args: Args): Promise<Row>;\n updateMany(args: Args): Promise<{ count: number }>;\n upsert(args: Args): Promise<Row>;\n delete(args: Args): Promise<Row>;\n deleteMany(args?: Args): Promise<{ count: number }>;\n}\n\nexport interface DurablePrismaTx {\n durableWorkflowRun: Delegate<RunRow>;\n durableStepCheckpoint: Delegate<CheckpointRow>;\n durableRunAttribute: Delegate<RunAttributeRow>;\n durableSignalWaiter: Delegate<WaiterRow>;\n durableBufferedSignal: Delegate<BufferedSignalRow>;\n}\n\nexport interface DurablePrismaClient extends DurablePrismaTx {\n /** Prisma's interactive-transaction form: runs `fn` with a tx-scoped client and commits on resolve. */\n $transaction<T>(fn: (tx: DurablePrismaTx) => Promise<T>): Promise<T>;\n}\n\n/**\n * Prisma-backed `StateStore`. Pass your `PrismaClient` after adding the models from\n * `prisma/schema.prisma` to your schema. JSON columns carry the run/step payloads directly;\n * `wakeAt` is a `BigInt` (epoch ms).\n */\nexport class PrismaStateStore implements StateStore {\n constructor(private readonly db: DurablePrismaClient) {}\n\n async createRun(run: WorkflowRun): Promise<void> {\n await this.db.durableWorkflowRun.create({ data: toRunData(run) });\n await this.reindexAttributes(run.id, run.searchAttributes);\n }\n\n async updateRun(runId: string, patch: Partial<WorkflowRun>): Promise<void> {\n await this.db.durableWorkflowRun.update({ where: { id: runId }, data: toRunPatch(patch) });\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 ): Promise<void> {\n await this.db.durableRunAttribute.deleteMany({ where: { runId } });\n const rows = normalizeAttributeRows(runId, attributes);\n if (rows.length) await this.db.durableRunAttribute.createMany({ data: rows });\n }\n\n async getRun(runId: string): Promise<WorkflowRun | null> {\n const row = await this.db.durableWorkflowRun.findUnique({ where: { id: runId } });\n return row ? fromRunRow(row) : null;\n }\n\n async deleteRun(runId: string): Promise<void> {\n // Child rows first, then the run — checkpoints, signal waiters, attribute rows.\n await this.db.durableStepCheckpoint.deleteMany({ where: { runId } });\n await this.db.durableSignalWaiter.deleteMany({ where: { runId } });\n await this.db.durableRunAttribute.deleteMany({ where: { runId } });\n await this.db.durableWorkflowRun.deleteMany({ where: { id: runId } });\n }\n\n async getCheckpoint(runId: string, seq: number): Promise<StepCheckpoint | null> {\n const row = await this.db.durableStepCheckpoint.findUnique({\n where: { runId_seq: { runId, seq } },\n });\n return row ? fromCheckpointRow(row) : null;\n }\n\n async saveCheckpoint(checkpoint: StepCheckpoint): Promise<void> {\n const data = toCheckpointData(checkpoint);\n await this.db.durableStepCheckpoint.upsert({\n where: { runId_seq: { runId: checkpoint.runId, seq: checkpoint.seq } },\n create: data,\n update: data,\n });\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.db.$transaction(async (tx) =>\n work({\n raw: tx,\n saveCheckpoint: async (cp) => {\n const data = toCheckpointData(cp);\n await tx.durableStepCheckpoint.upsert({\n where: { runId_seq: { runId: cp.runId, seq: cp.seq } },\n create: data,\n update: data,\n });\n },\n }),\n );\n }\n\n async listIncompleteRuns(): Promise<WorkflowRun[]> {\n const rows = await this.db.durableWorkflowRun.findMany({\n where: { status: { in: ['running', 'cancelling'] } },\n });\n return rows.map(fromRunRow);\n }\n\n async listPendingRuns(limit: number): Promise<WorkflowRun[]> {\n const rows = await this.db.durableWorkflowRun.findMany({\n where: { status: 'pending' },\n orderBy: { createdAt: 'asc' }, // FIFO dispatch\n take: limit,\n });\n return rows.map(fromRunRow);\n }\n\n async listDueTimers(nowMs: number): Promise<WorkflowRun[]> {\n const rows = await this.db.durableWorkflowRun.findMany({\n where: { status: 'suspended', wakeAt: { not: null, lte: BigInt(nowMs) } },\n });\n return rows.map(fromRunRow);\n }\n\n async tryLockRun(\n runId: string,\n owner: string,\n leaseUntilMs: number,\n nowMs: number,\n ): Promise<boolean> {\n const result = await this.db.durableWorkflowRun.updateMany({\n where: {\n id: runId,\n OR: [{ lockedUntil: null }, { lockedUntil: { lte: new Date(nowMs) } }],\n },\n data: { lockedBy: owner, lockedUntil: new Date(leaseUntilMs) },\n });\n return result.count === 1;\n }\n\n async releaseRunLock(runId: string): Promise<void> {\n await this.db.durableWorkflowRun.update({\n where: { id: runId },\n data: { lockedBy: null, lockedUntil: null },\n });\n }\n\n async renewRunLock(runId: string, owner: string, leaseUntilMs: number): Promise<boolean> {\n const result = await this.db.durableWorkflowRun.updateMany({\n where: { id: runId, lockedBy: owner },\n data: { lockedUntil: new Date(leaseUntilMs) },\n });\n return result.count === 1;\n }\n\n async listRuns(query: RunQuery): Promise<WorkflowRun[]> {\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). Combined with the\n // single-value `status` via AND when both are present, 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 if (query.tag) where.tags = { array_contains: query.tag };\n // Typed/range attribute predicates push DOWN into SQL: each filter becomes a relation `some`\n // (EXISTS) on the normalized `durable_run_attributes` side-table, so the DB filters AND paginates\n // — no full scan + in-process filter. ANDed: a run must match every filter, so one `some` each.\n if (query.attributes?.length) {\n const existing = (where.AND as unknown[] | undefined) ?? [];\n where.AND = [...existing, ...query.attributes.map((f) => attributeSome(f))];\n }\n const orderBy = { createdAt: 'desc' as const }; // newest first — recent runs on top in the dashboard\n const rows = await this.db.durableWorkflowRun.findMany({\n where,\n take: query.limit,\n skip: query.offset,\n orderBy,\n });\n return rows.map(fromRunRow);\n }\n\n async listCheckpoints(runId: string): Promise<StepCheckpoint[]> {\n const rows = await this.db.durableStepCheckpoint.findMany({\n where: { runId },\n orderBy: { seq: 'asc' },\n });\n return rows.map(fromCheckpointRow);\n }\n\n async getLatestCheckpointByName(\n runId: string,\n name: string,\n ): Promise<StepCheckpoint | undefined> {\n const row = await this.db.durableStepCheckpoint.findFirst({\n where: { runId, name },\n orderBy: { seq: 'desc' },\n });\n return row ? fromCheckpointRow(row) : undefined;\n }\n\n async listCheckpointsByNamePrefix(runId: string, prefixes: string[]): Promise<StepCheckpoint[]> {\n if (prefixes.length === 0) return [];\n const rows = await this.db.durableStepCheckpoint.findMany({\n where: { runId, OR: prefixes.map((p) => ({ name: { startsWith: p } })) },\n orderBy: { seq: 'asc' },\n });\n return rows.map(fromCheckpointRow);\n }\n\n async putSignalWaiter(waiter: SignalWaiter): Promise<void> {\n await this.db.durableSignalWaiter.upsert({\n where: { token: waiter.token },\n create: { ...waiter },\n update: { runId: waiter.runId, seq: waiter.seq },\n });\n }\n\n async takeSignalWaiter(token: string): Promise<SignalWaiter | null> {\n const row = await this.db.durableSignalWaiter.findUnique({ where: { token } });\n if (!row) return null;\n await this.db.durableSignalWaiter.delete({ where: { token } });\n return { token: row.token, runId: row.runId, seq: row.seq };\n }\n\n async listSignalWaiters(prefix: string): Promise<SignalWaiter[]> {\n const rows = await this.db.durableSignalWaiter.findMany({\n where: { token: { startsWith: prefix } },\n });\n return rows.map((r) => ({ token: r.token, runId: r.runId, seq: r.seq }));\n }\n\n async bufferSignal(token: string, payload: unknown): Promise<void> {\n await this.db.durableBufferedSignal.create({ data: { token, payload: jsonOrNull(payload) } });\n }\n\n async takeBufferedSignal(token: string): Promise<{ payload: unknown } | null> {\n const row = await this.db.durableBufferedSignal.findFirst({\n where: { token },\n orderBy: { id: 'asc' },\n });\n if (!row) return null;\n await this.db.durableBufferedSignal.delete({ where: { id: row.id } });\n return { payload: row.payload ?? undefined };\n }\n}\n\n/**\n * One attribute predicate as a Prisma relation `some` filter on the side-table — compiles to an\n * EXISTS, so the predicate runs in SQL. `<>` (ne) maps to `{ not }`, which under `some` also excludes\n * runs where the attribute is absent (the missing-key-never-matches contract): `some` already\n * requires a matching row to exist. Numeric operands compare `numValue`, everything else `strValue`.\n */\nfunction attributeSome(f: AttributeFilter): { attributes: { some: Record<string, unknown> } } {\n const col = attributeColumnFor(f); // 'numValue' | 'strValue'\n const operand = attributeOperand(f);\n const condition =\n f.op === 'eq' ? operand : f.op === 'ne' ? { not: operand } : { [f.op]: operand }; // gt/gte/lt/lte map 1:1 to Prisma operators\n return { attributes: { some: { key: f.key, [col]: condition } } };\n}\n\nconst bigOrNull = (n: number | undefined) => (n == null ? null : BigInt(n));\nconst numOrUndef = (n: bigint | null) => (n == null ? undefined : Number(n));\nconst jsonOrNull = (v: unknown) => v ?? null;\n\nfunction toRunData(run: WorkflowRun) {\n return {\n id: run.id,\n workflow: run.workflow,\n workflowVersion: run.workflowVersion,\n status: run.status,\n input: jsonOrNull(run.input),\n output: jsonOrNull(run.output),\n error: jsonOrNull(run.error),\n wakeAt: bigOrNull(run.wakeAt),\n lockedBy: run.lockedBy ?? null,\n lockedUntil: run.lockedUntil == null ? null : new Date(run.lockedUntil),\n recoveryAttempts: run.recoveryAttempts ?? null,\n tags: jsonOrNull(run.tags),\n searchAttributes: jsonOrNull(run.searchAttributes),\n priority: run.priority ?? null,\n createdAt: run.createdAt,\n updatedAt: run.updatedAt,\n };\n}\n\nfunction toRunPatch(patch: Partial<WorkflowRun>) {\n // Map EVERY patchable field, using presence (`'x' in patch`) semantics for the nullable ones so a\n // patch can CLEAR a column (e.g. `{ error: undefined }` on completion sets it to NULL — matching\n // the TypeORM / MikroORM / in-memory stores). The two non-null Date fields use a defined-guard\n // since they are never cleared. Previously only 7 fields were mapped, so `updateRun({ tags })` /\n // `{ lockedBy }` / clearing `error` silently no-opped on this adapter.\n const data: Record<string, unknown> = {};\n if ('workflow' in patch) data.workflow = patch.workflow;\n if ('workflowVersion' in patch) data.workflowVersion = patch.workflowVersion;\n if ('status' in patch) data.status = patch.status;\n if ('input' in patch) data.input = jsonOrNull(patch.input);\n if ('output' in patch) data.output = jsonOrNull(patch.output);\n if ('error' in patch) data.error = jsonOrNull(patch.error);\n if ('wakeAt' in patch) data.wakeAt = bigOrNull(patch.wakeAt);\n if ('lockedBy' in patch) data.lockedBy = patch.lockedBy ?? null;\n if ('lockedUntil' in patch)\n data.lockedUntil = patch.lockedUntil == null ? null : new Date(patch.lockedUntil);\n if ('recoveryAttempts' in patch) data.recoveryAttempts = patch.recoveryAttempts ?? null;\n if ('tags' in patch) data.tags = jsonOrNull(patch.tags);\n if ('searchAttributes' in patch) data.searchAttributes = jsonOrNull(patch.searchAttributes);\n if ('priority' in patch) data.priority = patch.priority ?? null;\n if (patch.createdAt != null) data.createdAt = patch.createdAt;\n if (patch.updatedAt != null) data.updatedAt = patch.updatedAt;\n return data;\n}\n\nfunction fromRunRow(row: RunRow): WorkflowRun {\n return {\n id: row.id,\n workflow: row.workflow,\n workflowVersion: row.workflowVersion,\n status: row.status as WorkflowRun['status'],\n input: row.input ?? undefined,\n output: row.output ?? undefined,\n error: (row.error ?? undefined) as StepError | undefined,\n wakeAt: numOrUndef(row.wakeAt),\n lockedBy: row.lockedBy ?? undefined,\n lockedUntil: row.lockedUntil == null ? undefined : row.lockedUntil.getTime(),\n recoveryAttempts: row.recoveryAttempts ?? undefined,\n tags: (row.tags as string[] | null) ?? undefined,\n searchAttributes:\n (row.searchAttributes as Record<string, string | number | boolean> | null) ?? undefined,\n priority: row.priority ?? undefined,\n createdAt: row.createdAt,\n updatedAt: row.updatedAt,\n };\n}\n\nfunction toCheckpointData(cp: StepCheckpoint) {\n return {\n runId: cp.runId,\n seq: cp.seq,\n name: cp.name,\n kind: cp.kind,\n stepId: cp.stepId,\n status: cp.status,\n input: jsonOrNull(cp.input),\n output: jsonOrNull(cp.output),\n error: jsonOrNull(cp.error),\n events: jsonOrNull(cp.events),\n attempts: cp.attempts,\n workerGroup: cp.workerGroup ?? null,\n wakeAt: bigOrNull(cp.wakeAt),\n enqueuedAt: cp.enqueuedAt,\n startedAt: cp.startedAt,\n finishedAt: cp.finishedAt,\n };\n}\n\nfunction fromCheckpointRow(row: CheckpointRow): StepCheckpoint {\n return {\n runId: row.runId,\n seq: row.seq,\n name: row.name,\n kind: row.kind as StepCheckpoint['kind'],\n stepId: row.stepId,\n status: row.status as StepCheckpoint['status'],\n input: row.input ?? undefined,\n output: row.output ?? undefined,\n error: (row.error ?? undefined) as StepError | undefined,\n events: (row.events ?? undefined) as StepEvent[] | undefined,\n attempts: row.attempts,\n workerGroup: row.workerGroup ?? undefined,\n wakeAt: numOrUndef(row.wakeAt),\n enqueuedAt: row.enqueuedAt ?? row.startedAt,\n startedAt: row.startedAt,\n finishedAt: row.finishedAt,\n };\n}\n"],"mappings":";;;;AAAA,SASEA,oBACAC,kBACAC,8BACK;AAmGA,IAAMC,mBAAN,MAAMA;EA/Gb,OA+GaA;;;;EACX,YAA6BC,IAAyB;SAAzBA,KAAAA;EAA0B;EAEvD,MAAMC,UAAUC,KAAiC;AAC/C,UAAM,KAAKF,GAAGG,mBAAmBC,OAAO;MAAEC,MAAMC,UAAUJ,GAAAA;IAAK,CAAA;AAC/D,UAAM,KAAKK,kBAAkBL,IAAIM,IAAIN,IAAIO,gBAAgB;EAC3D;EAEA,MAAMC,UAAUC,OAAeC,OAA4C;AACzE,UAAM,KAAKZ,GAAGG,mBAAmBU,OAAO;MAAEC,OAAO;QAAEN,IAAIG;MAAM;MAAGN,MAAMU,WAAWH,KAAAA;IAAO,CAAA;AAExF,QAAI,sBAAsBA,MAAO,OAAM,KAAKL,kBAAkBI,OAAOC,MAAMH,gBAAgB;EAC7F;;;EAIA,MAAcF,kBACZI,OACAK,YACe;AACf,UAAM,KAAKhB,GAAGiB,oBAAoBC,WAAW;MAAEJ,OAAO;QAAEH;MAAM;IAAE,CAAA;AAChE,UAAMQ,OAAOC,uBAAuBT,OAAOK,UAAAA;AAC3C,QAAIG,KAAKE,OAAQ,OAAM,KAAKrB,GAAGiB,oBAAoBK,WAAW;MAAEjB,MAAMc;IAAK,CAAA;EAC7E;EAEA,MAAMI,OAAOZ,OAA4C;AACvD,UAAMa,MAAM,MAAM,KAAKxB,GAAGG,mBAAmBsB,WAAW;MAAEX,OAAO;QAAEN,IAAIG;MAAM;IAAE,CAAA;AAC/E,WAAOa,MAAME,WAAWF,GAAAA,IAAO;EACjC;EAEA,MAAMG,UAAUhB,OAA8B;AAE5C,UAAM,KAAKX,GAAG4B,sBAAsBV,WAAW;MAAEJ,OAAO;QAAEH;MAAM;IAAE,CAAA;AAClE,UAAM,KAAKX,GAAG6B,oBAAoBX,WAAW;MAAEJ,OAAO;QAAEH;MAAM;IAAE,CAAA;AAChE,UAAM,KAAKX,GAAGiB,oBAAoBC,WAAW;MAAEJ,OAAO;QAAEH;MAAM;IAAE,CAAA;AAChE,UAAM,KAAKX,GAAGG,mBAAmBe,WAAW;MAAEJ,OAAO;QAAEN,IAAIG;MAAM;IAAE,CAAA;EACrE;EAEA,MAAMmB,cAAcnB,OAAeoB,KAA6C;AAC9E,UAAMP,MAAM,MAAM,KAAKxB,GAAG4B,sBAAsBH,WAAW;MACzDX,OAAO;QAAEkB,WAAW;UAAErB;UAAOoB;QAAI;MAAE;IACrC,CAAA;AACA,WAAOP,MAAMS,kBAAkBT,GAAAA,IAAO;EACxC;EAEA,MAAMU,eAAeC,YAA2C;AAC9D,UAAM9B,OAAO+B,iBAAiBD,UAAAA;AAC9B,UAAM,KAAKnC,GAAG4B,sBAAsBS,OAAO;MACzCvB,OAAO;QAAEkB,WAAW;UAAErB,OAAOwB,WAAWxB;UAAOoB,KAAKI,WAAWJ;QAAI;MAAE;MACrE3B,QAAQC;MACRQ,QAAQR;IACV,CAAA;EACF;EAEA,MAAMiC,YACJC,MAIY;AACZ,WAAO,KAAKvC,GAAGwC,aAAa,OAAOC,OACjCF,KAAK;MACHG,KAAKD;MACLP,gBAAgB,8BAAOS,OAAAA;AACrB,cAAMtC,OAAO+B,iBAAiBO,EAAAA;AAC9B,cAAMF,GAAGb,sBAAsBS,OAAO;UACpCvB,OAAO;YAAEkB,WAAW;cAAErB,OAAOgC,GAAGhC;cAAOoB,KAAKY,GAAGZ;YAAI;UAAE;UACrD3B,QAAQC;UACRQ,QAAQR;QACV,CAAA;MACF,GAPgB;IAQlB,CAAA,CAAA;EAEJ;EAEA,MAAMuC,qBAA6C;AACjD,UAAMzB,OAAO,MAAM,KAAKnB,GAAGG,mBAAmB0C,SAAS;MACrD/B,OAAO;QAAEgC,QAAQ;UAAEC,IAAI;YAAC;YAAW;;QAAc;MAAE;IACrD,CAAA;AACA,WAAO5B,KAAK6B,IAAItB,UAAAA;EAClB;EAEA,MAAMuB,gBAAgBC,OAAuC;AAC3D,UAAM/B,OAAO,MAAM,KAAKnB,GAAGG,mBAAmB0C,SAAS;MACrD/B,OAAO;QAAEgC,QAAQ;MAAU;MAC3BK,SAAS;QAAEC,WAAW;MAAM;MAC5BC,MAAMH;IACR,CAAA;AACA,WAAO/B,KAAK6B,IAAItB,UAAAA;EAClB;EAEA,MAAM4B,cAAcC,OAAuC;AACzD,UAAMpC,OAAO,MAAM,KAAKnB,GAAGG,mBAAmB0C,SAAS;MACrD/B,OAAO;QAAEgC,QAAQ;QAAaU,QAAQ;UAAEC,KAAK;UAAMC,KAAKC,OAAOJ,KAAAA;QAAO;MAAE;IAC1E,CAAA;AACA,WAAOpC,KAAK6B,IAAItB,UAAAA;EAClB;EAEA,MAAMkC,WACJjD,OACAkD,OACAC,cACAP,OACkB;AAClB,UAAMQ,SAAS,MAAM,KAAK/D,GAAGG,mBAAmB6D,WAAW;MACzDlD,OAAO;QACLN,IAAIG;QACJsD,IAAI;UAAC;YAAEC,aAAa;UAAK;UAAG;YAAEA,aAAa;cAAER,KAAK,IAAIS,KAAKZ,KAAAA;YAAO;UAAE;;MACtE;MACAlD,MAAM;QAAE+D,UAAUP;QAAOK,aAAa,IAAIC,KAAKL,YAAAA;MAAc;IAC/D,CAAA;AACA,WAAOC,OAAOM,UAAU;EAC1B;EAEA,MAAMC,eAAe3D,OAA8B;AACjD,UAAM,KAAKX,GAAGG,mBAAmBU,OAAO;MACtCC,OAAO;QAAEN,IAAIG;MAAM;MACnBN,MAAM;QAAE+D,UAAU;QAAMF,aAAa;MAAK;IAC5C,CAAA;EACF;EAEA,MAAMK,aAAa5D,OAAekD,OAAeC,cAAwC;AACvF,UAAMC,SAAS,MAAM,KAAK/D,GAAGG,mBAAmB6D,WAAW;MACzDlD,OAAO;QAAEN,IAAIG;QAAOyD,UAAUP;MAAM;MACpCxD,MAAM;QAAE6D,aAAa,IAAIC,KAAKL,YAAAA;MAAc;IAC9C,CAAA;AACA,WAAOC,OAAOM,UAAU;EAC1B;EAEA,MAAMG,SAASC,OAAyC;AACtD,UAAM3D,QAAiC,CAAC;AACxC,QAAI2D,MAAMC,SAAU5D,OAAM4D,WAAWD,MAAMC;AAG3C,QAAID,MAAM3B,UAAU2B,MAAME,UAAU;AAClC7D,YAAM8D,MAAM;QAAC;UAAE9B,QAAQ2B,MAAM3B;QAAO;QAAG;UAAEA,QAAQ;YAAEC,IAAI0B,MAAME;UAAS;QAAE;;IAC1E,WAAWF,MAAM3B,QAAQ;AACvBhC,YAAMgC,SAAS2B,MAAM3B;IACvB,WAAW2B,MAAME,UAAU;AACzB7D,YAAMgC,SAAS;QAAEC,IAAI0B,MAAME;MAAS;IACtC;AACA,QAAIF,MAAMI,IAAK/D,OAAMgE,OAAO;MAAEC,gBAAgBN,MAAMI;IAAI;AAIxD,QAAIJ,MAAMzD,YAAYK,QAAQ;AAC5B,YAAM2D,WAAYlE,MAAM8D,OAAiC,CAAA;AACzD9D,YAAM8D,MAAM;WAAII;WAAaP,MAAMzD,WAAWgC,IAAI,CAACiC,MAAMC,cAAcD,CAAAA,CAAAA;;IACzE;AACA,UAAM9B,UAAU;MAAEC,WAAW;IAAgB;AAC7C,UAAMjC,OAAO,MAAM,KAAKnB,GAAGG,mBAAmB0C,SAAS;MACrD/B;MACAuC,MAAMoB,MAAMvB;MACZiC,MAAMV,MAAMW;MACZjC;IACF,CAAA;AACA,WAAOhC,KAAK6B,IAAItB,UAAAA;EAClB;EAEA,MAAM2D,gBAAgB1E,OAA0C;AAC9D,UAAMQ,OAAO,MAAM,KAAKnB,GAAG4B,sBAAsBiB,SAAS;MACxD/B,OAAO;QAAEH;MAAM;MACfwC,SAAS;QAAEpB,KAAK;MAAM;IACxB,CAAA;AACA,WAAOZ,KAAK6B,IAAIf,iBAAAA;EAClB;EAEA,MAAMqD,0BACJ3E,OACA4E,MACqC;AACrC,UAAM/D,MAAM,MAAM,KAAKxB,GAAG4B,sBAAsB4D,UAAU;MACxD1E,OAAO;QAAEH;QAAO4E;MAAK;MACrBpC,SAAS;QAAEpB,KAAK;MAAO;IACzB,CAAA;AACA,WAAOP,MAAMS,kBAAkBT,GAAAA,IAAOiE;EACxC;EAEA,MAAMC,4BAA4B/E,OAAegF,UAA+C;AAC9F,QAAIA,SAAStE,WAAW,EAAG,QAAO,CAAA;AAClC,UAAMF,OAAO,MAAM,KAAKnB,GAAG4B,sBAAsBiB,SAAS;MACxD/B,OAAO;QAAEH;QAAOsD,IAAI0B,SAAS3C,IAAI,CAAC4C,OAAO;UAAEL,MAAM;YAAEM,YAAYD;UAAE;QAAE,EAAA;MAAI;MACvEzC,SAAS;QAAEpB,KAAK;MAAM;IACxB,CAAA;AACA,WAAOZ,KAAK6B,IAAIf,iBAAAA;EAClB;EAEA,MAAM6D,gBAAgBC,QAAqC;AACzD,UAAM,KAAK/F,GAAG6B,oBAAoBQ,OAAO;MACvCvB,OAAO;QAAEkF,OAAOD,OAAOC;MAAM;MAC7B5F,QAAQ;QAAE,GAAG2F;MAAO;MACpBlF,QAAQ;QAAEF,OAAOoF,OAAOpF;QAAOoB,KAAKgE,OAAOhE;MAAI;IACjD,CAAA;EACF;EAEA,MAAMkE,iBAAiBD,OAA6C;AAClE,UAAMxE,MAAM,MAAM,KAAKxB,GAAG6B,oBAAoBJ,WAAW;MAAEX,OAAO;QAAEkF;MAAM;IAAE,CAAA;AAC5E,QAAI,CAACxE,IAAK,QAAO;AACjB,UAAM,KAAKxB,GAAG6B,oBAAoBqE,OAAO;MAAEpF,OAAO;QAAEkF;MAAM;IAAE,CAAA;AAC5D,WAAO;MAAEA,OAAOxE,IAAIwE;MAAOrF,OAAOa,IAAIb;MAAOoB,KAAKP,IAAIO;IAAI;EAC5D;EAEA,MAAMoE,kBAAkBC,QAAyC;AAC/D,UAAMjF,OAAO,MAAM,KAAKnB,GAAG6B,oBAAoBgB,SAAS;MACtD/B,OAAO;QAAEkF,OAAO;UAAEH,YAAYO;QAAO;MAAE;IACzC,CAAA;AACA,WAAOjF,KAAK6B,IAAI,CAACqD,OAAO;MAAEL,OAAOK,EAAEL;MAAOrF,OAAO0F,EAAE1F;MAAOoB,KAAKsE,EAAEtE;IAAI,EAAA;EACvE;EAEA,MAAMuE,aAAaN,OAAeO,SAAiC;AACjE,UAAM,KAAKvG,GAAGwG,sBAAsBpG,OAAO;MAAEC,MAAM;QAAE2F;QAAOO,SAASE,WAAWF,OAAAA;MAAS;IAAE,CAAA;EAC7F;EAEA,MAAMG,mBAAmBV,OAAqD;AAC5E,UAAMxE,MAAM,MAAM,KAAKxB,GAAGwG,sBAAsBhB,UAAU;MACxD1E,OAAO;QAAEkF;MAAM;MACf7C,SAAS;QAAE3C,IAAI;MAAM;IACvB,CAAA;AACA,QAAI,CAACgB,IAAK,QAAO;AACjB,UAAM,KAAKxB,GAAGwG,sBAAsBN,OAAO;MAAEpF,OAAO;QAAEN,IAAIgB,IAAIhB;MAAG;IAAE,CAAA;AACnE,WAAO;MAAE+F,SAAS/E,IAAI+E,WAAWd;IAAU;EAC7C;AACF;AAQA,SAASP,cAAcD,GAAkB;AACvC,QAAM0B,MAAMC,mBAAmB3B,CAAAA;AAC/B,QAAM4B,UAAUC,iBAAiB7B,CAAAA;AACjC,QAAM8B,YACJ9B,EAAE+B,OAAO,OAAOH,UAAU5B,EAAE+B,OAAO,OAAO;IAAEvD,KAAKoD;EAAQ,IAAI;IAAE,CAAC5B,EAAE+B,EAAE,GAAGH;EAAQ;AACjF,SAAO;IAAE7F,YAAY;MAAEiG,MAAM;QAAEC,KAAKjC,EAAEiC;QAAK,CAACP,GAAAA,GAAMI;MAAU;IAAE;EAAE;AAClE;AANS7B;AAQT,IAAMiC,YAAY,wBAACC,MAA2BA,KAAK,OAAO,OAAOzD,OAAOyD,CAAAA,GAAtD;AAClB,IAAMC,aAAa,wBAACD,MAAsBA,KAAK,OAAO3B,SAAY6B,OAAOF,CAAAA,GAAtD;AACnB,IAAMX,aAAa,wBAACc,MAAeA,KAAK,MAArB;AAEnB,SAASjH,UAAUJ,KAAgB;AACjC,SAAO;IACLM,IAAIN,IAAIM;IACRkE,UAAUxE,IAAIwE;IACd8C,iBAAiBtH,IAAIsH;IACrB1E,QAAQ5C,IAAI4C;IACZ2E,OAAOhB,WAAWvG,IAAIuH,KAAK;IAC3BC,QAAQjB,WAAWvG,IAAIwH,MAAM;IAC7BC,OAAOlB,WAAWvG,IAAIyH,KAAK;IAC3BnE,QAAQ2D,UAAUjH,IAAIsD,MAAM;IAC5BY,UAAUlE,IAAIkE,YAAY;IAC1BF,aAAahE,IAAIgE,eAAe,OAAO,OAAO,IAAIC,KAAKjE,IAAIgE,WAAW;IACtE0D,kBAAkB1H,IAAI0H,oBAAoB;IAC1C9C,MAAM2B,WAAWvG,IAAI4E,IAAI;IACzBrE,kBAAkBgG,WAAWvG,IAAIO,gBAAgB;IACjDoH,UAAU3H,IAAI2H,YAAY;IAC1BzE,WAAWlD,IAAIkD;IACf0E,WAAW5H,IAAI4H;EACjB;AACF;AAnBSxH;AAqBT,SAASS,WAAWH,OAA2B;AAM7C,QAAMP,OAAgC,CAAC;AACvC,MAAI,cAAcO,MAAOP,MAAKqE,WAAW9D,MAAM8D;AAC/C,MAAI,qBAAqB9D,MAAOP,MAAKmH,kBAAkB5G,MAAM4G;AAC7D,MAAI,YAAY5G,MAAOP,MAAKyC,SAASlC,MAAMkC;AAC3C,MAAI,WAAWlC,MAAOP,MAAKoH,QAAQhB,WAAW7F,MAAM6G,KAAK;AACzD,MAAI,YAAY7G,MAAOP,MAAKqH,SAASjB,WAAW7F,MAAM8G,MAAM;AAC5D,MAAI,WAAW9G,MAAOP,MAAKsH,QAAQlB,WAAW7F,MAAM+G,KAAK;AACzD,MAAI,YAAY/G,MAAOP,MAAKmD,SAAS2D,UAAUvG,MAAM4C,MAAM;AAC3D,MAAI,cAAc5C,MAAOP,MAAK+D,WAAWxD,MAAMwD,YAAY;AAC3D,MAAI,iBAAiBxD,MACnBP,MAAK6D,cAActD,MAAMsD,eAAe,OAAO,OAAO,IAAIC,KAAKvD,MAAMsD,WAAW;AAClF,MAAI,sBAAsBtD,MAAOP,MAAKuH,mBAAmBhH,MAAMgH,oBAAoB;AACnF,MAAI,UAAUhH,MAAOP,MAAKyE,OAAO2B,WAAW7F,MAAMkE,IAAI;AACtD,MAAI,sBAAsBlE,MAAOP,MAAKI,mBAAmBgG,WAAW7F,MAAMH,gBAAgB;AAC1F,MAAI,cAAcG,MAAOP,MAAKwH,WAAWjH,MAAMiH,YAAY;AAC3D,MAAIjH,MAAMwC,aAAa,KAAM/C,MAAK+C,YAAYxC,MAAMwC;AACpD,MAAIxC,MAAMkH,aAAa,KAAMzH,MAAKyH,YAAYlH,MAAMkH;AACpD,SAAOzH;AACT;AAxBSU;AA0BT,SAASW,WAAWF,KAAW;AAC7B,SAAO;IACLhB,IAAIgB,IAAIhB;IACRkE,UAAUlD,IAAIkD;IACd8C,iBAAiBhG,IAAIgG;IACrB1E,QAAQtB,IAAIsB;IACZ2E,OAAOjG,IAAIiG,SAAShC;IACpBiC,QAAQlG,IAAIkG,UAAUjC;IACtBkC,OAAQnG,IAAImG,SAASlC;IACrBjC,QAAQ6D,WAAW7F,IAAIgC,MAAM;IAC7BY,UAAU5C,IAAI4C,YAAYqB;IAC1BvB,aAAa1C,IAAI0C,eAAe,OAAOuB,SAAYjE,IAAI0C,YAAY6D,QAAO;IAC1EH,kBAAkBpG,IAAIoG,oBAAoBnC;IAC1CX,MAAOtD,IAAIsD,QAA4BW;IACvChF,kBACGe,IAAIf,oBAAyEgF;IAChFoC,UAAUrG,IAAIqG,YAAYpC;IAC1BrC,WAAW5B,IAAI4B;IACf0E,WAAWtG,IAAIsG;EACjB;AACF;AApBSpG;AAsBT,SAASU,iBAAiBO,IAAkB;AAC1C,SAAO;IACLhC,OAAOgC,GAAGhC;IACVoB,KAAKY,GAAGZ;IACRwD,MAAM5C,GAAG4C;IACTyC,MAAMrF,GAAGqF;IACTC,QAAQtF,GAAGsF;IACXnF,QAAQH,GAAGG;IACX2E,OAAOhB,WAAW9D,GAAG8E,KAAK;IAC1BC,QAAQjB,WAAW9D,GAAG+E,MAAM;IAC5BC,OAAOlB,WAAW9D,GAAGgF,KAAK;IAC1BO,QAAQzB,WAAW9D,GAAGuF,MAAM;IAC5BC,UAAUxF,GAAGwF;IACbC,aAAazF,GAAGyF,eAAe;IAC/B5E,QAAQ2D,UAAUxE,GAAGa,MAAM;IAC3B6E,YAAY1F,GAAG0F;IACfC,WAAW3F,GAAG2F;IACdC,YAAY5F,GAAG4F;EACjB;AACF;AAnBSnG;AAqBT,SAASH,kBAAkBT,KAAkB;AAC3C,SAAO;IACLb,OAAOa,IAAIb;IACXoB,KAAKP,IAAIO;IACTwD,MAAM/D,IAAI+D;IACVyC,MAAMxG,IAAIwG;IACVC,QAAQzG,IAAIyG;IACZnF,QAAQtB,IAAIsB;IACZ2E,OAAOjG,IAAIiG,SAAShC;IACpBiC,QAAQlG,IAAIkG,UAAUjC;IACtBkC,OAAQnG,IAAImG,SAASlC;IACrByC,QAAS1G,IAAI0G,UAAUzC;IACvB0C,UAAU3G,IAAI2G;IACdC,aAAa5G,IAAI4G,eAAe3C;IAChCjC,QAAQ6D,WAAW7F,IAAIgC,MAAM;IAC7B6E,YAAY7G,IAAI6G,cAAc7G,IAAI8G;IAClCA,WAAW9G,IAAI8G;IACfC,YAAY/G,IAAI+G;EAClB;AACF;AAnBStG;","names":["attributeColumnFor","attributeOperand","normalizeAttributeRows","PrismaStateStore","db","createRun","run","durableWorkflowRun","create","data","toRunData","reindexAttributes","id","searchAttributes","updateRun","runId","patch","update","where","toRunPatch","attributes","durableRunAttribute","deleteMany","rows","normalizeAttributeRows","length","createMany","getRun","row","findUnique","fromRunRow","deleteRun","durableStepCheckpoint","durableSignalWaiter","getCheckpoint","seq","runId_seq","fromCheckpointRow","saveCheckpoint","checkpoint","toCheckpointData","upsert","transaction","work","$transaction","tx","raw","cp","listIncompleteRuns","findMany","status","in","map","listPendingRuns","limit","orderBy","createdAt","take","listDueTimers","nowMs","wakeAt","not","lte","BigInt","tryLockRun","owner","leaseUntilMs","result","updateMany","OR","lockedUntil","Date","lockedBy","count","releaseRunLock","renewRunLock","listRuns","query","workflow","statuses","AND","tag","tags","array_contains","existing","f","attributeSome","skip","offset","listCheckpoints","getLatestCheckpointByName","name","findFirst","undefined","listCheckpointsByNamePrefix","prefixes","p","startsWith","putSignalWaiter","waiter","token","takeSignalWaiter","delete","listSignalWaiters","prefix","r","bufferSignal","payload","durableBufferedSignal","jsonOrNull","takeBufferedSignal","col","attributeColumnFor","operand","attributeOperand","condition","op","some","key","bigOrNull","n","numOrUndef","Number","v","workflowVersion","input","output","error","recoveryAttempts","priority","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-prisma",
3
- "version": "0.10.0",
3
+ "version": "0.11.1",
4
4
  "description": "Prisma adapter for the nestjs-durable StateStore",
5
5
  "license": "MIT",
6
6
  "author": "Davide Carvalho",
@@ -26,8 +26,8 @@
26
26
  "prisma": "6.19.3",
27
27
  "typescript": "5.9.3",
28
28
  "tsup": "8.3.5",
29
- "@dudousxd/nestjs-durable-core": "^0.30.0",
30
- "@dudousxd/nestjs-durable-testing": "^0.6.0"
29
+ "@dudousxd/nestjs-durable-core": "^0.35.0",
30
+ "@dudousxd/nestjs-durable-testing": "^0.7.0"
31
31
  },
32
32
  "module": "./dist/index.js",
33
33
  "exports": {
@@ -15,6 +15,7 @@ model DurableWorkflowRun {
15
15
  recoveryAttempts Int? @map("recovery_attempts")
16
16
  tags Json?
17
17
  searchAttributes Json? @map("search_attributes")
18
+ priority Int? @map("priority")
18
19
  createdAt DateTime @map("created_at")
19
20
  updatedAt DateTime @map("updated_at")
20
21